Как сервер вычисляет Etag при скачивании файла

Как сервер вычисляет Etag при скачивании файла какой алгоритм или какая функция это делает какие параметры файла участвуют в создании ETag

Server: ddos-guard
Connection: keep-alive
Keep-Alive: timeout=60
Date: Thu, 21 Jul 2022 20:29:30 GMT
Content-Type: application/octet-stream
Content-Length: 13063421
Last-Modified: Tue, 09 Jun 2020 12:57:12 GMT
ETag: "10cd3c4-5a7a644121a00"
Accept-Ranges: bytes
Content-Range: bytes 4554439-17617859/17617860
Strict-Transport-Security: max-age=31536000;```

Ответы (2 шт):

Автор решения: Ein

Стандарт не регламентирует способ генерации etag: rfc7232 - 2.3.1

For example, a resource that has implementation-specific versioning applied to all changes might use an internal revision number, perhaps combined with a variance identifier for content negotiation, to accurately differentiate between representations. Other implementations might use a collision-resistant hash of representation content, a combination of various file attributes, or a modification timestamp that has sub-second resolution.

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

Если же вас интересуют именно конкретные реализации, то можно посмотреть это в исходниках nginx или apache.

→ Ссылка
Автор решения: Michael Sapach

Сервера, как и серверные приложения, для формирования Etag используют что-то простое для получения, не требующее вычитывания всего файла. В приведенном вами примере Etag представляет из себя размер файла в 16-чной форме (10cd3c4 = 17617860, оно же в заголовке Content-Range: bytes 4554439-17617859/17617860 в обычной 10-чной форме), затем символ "минус", затем, предполагаю, время изменения файла в 16-чной форме (оно же в заголовке Last-Modified: Tue, 09 Jun 2020 12:57:12 GMT, но мне лень проверять, извините). Форма эта свободная, каждый сервер может это кодировать по-своему, достигая своих целей, вид этот может отличаться от версии к версии, и совершенно ни к чему подстраиваться под это.

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

Из этого следует, что эффективнее в Etag включать или хэшировать исключительно ту информацию, которая напрямую определяет уникальность выдаваемого контента, и которую вы можете легко и просто проверить, собрав заголовки запроса, и прочую имеющуюся у вас, как разработчика, информацию, такую, как максимальное время изменения всех участвующих в выдаче файлов/таблиц (можно в то же время для этого использовать вычисление строки для Last-Modified, сравнивая ее с входящей строкой If-Modified-Since, но можно этого не делать, а запаковать и это в Etag в удобном для вас виде, и сравнивать с If-None-Match, что проще), и/или имя/номер пользователя/группы/сессии, если имеется фильтрация контента для разных пользователей/групп, возможно, язык контента, если используется многоязыковой контент, и т.д. Просто собираете эту информацию из имеющихся источников (файлы, таблицы, входящие заголовки) в Etag и сравниваете с поступившей информацией в заголовке If-None-Match. Если равны, то 304, иначе 200 с выдачей контента. Вполне можно использовать тот же md5 для объединения всей полезной для идентификации информации в единый хэш.

→ Ссылка