HTTP if-none-match и if-Modified-Since и пояснение 304 в PHP - PullRequest
8 голосов
/ 18 января 2010

Мой вопрос о том, как ответить HTTP 304 «Не изменен», когда я получаю оба if-none-match и if-Modified-Since от запроса прокси / клиента.

Из RFC 2616, раздел 14.26 (http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.26):

Если ни один из тегов сущности не совпадает, то сервер МОЖЕТ выполнить запрошенный метод как если бы заголовок If-None-Match поле не существует, но ДОЛЖНО также игнорировать любой заголовок If-Modified-Since поля в запросе. То есть если теги сущностей не совпадают, значит сервер НЕ ДОЛЖЕН возвращать 304 (не модифицированный) ответ.

Я не уверен, что понимаю это утверждение ...

  1. «Если ни один из тегов сущностей не совпадает» в PHP, они говорят о $_SERVER['HTTP_IF_NONE_MATCH'] против моих ETag, которые я отправил ранее?
  2. Если я правильно понимаю это утверждение, как только ни один из ETag, перечисленных в $_SERVER['HTTP_IF_NONE_MATCH'], не соответствует моим ETag, я прекращаю все проверки и обслуживаю страницу в обычном режиме.

Кто-нибудь может перевести эту часть RFC в псевдокод (или код PHP) и / или ответить на мои 2 пункта выше?

РЕДАКТИРОВАТЬ 1: Спасибо St.Woland за ваш ответ. Можете ли вы (или кто-либо еще) сказать мне, если я прав по этим 6 пунктам:

  1. Формат $_SERVER['HTTP_IF_NONE_MATCH'] может быть любым:

    a) If-None-Match: "xyzzy", "r2d2xxxx", "c3piozzzz"

    b) If-None-Match: "xyzzy"

    и НЕ:

    c) If-None-Match: "xyzzy, r2d2xxxx, c3piozzzz"

  2. Если !array_key_exists('HTTP_IF_NONE_MATCH', $_SERVER), anyTagMatched () возвращает NULL.

  3. Как только ETag в $_SERVER['HTTP_IF_NONE_MATCH'] совпадает с моим документом ETag, anyTagMatched () возвращает TRUE.

  4. Если ни один из Etags в $_SERVER['HTTP_IF_NONE_MATCH'] не соответствует моему документу ETag, anyTagMatched() возвращает FALSE.

  5. Если установлено $_SERVER['HTTP_IF_MODIFIED_SINCE'] и соответствует моему документу «дата последнего изменения» isExpired() возвращает FALSE, в противном случае возвращает TRUE.

  6. Как только anyTagMatched() вернет TRUE, я выдаю 304. Если anyTagMatched () вернул NULL, а isExpired() вернул FALSE, я могу выдать 304. В любой другой ситуации я обслуживаю свою страницу как обычно (я также выпускать последние заголовки Last-Modified и ETag).

1 Ответ

5 голосов
/ 18 января 2010

Это должно быть поставлено в конце (перемещено для лучшего вида).

$anyTagMatched = anyTagMatched() ;
if( $anyTagMatched || ( ( null === $anyTagMatched ) && !isExpired() ) ) {
    notModified() ;
}
// Output content

Псевдокод (необходим обзор):

<?php

/**
 * Calculates eTag for the current resource.
 */
function calculateTag() {
}

/**
 * Gets date of the most recent change.
 */
function lastChanged() {
}

/**
 * TRUE if any tag matched
 * FALSE if none matched
 * NULL if header is not specified
 */
function anyTagMatched() {
    $if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH']) ?
        stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) : 
        false ;

    if( false !== $if_none_match ) {
        $tags = split( ", ", $if_none_match ) ;
        $myTag = calculateTag() ;
        foreach( $tags as $tag ) {
            if( $tag == $myTag ) return true ;
        }
        return false ;
    }
    return null ;
}

function isExpired() {
    $if_modified_since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ?
        stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']) :
        false;

    if( false !== $if_modified_since ) {
        // Compare time here; pseudocode.
        return ( $if_modified_since < lastChanged() ) ;
    }

    return true ;
}

function notModified() {
    header('HTTP/1.0 304 Not Modified');
    exit ;
}

Основной ответ здесь .

...