Как изолировать заголовки / тело HTTP от запроса сокетов PHP - PullRequest
9 голосов
/ 06 января 2012

Я использую сокетное соединение в PHP для публикации данных на веб-сервере Apache. Я немного новичок в этой технике, и я не уверен, как изолировать заголовки от тела ответа.

Код отправки:

<?php
// collect data to post
$postdata = array(
    'hello' => 'world'
);
$postdata = http_build_query($postdata);
// open socket, send request
$fp = fsockopen('127.0.0.1', 80);
fwrite($fp, "POST /server.php HTTP/1.1\r\n");
fwrite($fp, "Host: fm1\r\n");
fwrite($fp, "Content-Type: application/x-www-form-urlencoded\r\n");
fwrite($fp, "Content-Length: ".strlen($postdata)."\r\n");
fwrite($fp, "Connection: close\r\n");
fwrite($fp, "\r\n");
fwrite($fp, $postdata);
// go through result
$result = "";
while(!feof($fp)){
    $result .= fgets($fp);
}
// close
fclose($fp);
// display result
echo $result;
?>

Код сервера:

<code>Hello this is server. You posted:
<pre>
<?php print_r($_POST); ?>

При публикации на одном сервере я получаю:

<code>HTTP/1.1 200 OK
Date: Fri, 06 Jan 2012 09:55:27 GMT
Server: Apache/2.2.15 (Win32) mod_ssl/2.2.15 OpenSSL/0.9.8m PHP/5.3.2
X-Powered-By: PHP/5.3.2
Content-Length: 79
Connection: close
Content-Type: text/html

Hello this is server. You posted:
<pre>
Array
(
    [hello] => world
)

Как и ожидалось. Я хочу убрать заголовки, и просто прочитать тело с «Привет, это сервер .....» и далее. Как я могу надежно определить конец заголовков и прочитать тело в переменную?

Кроме того, еще один сервер, который я проверял на ответы с этим:

<code>HTTP/1.1 200 OK
Date: Fri, 06 Jan 2012 10:02:04 GMT
Server: Apache/2
X-Powered-By: PHP/5.2.17
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html

4d
Hello this is server. You posted:
<pre>
Array
(
    [hello] => world
)
0

Что такое "4d" и "0" вокруг основного текста ??

Спасибо!

PS прежде чем кто-то скажет использовать CURL, я, к сожалению, не могу: - (

Ответы [ 3 ]

16 голосов
/ 06 января 2012

Вы можете отделить заголовок от тела, разделив его на двойной разрыв строки.Это должно быть <CRLF><CRLF>, так что это обычно работает:

list($header, $body) = explode("\r\n\r\n", $response, 2);

Более надежно, вы должны использовать регулярное выражение, чтобы поймать варианты разрыва строки (супер маловероятно, чтобы когда-либо произошло):

list($header, $body) = preg_split("/\R\R/", $response, 2);

Вещи с 4d и 0 называются chunked encoding .(Это шестнадцатеричные числа, разделенные очередным переводом строки, и указывают длину следующего блока необработанного содержимого.)

Чтобы выяснить это, сначала нужно посмотреть на заголовки и посмотреть, есть ли соответствующий Transfer-Encoding: запись.Это было бы сложно и желательно использовать один из множества существующих классов обработки HTTP-пользователей.У PEAR есть один .

0 голосов
/ 06 июля 2015

В большинстве случаев ответ Марио должен работать, но я только что попытался применить этот метод к ответу от Couch DB, и есть некоторые случаи, когда он не работает.

Если ответ не содержит никаких документов, то Couch DB помещает "\ r \ n \ r \ n" в тело ответа, пытаясь сохранить правильность результатов, и в этом случае недостаточно просто разделить ответ на "\ r \ n \ r \ n ", потому что вы можете случайно порезать концевую часть тела.

HTTP/1.0 200 OK Server: CouchDB/1.6.1 (Erlang OTP/R16B02) ETag: "DJNMQO5WQIBZHFMDU40F1O94T" Date: Mon, 06 Jul 2015 09:37:33 GMT Content-Type: text/plain; charset=utf-8 Cache-Control: must-revalidate 
{"total_rows":0,"offset":0,"rows":[
// Couch DB adds some extra line breakers on this line
]}

Следующий анализ кажется более надежным для Couch DB:

$parts = explode("\r\n\r\n", $response);

if ($parts)
{
    $headers = array_shift($parts);
    $body = json_decode(implode("\r\n\r\n", $parts));
}
0 голосов
/ 06 января 2012

Заголовки должны заканчиваться "\r\n\r\n" (два раза).Эти 4d и 0 , возможно, являются частью вашего php-ответа (они не являются частью заголовков).

...