Опубликован: 28.09.2007 | Уровень: специалист | Доступ: платный
Лекция 7:

Гипертекстный протокол HTTP

Вычисление времени жизни (Expiration)

Для того, чтобы решить, является ли отклик свежим или устаревшим, нам нужно сравнить его время жизни с возрастом. Этот раздел описывает, как вычисляется время жизни и как определяется, истекло ли время жизни отклика. В обсуждении, приведенном ниже, величины могут быть представлены в любой форме, удобной для выполнения арифметических операций.

Мы применяем термин expires_value для обозначения содержимого заголовка Expires. Для обозначения числа секунд, определенного директивой максимального возраста заголовка Cache-Control отклика, используется термин max_age_value.

Директива максимального возраста имеет приоритет перед Expires — так, если maxage присутствует в отклике, вычисление производится просто:

freshness_lifetime = max_age_value

В противном случае, если в отклике присутствует Expires, то вычисления осуществляются следующим образом:

freshness_lifetime = expires_value  date_value

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

Если ни Expires, ни Cache-Control: maxage не определяют максимальный возраст отклика, а отклик не содержит других ограничений на кэширование, кэш может вычислить время жизни, используя эвристику. Если эта величина больше 24 часов, кэш должен присоединить к отклику Warning 13 (если такое предупреждение еще не добавлено).

Кроме того, если отклик имеет время Last-Modified, эвристическое значение времени жизни должно быть не больше некоторой доли времени, прошедшего со времени модификации. Типичное значение этой доли может составлять 10%. Расчет того, истекло ли время жизни отклика, достаточно прост:

response_is_fresh = (freshness_lifetime > current_age)
Устранение неопределенности значений времени жизни

Из­за того, что значения времени жизни часто назначаются оптимистически, может так случиться, что два кэша содержат две свежих записи одного и того же ресурса, которые различаются.

Если клиент, выполняя извлечение ресурса, получает отклик не из первых рук на запрос, который был свежим в своем собственном кэше, а заголовок Date в его кэше новей, чем Date нового отклика, тогда клиент может игнорировать этот отклик. Если это так, он может повторить запрос с директивой "Cache-Control: maxage=0", чтобы усилить контроль со стороны исходного сервера.

Если кэш имеет два свежих отклика для одного и того же представления с различными указателями корректности (validator), он должен использовать тот, который имеет современный заголовок Date. Эта ситуация может возникнуть, когда кэш извлекает отклик из других кэшей, или потому, что клиент запросил перезагрузку или повторную проверку корректности заведомо свежего объекта.

Неопределенность из-за множественных откликов

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

Ни метка объекта, ни значение времени жизни не могут определять порядок откликов, так как возможно, что более поздний отклик имеет срок годности, который истекает раньше. Однако спецификация HTTP/1.1 требует передачи заголовка Date в каждом отклике, а значения Date должны быть кратны одной секунде.

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

Cache-Control: maxage=0

чтобы заставить некоторые промежуточные кэши сверить свои копии непосредственно с исходным сервером, или

Cache-Control: no-cache

чтобы заставить любые промежуточные кэши получит новые копии от исходного сервера.

Если значения Date равны, тогда клиент может использовать любой отклик (или может, если он особенно осторожен, затребовать новый отклик). Серверы не должны зависеть от возможности клиентов четко выбирать между откликами, сгенерированными в пределах одной и той же секунды, если их сроки пригодности перекрываются.

Модель проверки пригодности

Когда кэш имеет устаревшую запись, которую бы он хотел использовать в качестве отклика на запрос клиента, он сначала должен произвести сверку с базовым сервером (или, возможно, промежуточным кэшем, содержащим свежий отклик), чтобы убедиться, что кэшированная запись все еще применима. Мы это называем проверкой пригодности записи кэша (validating). Так как мы не хотим пересылки всей записи, если с ней все в порядке, и мы не хотим тратить лишнее время изза RTT в случае, если запись более не пригодна, протокол HTTP/1.1 поддерживает использование условных методов.

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

Сервер сверяет полученный валидатор с текущим валидатором объекта, и, если они совпадают, посылается отклик с соответствующим статусным кодом (обычно, 304 (Not Modified)) и без тела объекта. В противном случае возвращается полный отклик (включая тело объекта). Таким образом, мы избегаем передачи полного отклика, если валидаторы взаимно согласованы.

В HTTP/1.1 условный запрос выглядит точно так же, как и обычный запрос того же самого ресурса, за исключением того, что он несет в себе специальный заголовок (который содержит валидатор) и неявно меняет обычный метод GET на условный.

Протокол предусматривает как положительное, так и отрицательное значения условий проверки пригодности записей кэша. То есть, можно запросить, чтобы был реализован этот метод тогда и только тогда, когда валидатор подходит, или тогда и только тогда, когда ни один валидатор не подходит.

Замечание. Отклик, который не имеет валидатора, может кэшироваться и использоваться до истечения его срока годности, если только это явно не запрещено директивой Cache-Control. Однако кэш не может выполнить условную доставку ресурса, если он не имеет валидатора для запрашиваемого объекта, что означает отсутствие возможности его актуализации после истечения срока годности.

Даты последней модификации

Значение поля заголовка объекта Last-Modified часто используется кэшем в качестве валидатора. Иными словами, запись в кэше рассматривается как пригодная, если объект не был модифицирован с момента, указанного в Last-Modified.

Валидаторы кэша для меток объектов (Entity Tag Cache Validators)

Значение поля заголовка объекта ETag (Entity Tag — метка объекта), представляет собой непрозрачный валидатор кэша. Это может гарантировать большую надежность при контроле пригодности в ситуациях, когда неудобно запоминать модификации дат, где недостаточно односекундного разрешения для значения даты HTTP или где исходный сервер хочет избежать определенных парадоксов, которые могут возникнуть от использования дат модификации.

Слабые и сильные валидаторы

Так как исходные серверы и кэши будут сравнивать два валидатора, чтобы решить, представляют ли они один и тот же объект, обычно подразумевается, что, если объект (тело объекта или любой заголовок) изменяется каким­-либо образом, то и сопряженный валидатор изменится. Если это так, такой валидатор называется сильным.

Однако могут встретиться случаи, когда сервер предпочитает изменять валидатор только при семантически существенных изменениях. Валидатор, который не изменяется всякий раз при изменении ресурса, называется слабым.

Метки объекта обычно являются сильными валидаторами, но протокол предлагает механизм установки слабой метки объекта. Можно считать, что сильный валидатор — это тот, который изменяется, если меняется хотя бы один бит в объекте, в то время как значение слабого изменяется при вариации значения объекта.

Сильный валидатор представляет собой часть идентификатора конкретного объекта, а слабый валидатор является частью идентификатора набора семантически эквивалентных объектов.

Замечание. Примером сильного валидатора является целое число, которое увеличивается на единицу всякий раз, когда в объект вносится какое­-либо изменение.

Время модификации объекта при односекундном разрешении может быть лишь слабым валидатором, так как имеется возможность того, что ресурс может быть модифицирован дважды в течение одной и той же секунды.

Поддержка слабых валидаторов является опционной. Однако слабый валидатор позволяет более эффективно кэшировать эквивалентные объекты.

Валидатор используется либо, когда клиент генерирует запрос и включает валидатор в поле заголовка проверки годности, либо когда сервер сравнивает два валидатора.

Сильные валидаторы могут использоваться в любом контексте. Слабые валидаторы применимы только в контексте, который не зависит от точной эквивалентности объектов. Например, как один, так и другой вид валидаторов применим для условного GET. Однако только сильный валидатор применим для фрагментированного извлечения ресурсов, так как в противном случае клиент может прервать работу с внутренне противоречивым объектом.

Единственной функцией протокола HTTP/1.1, определенной для валидаторов, является сравнение. Существует две функции сравнения валидаторов, в зависимости от того, допускает ли контекст использование слабых валидаторов или нет.

  • Функция сильного сравнения. Для того, чтобы считаться равными, оба валидатора должны быть идентичными и не один из них не должен быть слабым.
  • Функция слабого сравнения. Для того, чтобы считаться равными, оба валидатора должны быть идентичными, но либо оба, либо один из них могут иметь метку "слабый" без какого-либо воздействия на результат.

Функция слабого сравнения может быть использована для простых (nonsubrange — не фрагментных) GETзапросов. Функция сильного сравнения должна быть использована во всех прочих случаях. Метка объекта является сильной, если она не помечена явно как слабая.

Параметр Last-Modified time при использовании в качестве валидатора запроса является неявно слабым, если невозможно установить, что он сильный, используя следующие правила:

  • валидатор сравнивается исходным сервером с текущим рабочим валидатором для данного объекта и,
  • исходный сервер твердо знает, что соответствующий объект не изменялся дважды за секунду, к которой привязан настоящий валидатор.

Или:

  • валидатор предполагается использовать клиентом в заголовке If-Modified-Since или If-Unmodified-Since, так как клиент имеет запись в кэше для соответствующего объекта, и
  • эта запись в кэш включает в себя значение Date, которое определяет время, когда исходный сервер послал оригинал запроса, и
  • предлагаемый параметр Last-Modified time соответствует моменту времени, по крайней мере, на 60 секунд раньше значения Date.

Или:

  • валидатор сравнивается промежуточным кэшем с валидатором, запомненным в записи для данного объекта, и
  • эта запись в кэше включает в себя значение Date, которое определяет время, когда исходный сервер послал оригинал запроса, и
  • предлагаемый параметр Last-Modified time соответствует моменту времени, по крайней мере, на 60 секунд раньше значения Date.

Этот метод базируется на том факте, что, если два различных отклика были посланы исходным сервером в пределах одной и той же секунды, но оба имеют одно и то же время Last-Modified, то, по крайней мере, один из этих откликов имеет значение Date, равное его времени Last-Modified. Произвольный 60-секундный лимит предохраняет против того, что значения Date и Last-Modified сгенерированы с использованием различных часов или в несколько разные моменты времени при подготовке отклика. Конкретная реализация может использовать величину больше 60 секунд, если считается, что 60 секунд слишком мало.

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

Правила того, когда использовать метки объекта и даты последней модификации

Мы принимаем набор правил и рекомендаций для исходных серверов, клиентов и кэшей относительно того, когда должны использоваться различные типы валидаторов и для каких целей.

Исходный сервер HTTP/1.1:

  • должен послать валидатор метки объекта, если только возможно его сгенерировать;
  • может послать слабую метку объекта вместо сильной, если рабочие соображения поддерживают использования слабых меток объекта или если невозможно послать сильную метку объекта;
  • должен послать значение Last-Modified, когда это возможно, если только риск нарушения семантической прозрачности, которое может явиться следствием использования этой даты в заголовке, не приведет к серьезным проблемам.

Другими словами, предпочтительным поведением для исходного сервера HTTP/1.1 является посылка сильной метки объекта и значения Last-Modified.

Для сохранения легальности сильная метка объекта должна изменяться всякий раз, когда каким­-либо образом меняется ассоциированное значение объекта. Слабую метку объекта следует менять всякий раз, когда соответствующий объект изменяется семантически значимым образом.

Для того, чтобы обеспечить семантически прозрачное кэширование, исходный сервер должен избегать повторного использования специфических, сильных меток для двух разных объектов или повторного использования специфических, слабых меток для двух семантически разных объектов. Записи в кэш могут существовать сколь угодно долгое время вне зависимости от времени годности. Таким образом, может оказаться неразумным ожидать, что кэш никогда вновь не попытается перепроверить запись, используя валидатор, который он получил в какой­то момент в прошлом.

Клиенты HTTP/1.1

  • Если метка объекта была прислана исходным сервером, эта метка должна быть использована в любом условном запросе кэша (с If-Match или If-None-Match ).
  • Если только значение Last-Modified было прислано исходным сервером, оно должно использоваться в нефрагментных, условных запросах кэша (с использованием If-Modified-Since ).
  • Если только значение Last-Modified было прислано исходным сервером HTTP/1.0, оно может использоваться в фрагментных, условных запросах кэша (с использованием If-Unmodified-Since:). Агенту пользователя следует обеспечить способ блокировки этого в случае возникновения трудностей.
  • Если и метка объекта и значение Last-Modified были присланы исходным сервером, в условных запросах кэша следует использовать оба валидатора. Это позволяет корректно реагировать кэшам, поддерживающим как HTTP/1.0, так и HTTP/1.1.

Кэш HTTP/1.1 при получении запроса должен использовать наиболее регламентирующий валидатор, когда проверяется, соответствуют ли друг другу запись в буфере клиента и запись в кэше. Это единственный выход, когда запрос содержит как метку объекта, так и валидатор lastmodifieddate ( If-Modified-Since или If-Unmodified-Since ).

Базовым принципом всех этих правил является то, что HTTP/1.1 серверы и клиенты должны пересылать как можно больше надежной информации в своих запросах и откликах. HTTP/1.1 системы, принимая эту информацию, используют наиболее консервативное предположение относительно валидаторов, которые они получают.

Условия пригодности

Принцип использования меток объектов базируется на том, что только автор услуг знает семантику ресурсов достаточно хорошо, чтобы выбрать подходящий механизм контроля кэширования. Спецификация любой функции сравнения валидаторов более сложна, чем сравнение байтов. Таким образом, для целей проверки пригодности записи в кэше никогда не используется сравнение любых других заголовков кроме Last-Modified, для совместимости с HTTP/1.0.

Кэшируемость отклика

Если только нет специального ограничения директивой Cache-Control, система кэширования может всегда запоминать отклик в виде записи в кэш, может прислать его без проверки пригодности, если он является свежим, и может отослать его после успешной проверки пригодности. Если нет ни валидатора кэша, ни времени пригодности, ассоциированного с этим откликом, такой отклик может не кэшироваться, но некоторые кэши могут нарушить это правило (например, когда имеется плохая коннективность или она вообще отсутствует). Клиент обычно может детектировать, что такой отклик был взят из кэша, после сравнения заголовка Date с текущим временем.

Заметьте, что некоторые кэши HTTP/1.0 нарушают эти правила, даже не присылая предупреждения.

Однако в некоторых случаях для кэша может быть неприемлемо сохранять объект или присылать его в ответ на последующие запросы. Возможная причина: автор сервиса полагает необходимой абсолютную семантическую прозрачность по соображениям безопасности или конфиденциальности. Определенные директивы Cache-Control предназначены для того, чтобы сервер мог указать, что некоторые объекты ресурсов или их части не могут кэшироваться ни при каких обстоятельствах.

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

Отклик, полученный со статусным кодом 200, 203, 206, 300, 301 или 410, может быть запомнен кэшем и использован в ответе на последующие запросы, если директива не препятствует кэшированию. Однако кэш, который не поддерживает заголовки Range и ContentRange, не должен кэшировать отклики 206 (Partial Content).

Отклик, полученный с любым другим статусным кодом, не должен отсылаться в ответ на последующие запросы, если только нет директив Cache-Control или других заголовков, которые напрямую разрешают это. К таким, например, относятся: заголовок Expires; maxage, mustrevalidate, proxyrevalidate, public или private директива Cache-Control.

Формирование откликов кэшей

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

Заголовки End-to-end (точка­точка) и Hop-by-hop (шаг­за-шагом)

Для определения поведения кэшей и некэширующих проксисерверов заголовки HTTP делят на две категории.

  • Заголовки End-to-end, которые должны быть пересланы конечному получателю запроса или отклика. Такие заголовки в откликах должны запоминаться как часть объекта кэша и пересылаться в любом отклике, полученном из записи кэша.
  • Заголовки Hop-by-hop, которые имеют смысл только для одноуровневого транспортного соединения, они не запоминаются кэшем и не переадресуются проксисерверами.

Следующие заголовки HTTP/1.1 относятся к категории hop-by-hop:

  • Connection
  • Keep-Alive
  • Public
  • Proxy-Authenticate
  • Transfer-Encoding
  • Upgrade

Все другие заголовки, определенные HTTP/1.1, относятся к категории end-to-end. Заголовки Hop-by-hop должны быть перечислены в заголовке Connection.

Немодифицируемые заголовки

Некоторые черты протокола HTTP/1.1, такие, как Digest Authentication, зависят от значения определенных заголовков end-to-end. Кэш или некэширующий прокси не должны модифицировать заголовок end-to-end, если только определение этого заголовка не требует или не разрешает этого.

Кэш или некэширующий прокси не должны модифицировать любое из следующих полей запроса или отклика или добавлять какие­-либо поля, если они еще не существуют:

  • Content-Location
  • Etag
  • Expires
  • Last-Modified

Кэш или некэширующий прокси не должны модифицировать или добавлять следующие поля в любых запросах и в откликах, которые содержат директиву notransform Cache-Control:

  • Content-Encoding
  • Content-Length
  • Content-Range
  • Content-Type

Кэш или некэширующий прокси могут модифицировать или добавлять эти поля в отклик, который не включает директиву notransform. Если же он содержит эту директиву, следует добавить предупреждение 14 (Transformation applied) (если оно еще не занесено в отклик).

Комбинирование заголовков

Когда кэш делает запрос серверу о пригодности ресурса и сервер выдает отклик 304 (Not Modified), кэш должен подготовить и отправить отклик, чтобы послать клиенту. Кэш использует тело объекта из записи в кэше при формировании отклика. Заголовки end-to-end, записанные в кэше, используются для конструирования отклика. Исключение составляют любые end-to-end заголовки, поступившие в рамках отклика 304, — они должны заместить соответствующие заголовки из записи в кэше. Если только кэш не решил удалить запись, он должен также заменить end-to-end заголовки своей записи соответствующими заголовками из полученного отклика.

Другими словами, набор end-to-end заголовков, полученный вместе с откликом, переписывает все соответствующие end-to-end заголовки из записи в кэше. Кэш может добавить к этому набору заголовки предупреждений.

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

Замечание. Это правило позволяет исходному серверу использовать отклик 304 (Not Modified) для актуализации любого заголовка, связанного с предыдущим откликом для того же объекта, хотя это может не всегда иметь смысл. Это правило не позволяет исходному серверу использовать отклик 304 (not Modified) для того, чтобы полностью стереть заголовок, который был прислан предыдущим откликом.

Комбинирование байтовых фрагментов

Отклик может передать только субдиапазон байтов тела объекта, либо потому, что запрос включает в себя один или более спецификаций Range, либо изза преждевременного обрыва соединения.

Если кэш запомнил не пустой набор субфрагментов объекта, а входящий отклик передает еще один фрагмент, кэш может комбинировать новый субфрагмент с уже имеющимся набором, если для обоих выполняются следующие условия:

  • оба приходящие отклика и запись в кэше должны иметь валидатор кэша;
  • оба валидатора кэша должны соответствовать функции сильного сравнения.

Если любое из условий не выполнено, кэш должен использовать только наиболее поздний частичный отклик и отбросить другую частичную информацию.

Каролина Попович
Каролина Попович
Евгений Виноградов
Евгений Виноградов

Прошел экстерном экзамен по курсу перепордготовки "Информационная безопасность". Хочу получить диплом, но не вижу где оплатить? Ну и соответственно , как с получением бумажного документа?

Р Алоев
Р Алоев
Россия
Татьяна Тренина
Татьяна Тренина
Россия, Челябинск