我需要编写一个PHP脚本,使用本地代理(squid)“执行”HTTP请求。从客户端接收HTTP请求,脚本将请求发送到代理,从代理接收HTTP响应,并在经过一些处理后将其返回给客户端。我知道你要告诉我关于这种方法的所有不好的事情,但相信我,我需要这样做。
我正在使用PHP套接字来实现这一目标。这是我试图转发请求的代码片段(它基于我在网络上找到的一个例子):
<?php
$PROXY="localhost";
$PORT="3128";
$BUFFER_SIZE=1024*1024*5; //5Mb buffer
// (An untested HTTP request example, replace if it is not correct pls)
$request = "GET http://www.google.com HTTP/1.1\nHost: www.google.com\n\n";
// Create socket
if(!($sock = socket_create(AF_INET, SOCK_STREAM, 0)))
{
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
die("Couldn't create socket: [$errorcode] $errormsg\n");
}
//Connect socket to proxy server
if(!socket_connect($sock , $HOST , $PORT))
{
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
die("Could not connect: [$errorcode] $errormsg\n");
}
//Send the message to the proxy
if( ! socket_send ( $sock , $request, strlen($request) , 0))
{
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
die("Could not send data: [$errorcode] $errormsg\n");
}
//Now receive reply from proxy
if(socket_recv ( $sock , $buf , $BUFFER_SIZE , MSG_WAITALL ) === FALSE)
{
$errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
die("Could not receive data: [$errorcode] $errormsg\n");
}
//print the received message
print $buf;
此代码将消息发送给代理,但是......它被阻止了。经过一些研究后我发现了问题所在:脚本等待至少接收到BUFFER_SIZE字节或连接关闭。
我可以避免此设置超时选项:
if(!socket_set_option($sock,SOL_SOCKET,SO_RCVTIMEO,array("sec"=>2, "usec"=>0)))
{ $errorcode = socket_last_error();
$errormsg = socket_strerror($errorcode);
die("Can't set options: [$errorcode] $errormsg\n");
};
但这并没有解决我的问题,因为我想收到整个HTTP响应,而且请求可以是HTTP 1.1
我一直在考虑它,我唯一的想法是编写代码来分析HTTP响应以查看它的结束位置。我一直在搜索一些PHP代码,但是我没有找到任何东西。
所以我的问题是:
非常感谢。
更新
我按照Maskime的推荐尝试了一个循环。这是代码:
while($response=socket_recv ( $sock , $buf , 1 , MSG_WAITALL ))
{
...
print $buf;
}
它读取数据并在超时到达时退出,而不是之前。我不能使用这种方法,因为如果我设置超时,所有请求将至少遭受延迟,如果我设置得太低,一些请求将没有时间加载。
答案 0 :(得分:0)
经过一番调查后,您似乎需要解码&#34; HTTP / 1.1响应正确处理它。我还没有找到一个可以满足我需要的库,所以我尝试了另一种方法。
我所做的是修改代理级别的请求,以便连接变为非持久性。要做到这一点,你需要在squid.conf中设置这个指令(也许只有它们的一部分就足够了,但我还没试过):
client_persistent_connections off
server_persistent_connections off
persistent_connection_after_error off
使用该配置,它可以按我的意愿工作。将接收超时调整为两秒以上是个好主意,否则很多请求都会丢失。十秒对我来说很好,但可能更多:只有在真正的超时时它才会升起。
我想知道对第二个问题的回答,如果你有一个想法,那么知道它会很好。我一直在寻找Snoopy库,但它适用于HTTP / 1.0,并且没有进一步调查。