Метод 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.
Хороший пример на счет запроса к большим файлам. Очень кстати информация! Спасибо
по поводу использования маленького файлика и 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;
}