Разработчику. Сборник рецептов PHP
Задавайте вопросы

Отладка обмена заголовками HTTP

Вернуться назад

Задача

Необходимо проанализировать HTTP-запрос броузера к серверу и соответствующий HTTP-ответ. Например, сервер не выдает ожидаемого ответа на определенный запрос, поэтому требуется точно определить, какие компоненты запрашивались.

Решение

Если запросы простые, надо соединиться с веб-сервером c помощью программы telnet и ввести с клавиатуры следующие заголовки запроса:

% telnet www.example.com 80
Trying 10.1.1.1...
Connected to www.example.com.
Escape character is '^]'.
GET / HTTP/1.0
Host: www.example.com


HTTP/1.1 200 OK
Date: Sat, 17 Aug 2002 06:10:19 GMT
Server: Apache/1.3.26 (UNIX) PHP/4.2.2 mod_ssl/2.8.9 OpenSSL/0.9.6d
X Powered By: PHP/4.2.2
Connection: close
Content Type: text/html

// ... основная часть страницы ...

Обсуждение

Когда вы печатаете от руки заголовки запроса, веб-сервер не знает, что это именно вы печатаете, а не броузер представляет запрос. Однако некоторые веб-серверы определенное время ожидают запроса, поэтому иногда удобнее заблаговременно набрать запрос, а затем вставить его в окно программы telnet. Первая строка запроса содержит метод запроса (GET), пробел и путь к требуемому файлу (/), а затем пробел и используемый протокол (HTTP/1.0). Следующая строка, заголовок Host, сообщает серверу, какой виртуальный сервер использовать, если несколько серверов используют один и тот же IP-адрес. Пустая строка говорит серверу, что запрос завершен; тогда он выдает свой ответ: сначала заголовки, потом пустую строку, а затем основное содержание ответа.

Вставка текста в окно программы telnet может быть утомительным занятием, а еще труднее таким образом делать запросы методом POST. При посылке запроса с использованием класса HTTP_Request можно получить заголовки и тело ответа с помощью методов getResponseHeader() и getResponseBody():

require 'HTTP/Request.php';
$r = new HTTP_Request('http://www.example.com/submit.php');
$r->setMethod(HTTP_REQUEST_METHOD_POST);
$r->addPostData('monkey','uncle');
$r->sendRequest();

$response_headers = $r->getResponseHeader();
$response_body = $r->getResponseBody();

Чтобы получить определенный заголовок ответа, передайте имя заголовка функции getResponseHeader(). Без аргумента метод getResponseHeader() возвращает массив, содержащий все заголовки ответа. Класс HTTP_Request не сохраняет выходящие запросы в переменной, но его можно реконструировать с помощью вызова частного метода _buildRequest():

require 'HTTP/Request.php';

$r = new HTTP_Request('http://www.example.com/submit.php');
$r->setMethod(HTTP_REQUEST_METHOD_POST);
$r->addPostData('monkey','uncle');

print $r->_buildRequest();

Напечатанный запрос выглядит так:

POST /submit.php HTTP/1.1
User-Agent: PEAR HTTP_Request class ( http://pear.php.net/ )
Content-Type: application/x-www-form-urlencoded
Connection: close
Host: www.example.com
Content-Length: 12

monkey=uncle

При использовании расширения c URL для включения заголовков ответа в вывод функции curl_exec() установите параметр CURLOPT_HEADER:

$c = curl_init('http://www.example.com/submit.php');
curl_setopt($c, CURLOPT_HEADER, 1);
curl_setopt($c, CURLOPT_POST, 1);
curl_setopt($c, CURLOPT_POSTFIELDS, 'monkey=uncle&rhino=aunt');
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
$response_headers_and_page = curl_exec($c);
curl_close($c);

Чтобы записать заголовки ответа в файл на диске, откройте дескриптор файла с помощью функции fopen() и установите для этого дескриптора файла параметр CURLOPT_WRITEHEADER:

$fh = fopen('/tmp/curl-response-headers.txt','w') or die($php_errormsg);
$c = curl_init('http://www.example.com/submit.php');
curl_setopt($c, CURLOPT_POST, 1);
curl_setopt($c, CURLOPT_POSTFIELDS, 'monkey=uncle&rhino=aunt');
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($c, CURLOPT_WRITEHEADER, $fh);
$page = curl_exec($c);
curl_close($c);
fclose($fh) or die($php_errormsg);

Параметр CURLOPT_VERBOSE модуля c URL заставляет функции curl_exec() и curl_close() выводить отладочную информацию в поток стандартных ошибок, включая содержимое запроса:

$c = curl_init('http://www.example.com/submit.php');
curl_setopt($c, CURLOPT_VERBOSE, 1);
curl_setopt($c, CURLOPT_POST, 1);
curl_setopt($c, CURLOPT_POSTFIELDS, 'monkey=uncle&rhino=aunt');
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
$page = curl_exec($c);
curl_close($c);

В результате будет напечатано:

* Connected to www.example.com (10.1.1.1)
> POST /submit.php HTTP/1.1
Host: www.example.com
Pragma: no-cache
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, */*
Content-Length: 23
Content-Type: application/x-www-form urlencoded

monkey=uncle&rhino=aunt* Connection #0 left intact
* Closing connection #0

Поскольку расширение c URL выводит отладочную информацию в поток стандартных ошибок, а не в стандартный поток вывода, он не может быть захвачен буфером вывода, подобно тому как в рецепте (Регистрация отладочной информации и ошибок) это делается с помощью функции print_r(). Однако чтобы направить отладочную информацию в файл, можно открыть дескриптор файла на запись и установить для этого дескриптора параметр CURLOUT_STDERR:

$fh = fopen('/tmp/curl.out','w') or die($php_errormsg);
$c = curl_init('http://www.example.com/submit.php');
curl_setopt($c, CURLOPT_VERBOSE, 1);
curl_setopt($c, CURLOPT_POST, 1);
curl_setopt($c, CURLOPT_POSTFIELDS, 'monkey=uncle&rhino=aunt');
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($c, CURLOPT_STDERR, $fh);
$page = curl_exec($c);
curl_close($c);
fclose($fh) or die($php_errormsg);

Вернуться назад

Рейтинг@Mail.ru

Яндекс.Метрика

Индекс цитирования

Рейтинг Сайтов ДОСКИ.РУ