[英]How to capture full HTTP request data (headers and body) with PHP?
我在实现与Java一起使用的API时遇到问题,但无法使用cURL。 到目前为止,我们已经完成了所有事情,并且必须在Java生成的请求和我们制作的内容之间有所不同。
在PHP中,我们可以通过查看$_SERVER['HTTP_*']
变量获取头数据,我们可以从file_get_contents('php://input');
获取请求体file_get_contents('php://input');
但是我们无法获得从用户代理发送到客户端的确切数据。
是否可以通过PHP获取用户代理发送的完整请求? 包括标题和身体? 如果是这样,那怎么样?
我找到的唯一例子就是这里 ,但是这个以我提到的方式得到了主体,而它通过解析$_SERVER
得到了标题,这似乎是一个黑客,因为它从来不是实际发送的100%。
所有帮助和提示表示赞赏!
对于标题,您可以尝试apache_request_headers() ,对于body我不知道除file_get_contents('php://input');
之外的其他方法file_get_contents('php://input');
老问题,但对于将来需要这样做的人来说......最好的(可能是唯一的)方法是通过作为服务器来完全控制服务器。
设置一个侦听端口80的套接字服务器(如果这是你需要服务器做的全部),或者如果80不可用则设置任何其他端口。
这样您就可以完全不加修改地捕获请求。 基本套接字服务器的例子很多,这是我实现的最新版本的简化版本,它将打印完整的请求:
<?php
//Read the port number from first parameter on the command line if set
$port = (isset($argv[1])) ? intval($argv[1]) : 80;
//Just a helper
function dlog($string) {
echo '[' . date('Y-m-d H:i:s') . '] ' . $string . "\n";
}
//Create socket
while (($sock = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) {
dlog("socket_create() failed: reason: " . socket_strerror(socket_last_error()));
sleep(1);
}
//Reduce blocking if previous connections weren't ended correctly
if (!socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1)) {
dlog("socket_set_option() failed: reason: " . socket_strerror(socket_last_error($sock)));
exit;
}
//Bind to port
$tries = 0;
while (@socket_bind($sock, 0, $port) === false) {
dlog("socket_bind() failed: reason: " . socket_strerror(socket_last_error($sock)));
sleep(1);
$tries++;
if ($tries>30) {
dlog("socket_bind() failed 30 times giving up...");
exit;
}
}
//Start listening
while (@socket_listen($sock, 5) === false) {
dlog("socket_listen() failed: reason: " . socket_strerror(socket_last_error($sock)));
sleep(1);
}
//Makes it possible to accept several simultaneous connections
socket_set_nonblock($sock);
//Keeps track of active connections
$clients = array();
dlog("server started...");
while(true) {
//Accept new connections
while (($msgsock = @socket_accept($sock)) !== false) {
//Prevent blocking
socket_set_nonblock($msgsock);
//Get IP - just for logging
socket_getpeername($msgsock, $remote_address);
//Add new client to array
$clients[] = array('sock' => $msgsock, 'timeout' => time()+30, 'ip' => $remote_address);
dlog("$remote_address connected, client count: ".count($clients));
}
//Loop existing clients and read input
foreach($clients as $key => $client) {
$rec = '';
$buf = '';
while (true) {
//Read 2 kb into buffer
$buf = socket_read($clients[$key]['sock'], 2048, PHP_BINARY_READ);
//Break if error reading
if ($buf === false) break;
//Append buffer to input
$rec .= $buf;
//If no more data is available socket read returns an empty string - break
if ($buf === '') break;
}
if ($rec=='') {
//If nothing was received from this client for 30 seconds then end the connection
if ($clients[$key]['timeout']<time()) {
dlog('No data from ' . $clients[$key]['ip'] . ' for 30 seconds. Ending connection');
//Close socket
socket_close($client['sock']);
//Clean up clients array
unset($clients[$key]);
}
} else {
//If something was received increase the timeout
$clients[$key]['timeout']=time()+30;
//And.... DO SOMETHING
dlog('Raw data received from ' . $clients[$key]['ip'] . "\n------\n" . $rec . "\n------");
}
}
//Allow the server to do other stuff by sleeping for 50 ms on each iteration
usleep(50000);
}
//We'll never reach here, but some logic should be implemented to correctly end the server
foreach($clients as $key => $client) {
socket_close($client['sock']);
}
@socket_close($sock);
exit;
要在端口8080上启动服务器,只需从shell运行php filename.php 8080
。
这些不是“与PHP”,但你可能会发现它们对你的目的很有用
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.