简体   繁体   English

如何使用PHP捕获完整的HTTP请求数据(标题和正文)?

[英]How to capture full HTTP request data (headers and body) with PHP?

I have a problem implementing an API that works with Java, but fails to work with cURL. 我在实现与Java一起使用的API时遇到问题,但无法使用cURL。 We've gone through everything so far and there must be something that is different between the requests that Java makes and what we make. 到目前为止,我们已经完成了所有事情,并且必须在Java生成的请求和我们制作的内容之间有所不同。

In PHP we can get header data by looking at $_SERVER['HTTP_*'] variables and we can get request body from file_get_contents('php://input'); 在PHP中,我们可以通过查看$_SERVER['HTTP_*']变量获取头数据,我们可以从file_get_contents('php://input');获取请求体file_get_contents('php://input'); But we cannot get the exact data sent from user agent to client. 但是我们无法获得从用户代理发送到客户端的确切数据。

Is it possible to get the full request, that user agent sends, with PHP? 是否可以通过PHP获取用户代理发送的完整请求? Headers and body included? 包括标题和身体? If so, then how? 如果是这样,那怎么样?

The only example I found is here , but this one gets the body the way I mentioned, while it gets headers by parsing through $_SERVER , which seems like a hack since it's never 100% of what was actually sent. 我找到的唯一例子就是这里 ,但是这个以我提到的方式得到了主体,而它通过解析$_SERVER得到了标题,这似乎是一个黑客,因为它从来不是实际发送的100%。

All help and tips are appreciated! 所有帮助和提示表示赞赏!

对于标题,您可以尝试apache_request_headers() ,对于body我不知道除file_get_contents('php://input');之外的其他方法file_get_contents('php://input');

Old question, but for anyone needing to do this in the future... The best (probably only) way would be to take full control of the server by being the server. 老问题,但对于将来需要这样做的人来说......最好的(可能是唯一的)方法是通过作为服务器来完全控制服务器。

Set up a socket server listening on port 80 (if this is all you need the server to do), or any other port if 80 is not available. 设置一个侦听端口80的套接字服务器(如果这是你需要服务器做的全部),或者如果80不可用则设置任何其他端口。

That way you can capture the request completely unmodified. 这样您就可以完全不加修改地捕获请求。 Examples of basic socket servers are plentiful, here is a simplified version of the latest one I implemented, which will print the full request: 基本套接字服务器的例子很多,这是我实现的最新版本的简化版本,它将打印完整的请求:

<?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;

To start the server on port 8080 just run php filename.php 8080 from a shell. 要在端口8080上启动服务器,只需从shell运行php filename.php 8080

These aren't "with php" but you might find them useful for your purposes nevertheless 这些不是“与PHP”,但你可能会发现它们对你的目的很有用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM