HTTP: создание заголовка ETag

Как создать HTTP-заголовок ETag для файла ресурсов?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
25
0
21 567
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Ответ принят как подходящий

Etag - это произвольная строка, которую сервер отправляет клиенту, которую клиент отправит обратно на сервер при следующем запросе файла.

Etag должен вычисляться на сервере на основе файла. Что-то вроде контрольной суммы, но вы можете не захотеть подсчитывать контрольную сумму для каждого отправляющего ее файла.

 server                client
 
        <------------- request file foo
 
 file foo etag: "xyz"  -------->
 
        <------------- request file foo
                       etag: "xyz" (what the server just sent)
 
 (the etag is the same, so the server can send a 304)

Я построил строку в формате «дата-метка-размер-файл номер инода». Таким образом, если файл был изменен на сервере после того, как он был передан клиенту, вновь созданный etag не будет соответствовать, если клиент повторно запросит его.

char *mketag(char *s, struct stat *sb)
{
    sprintf(s, "%d-%d-%d", sb->st_mtime, sb->st_size, sb->st_ino);
    return s;
}

Если mtime - это время последнего изменения файла, то для чего нужен размер и индексный дескриптор?

Steve 04.02.2010 06:20

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

Mark Harrison 04.02.2010 07:21

@MarkHarrison, зачем вам двойные кавычки вокруг etag? Это обязательная часть синтаксиса?

Pacerier 19.07.2012 00:02

От http://developer.yahoo.com/performance/rules.html#etags:

By default, both Apache and IIS embed data in the ETag that dramatically reduces the odds of the validity test succeeding on web sites with multiple servers.

...

If you're not taking advantage of the flexible validation model that ETags provide, it's better to just remove the ETag altogether.

Поскольку он изменяется всякий раз, когда изменяется представление ресурса, то как вы его создаете, полностью зависит от вас.

Вы должны попытаться создать его таким образом, чтобы дополнительно:

  1. не требует, чтобы вы повторно вычисляли его при каждом условном GET, и
  2. не меняется, если содержимое ресурса не изменилось

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

Использование номеров inode может привести к сбою в # 2, если вы измените свою файловую систему или обслуживаете контент с нескольких серверов.

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

Я бы рекомендовал не использовать их и вместо этого использовать заголовки, измененные последними.

У Askapache есть полезная статья по этому поводу. (поскольку они делают почти все, что кажется!)

http://www.askapache.com/htaccess/apache-speed-etags.html

Хм, это позор, надеюсь, они скоро вернутся, так как сайт стал кладезем советов!

Rich Bradshaw 03.02.2010 23:20

@RichBradshaw просто вопрос, как мы можем узнать последнюю измененную временную метку ресурса? Это полностью ручная операция после просмотра истории изменений БД? Или есть какие-то автоматические способы?

Supun Wijerathne 28.11.2017 09:46

Как сгенерировать apache etag по умолчанию в bash

for file in *; do printf "%x-%x-%x\t$file\n" `stat -c%i $file` `stat -c%s $file` $((`stat -c%Y $file`*1000000)) ; done

Даже когда я искал что-то в точности похожее на etag (браузер запрашивает файл только в том случае, если он был изменен на сервере), он никогда не работал, и я закончил использовать трюк GET (добавив временную метку в качестве аргумента получения в файлы js ).

Я использовал Adler-32 как сокращатель HTML-ссылок. Я не уверен, хорошая ли это идея, но пока не заметил никаких дубликатов. Может работать как генератор etag. И это должно быть быстрее, чем попытки хеширования с использованием схемы шифрования, такой как sha, но я не проверял это. Я использую следующий код:

 shortlink = str(hex(zlib.adler32(link)+(2**32-1)/2))[2:-1]

Пример кода Марка Харрисона аналогичен тому, что использовался в Apache 2.2. Но такой алгоритм вызывает проблемы с балансировкой нагрузки, когда у вас есть два сервера с одним и тем же файлом, но inode файла отличается. Вот почему в Apache 2.4 разработчики упростили схему ETag и удалили часть inode. Также, чтобы сделать ETag короче, обычно они кодируются в шестнадцатеричном формате:

    
<inttypes.h>
    
    
char *mketag(char *s, struct stat *sb)
{
    sprintf(s, "\"%" PRIx64 "-%" PRIx64 "\"", sb->st_mtime, sb->st_size);
    return s;
}
    

или для Java

 etag = '"' + Long.toHexString(lastModified) + '-' +
                                Long.toHexString(contentLength) + '"';

для C#

// Generate ETag from file's size and last modification time as unix timestamp in seconds from 1970
public static string MakeEtag(long lastMod, long size)
{
    string etag = '"' + lastMod.ToString("x") + '-' + size.ToString("x") + '"';
    return etag;
}

public static void Main(string[] args)
{
    long lastMod = 1578315296;
    long size = 1047;
    string etag = MakeEtag(lastMod, size);
    Console.WriteLine("ETag: " + etag);
    //=> ETag: "5e132e20-417"
}

Функция возвращает ETag, совместимый с Nginx. См. сравнение ETags с разных серверов

Другие вопросы по теме