我有一个mod_rewrite规则,将任何子域请求发送到PHP脚本,该脚本应该将这些请求代理到另一个主机(内部代理,而不是302).
我很接近,因为我的脚本适用于Web浏览器,但curl似乎不喜欢它:
curl: (56) Received problem 2 in the chunky parser
Run Code Online (Sandbox Code Playgroud)
这是我的mod_rewrite:
RewriteCond %{HTTP_HOST} ^(.*)\.example\.com$
RewriteRule ^.*$ %{DOCUMENT_ROOT}/proxy.php?__path=%1 [QSA,L]
Run Code Online (Sandbox Code Playgroud)
和我的 proxy.php
<?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);
Run Code Online (Sandbox Code Playgroud)
任何理由为什么curl不喜欢这个但浏览器还可以呢?
编辑:似乎我没有发送Transfer-Encoding: chunked标题,一切都很好(因为我代理完整的请求,无法进行分块).所以后续问题:我可以充当真正的中间人并在我通过套接字发送数据时发送数据吗?
是的,您应该能够在收到数据后通过网络发送数据。但我怀疑你的问题可能源于持久的 http 连接。HTTP 1.0 将在请求后断开连接,在您的代码中,您将为每个请求创建一个新的 CURL 句柄,这更像是 HTTP/1.0 而不是默认的 HTTP/1.1
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
Run Code Online (Sandbox Code Playgroud)
您可能仍然遇到应用程序层的问题,因为 CURL 并不意味着充当这样的代理。另一种方法是修改现有的PHP HTTP 客户端并确保转发的请求足够接近您的需求。
无论您使用哪种方法,我都强烈建议使用 WireShark 进行调试。然后,您可以转储 2 个 http 请求,然后使用Meld之类的工具来找出差异。