开发者

PHP: Proxy another url

开发者 https://www.devze.com 2022-12-22 10:05 出处:网络
I have a mod_rewrite rule that will send any subdomain requests to a php script which should proxy those requests to another host (internal proxy, not 302).

I have a mod_rewrite rule that will send any subdomain requests to a php script which should proxy those requests to another host (internal proxy, not 302).

I'm close, in that my script works with web browsers, but curl seems not like it:

curl: (56) Received problem 2 in the chunky parser

Here is my mod_rewrite:

RewriteCond %{HTTP_HOST} ^(.*)\.example\.com$
RewriteRule ^.*$ %{DOCUMENT_ROOT}/proxy.php?__path=%1 [QSA,L]

And my proxy.php

&l开发者_运维百科t;?php

$name = $_GET['__path'];
unset($_GET['__path']);
$path = $_SERVER['REQUEST_URI'];

$url = "http://$name.internal.example.com$path";
$ch = curl_init($url);
$headers = array();
foreach (apache_request_headers() as $key => $value) {
    $headers[] = "$key: $value";
}
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $_SERVER['REQUEST_METHOD']);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($_POST));
curl_setopt($ch, CURLOPT_HEADER, TRUE);  

$data = curl_exec($ch);

list($headers, $body) = explode("\r\n\r\n", $data, 2);
$headers = explode("\r\n", $headers);
foreach ($headers as $header) {
    header($header);
}
die($body);

Any reason why curl doesn't like this but browsers are ok with it?

EDIT: It seems if I don't send the Transfer-Encoding: chunked header, everything is ok (since I'm proxying the full request, chunking isn't possible). So a follow up question: Can I act as a true middleman and send the data as I get it over the socket?


Yes, you should be able send data over the network as you get it. But I suspect your problem may stem from persistent http connections. HTTP 1.0 will break the connection after the request, in your code you are creating a new CURL handle for each request, which is more like HTTP/1.0 instead of the default HTTP/1.1

curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);

You may still have problems with the application layer because CURL isn't meant to act as a proxy like this. Another approach would be to modify an existing PHP HTTP Client and make sure that the forwarded requests are close enough for your needs.

No matter what approach you use, I highly recommend using WireShark for debugging. You can then dump 2 http requests and then use something like Meld to pick out the differences.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号