10

我在实现适用于 Java 的 API 时遇到问题,但无法使用 cURL。到目前为止,我们已经完成了所有工作,Java 发出的请求与我们发出的请求之间肯定存在一些不同之处。

在 PHP 中,我们可以通过查看$_SERVER['HTTP_*']变量来获取标头数据,我们可以从中获取请求正文,file_get_contents('php://input');但我们无法获取从用户代理发送到客户端的确切数据。

是否可以使用 PHP 获取用户代理发送的完整请求?包括标题和正文?如果是这样,那怎么办?

我发现的唯一示例是here,但是这个示例以我提到的方式获取正文,而它通过解析获取标头$_SERVER,这似乎是一种黑客攻击,因为它从来都不是实际发送的100%。

感谢所有帮助和提示!

4

3 回答 3

16

对于标题,您可以尝试apache_request_headers()而对于正文,我不知道其他方法file_get_contents('php://input');

于 2012-05-25T08:42:30.427 回答
4

老问题,但是对于将来需要这样做的任何人......最好的(可能唯一的)方法是通过成为服务器来完全控制服务器。

设置一个侦听端口 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 上启动服务器,只需php filename.php 8080从 shell 运行。

于 2014-05-13T08:20:09.773 回答
1

这些不是“使用 php”,但您可能会发现它们对您的目的很有用

于 2017-06-09T16:38:51.343 回答