Метод HEAD

Метод HEAD аналогичен методу GET, за исключением того, что сервер ничего не посылает в информационной части ответа. Метод HEAD запрашивает только информацию о файле и ресурсе, т.е. ничего кроме заголовков не возвращает. Этот метод используется, когда клиент хочет найти информацию о документе, не получая его. Удобно, когда нужно узнать размер файла, существует ли файл, когда последний раз изменялся файл. Позволяет сэкономить много времени и трафика.

Состав заголовка запроса HEAD должен быть такой же, как в запросе GET.

Пример метода HEAD

<?php
// открываем сокет
$fp = fsockopen('ekimoff.ru', 80, $errno, $errstr, 5);
if (!$fp) {
    echo $errno; // ошибка подключения
}
else {
    // формируем http-заголовки к серверу
    $request  = "HEAD /download/file.txt HTTP/1.0\r\n";
    $request .= "Host: ekimoff.ru\r\n";
    $request .= "User-Agent: Mozilla/2.0\r\n";
    $request .= "Connection: close\r\n\r\n";
	 
    // отсылаем запрос серверу
    fputs($fp, $request);
	 
    // получем ответ от сервера
    $content = '';
    while(!feof($fp) ){
        $content .= fgets($fp);
    }
    echo $content;
    fclose($fp);
}
?>

Как мы видим, содержимое файла в ответ на запрос HEAD не передается. Приходят только заголовки

HTTP/1.1 200 OK
Server: nginx/0.6.32
Date: Sat, 24 Apr 2010 14:19:41 GMT
Content-Type: text/plain; charset=UTF-8
Connection: close
Last-Modified: Sat, 24 Apr 2010 13:19:02 GMT
ETag: "43ace4b-b-4bd2efc6"
Accept-Ranges: bytes
Content-Length: 11

Теперь заменим в исходном коде метод HEAD на метод GET

<?php
// открываем сокет
$fp = fsockopen('ekimoff.ru', 80, $errno, $errstr, 5);
if (!$fp) {
    echo $errno; // ошибка подключения
}
else {
    // формируем http-заголовки к серверу
    $request  = "GET /download/file.txt HTTP/1.0\r\n";
    $request .= "Host: ekimoff.ru\r\n";
    $request .= "User-Agent: Mozilla/2.0\r\n";
    $request .= "Connection: close\r\n\r\n";
	 
    // отсылаем запрос серверу
    fputs($fp, $request);
 
    // получем ответ от сервера
    $content = '';
    while(!feof($fp) ){
        $content .= fgets($fp);
    }
    echo $content;
    fclose($fp);
}
?>

Ответ аналогичен, но теперь сервер отправил еще содержимое файла:

HTTP/1.1 200 OK
Server: nginx/0.6.32
Date: Sat, 24 Apr 2010 15:04:36 GMT
Content-Type: text/plain; charset=UTF-8
Connection: close
Last-Modified: Sat, 24 Apr 2010 13:19:02 GMT
ETag: "43ace4b-b-4bd2efc6"
Accept-Ranges: bytes
Content-Length: 11
 
bla-bla-bla

Размер файлика всего 11 байт. Представим, что в файл весит 11 Мб и запрашивается каждую секунду (например, последние обновления продуктов компании). Если внешнее приложение будет запрашивать данный файл напрямую каждую секунду, то трафик будет расти как на дрожжах.

Кстати, подобная схема используется у нас на работе, за тем исключением, что рядом с большим xml-файлом лежит маленький файлик в несколько байт, в котором хранится md5–хэш от большого файла. Таким образом, сделав сначала GET-запрос к маленькому файлу с md-хэшем, мы узнаем нужно ли нам делать запрос к основному файлу. md5-хэш хранится у нас в кэше для того чтобы сравнить его с содержимым md5-файлика на удаленном сервере. В данном примере не используется метод HEAD, но принцип экономии ресурсов и трафика аналогичен методу HEAD.

#1

Хороший пример на счет запроса к большим файлам. Очень кстати информация! Спасибо

Fuzaylov, 25.04.2010 - 07:58
#2

по поводу использования маленького файлика и md5 для проверки. можно использовать другой метод, более прямой, на мой взгляд. суть - в использовании заголовка If-Modified-Since. алгоритм такой: если удаленный файл более новый, чем локальный, то качаем его и заменяем им локальный, иначе ничего не делаем.

пример на curl:

URL=http://domain.tld/repo/remote_file.txt

curl -H "If-Modified-Since: `TZ=GMT date "+%a, %d %b %Y %H:%M:%S %Z" -r local_file.txt `" ${URL} > /tmp/local_temp_file.txt 2> /dev/null

[ -s /tmp/local_temp_file.txt ] && cat /tmp/local_temp_file.txt > local_file.txt

конфиг для nginx

location /repo/ {
root /opt/;
if_modified_since before;
}

nikl, 9.06.2012 - 11:20
Оставить комментарий