Хабрахабр

[Перевод] Ненужные HTTP-заголовки

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

Самые известные — Content-Type и Content-Length, это почти универсальные хедеры. Большинство разработчиков знают о важных и нужных HTTP-заголовках. Несмотря на широкую поддержку в браузерах, лишь немногие их используют. Но в последнее время для повышения безопасности начали использоваться заголовки вроде Content-Security-Policy и Strict-Transport-Security, а для повышения производительности — Link rel=preload.

Мы можем это доказать с помощью HTTP Archive, проекта под управлением Google и спонсируемого Fastly, который каждый месяц при помощи WebPageTest скачивает 500 000 сайтов и выкладывает результаты в BigQuery.
Вот 30 самых популярных заголовков ответов по данным HTTP Archive (на основе количества доменов в архиве, которые выдают каждый заголовок), и примерная оценка полезности каждого из них: В то же время есть много чрезвычайно популярных заголовков, которые вообще не новые и не очень полезные.

Заголовок

Запросов

Доменов

Статус

date

48779277

535621

Требуется по протоколу

content-type

47185627

533636

Обычно требуется браузером

server

43057807

519663

Необязателен

content-length

42388435

519118

Полезен

last-modified

34424562

480294

Полезен

cache-control

36490878

412943

Полезен

etag

23620444

412370

Полезен

content-encoding

16194121

409159

Требуется для сжатого контента

expires

29869228

360311

Необязателен

x-powered-by

4883204

211409

Необязателен

pragma

7641647

188784

Необязателен

x-frame-options

3670032

105846

Необязателен

access-control-allow-origin

11335681

103596

Полезен

x-content-type-options

11071560

94590

Полезен

link

1212329

87475

Полезен

age

7401415

59242

Полезен

x-cache

5275343

56889

Необязателен

x-xss-protection

9773906

51810

Полезен

strict-transport-security

4259121

51283

Полезен

via

4020117

47102

Необязателен

p3p

8282840

44308

Необязателен

expect-ct

2685280

40465

Полезен

content-language

334081

37927

Спорно

x-aspnet-version

676128

33473

Необязателен

access-control-allow-credentials

2804382

30346

Полезен

x-robots-tag

179177

24911

Не имеет значения для браузеров

x-ua-compatible

489056

24811

Необязателен

access-control-allow-methods

1626129

20791

Полезен

access-control-allow-headers

1205735

19120

Полезен

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

Тщеславие (server, x-powered-by, via)

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

1. Server: apache
X-Powered-By: PHP/5. 1 varnish, 1. 1
Via: 1. 1 squid

Чаще всего это строка вроде "apache" или "nginx". RFC7231 позволяет включать в ответ сервера заголовок Server, указывая конкретный софт на сервере, который используется для выдачи контента. Тем не менее, сегодня это третий по популярности серверный HTTP-заголовок в интернете. Хотя заголовок разрешён, он не обязательный и не особо ценный для разработчиков или конечных пользователей.

Самые популярные ответы включают в себя "ASP.net", "PHP" и "Express". X-Powered-By — самый популярный заголовок из тех, что не определены никаким стандартом, и у него похожая цель: обычно он указывает платформу приложений, на которой работает сервер. Опять же, это не несёт никакой ощутимой пользы и просто занимает место.

Его обязан (по RFC7230) добавлять в запрос каждый прокси, через который проходит запрос — для идентификации прокси. Возможно, более спорным можно считать Via. Удаление (или не добавление) такого заголовка может привести к циклу переадресации прокси. Это может быть имя хоста прокси, но чаще общий идентификатор вроде "vegur", "varnish" или "squid". Но интересно, что он также добавляется в ответ на обратном пути к браузеру — и здесь выполняет просто информационную функцию: никакие браузеры ничего не с ним делают, поэтому достаточно безопасно избавиться от него, если хотите.

Устаревшие стандарты (P3P, Expires, X-Frame-Options, X-UA-Compatible)

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

P3P: cp="this is not a p3p policy"
Expires: Thu, 01 Dec 1994 16:00:00 GMT
X-Frame-Options: SAMEORIGIN
X-UA-Compatible: IE=edge

Я понятия не имел, что это такое. P3P — забавная штучка. Ну так это оно или нет? Ещё забавнее, что одно из самых распространённых содержаний заголовка P3P — «Это не правило P3P».

Были разногласия по поводу того, как отображать данные в браузерах, и только один браузер реализовал поддержку этого заголовка — Internet Explorer. Тут история восходит к попытке стандартизировать машиночитаемые правила приватности. Некоторые сайты даже установили правила несоблюдения P3P, как в примере выше, хотя делать так весьма сомнительно. Но даже в нём P3P не имел никакого визуального эффекта для пользователя; он просто должен был присутствовать, чтобы разрешить доступ к сторонним кукам во фреймах.

Нечего и говорить, что чтение сторонних куков вообще обычно плохая идея, так что если вы этого не делаете, то вам и не нужно устанавливать заголовок P3P!

Если заголовок Cache-Control содержит директиву max-age, то любой заголовок Expires в том же ответе игнорируется. Expires просто невероятно популярен с учётом того, что Cache-Control имеет преимущество перед Expires уже в течение 20 лет. Конечно, ведь проще всего копипастнуть дату из спецификаций. Но огромное количество сайтов устанавливает оба этих заголовка, а Expires чаще всего ставят на дату Thu, 01 Dec 1994 16: 00: 00 GMT, чтобы контент не кэшировался.

Если у вас заголовок Expires с датой из прошлого, просто замените его на: Но просто незачем это делать.

Cache-Control: no-store, private

(no-store — слишком строгая директива не записывать контент в постоянное хранилище, так что вы можете предпочесть no-cache ради лучшей производительности, например, для навигации назад/вперёд или возобновления «спящих» вкладок в браузере)

Он говорит браузерам, что вы отказываетесь отдавать контент во фрейм на другом сайте: как правило, это хорошая защита от кликджекинга. Некоторые инструменты проверки сайтов посоветуют добавить заголовок X-Frame-Options со значением 'SAMEORIGIN'. Но того же эффекта можно достигнуть другим заголовком с более последовательной поддержкой и более надёжным поведением:

Content-Security-Policy: frame-ancestors 'self'

Вероятно, в наше время можно обойтись без X-Frame-Options. Здесь есть дополнительная выгода, потому что заголовок CSP вы всё равно должны отдавать по иным причинам (о них позже).

Даже в нормальном режиме браузер думал, что для правильного рендеринга может понадобиться более ранняя версия движка. Наконец, ещё в IE9 компания Microsoft представила «режим совместимости», который отображал страницу с помощью движка IE8 или IE7. Фактически, это стало стандартной частью многих фреймворков вроде Bootstrap. Эти эвристики не всегда работали корректно, и разработчики могли переопределить их, используя заголовок или метатег X-UA-Compatible. И если вы активно поддерживаете сайт, то очень маловероятно, что на нём используются технологии, которые запустят режим совместимости. Сейчас этот заголовок практически бесполезен: очень мала доля браузеров, которые понимают его.

Данные для отладки (X-ASPNet-Version, X-Cache)

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

2. X-Cache: HIT
X-Request-ID: 45a336c7-1bd5-4a06-9647-c5aab6d5facf
X-ASPNet-Version: 3. 32
X-AMZN-RequestID: 0d6e39e2-4ecb-11e8-9c2d-fa7ae01bbebc

Обычно это артефакты использования определённых серверных фреймворков, софта или сервисов конкретных поставщиков (например, последний заголовок типичен для AWS). На самом деле, эти «неизвестные» заголовки не выдумали разработчики.

Когда отладка включена, то добавляется ещё больше, например, Fastly-Debug-Path и Fastly-Debug-TTL. Заголовок X-Cache добавляет Fastly (и другие CDN), вместе с другими специфичными хедерами, такими как X-Cache-Hits и X-Served-By.

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

Недоразумения (Pragma)

Не ожидал, что в 2018 году придётся упоминать заголовок Pragma, но согласно HTTP Archive он по-прежнему в топе (11-е место). Его не только объявили устаревшим ещё в 1997 году, но он вообще никогда не задумывался как заголовок ответа, а только как часть запроса.

Pragma: no-cache

Но сегодня практически нулевая вероятность, что кто-то понимает Pragma в контексте ответа, но не понимает Cache-Control. Тем не менее его настолько широко используют в качестве заголовка ответа, что некоторые браузеры даже распознают его и в этом контексте. Если хотите запретить кэширование, всё что вам нужно — это Cache-Control: no-store, private.

Не-браузеры (X-Robots-Tag)

Один заголовок в нашем топ-30 не является заголовком для браузера. X-Robots-Tag предназначен для краулеров, таких как боты Google или Bing. Поскольку для браузера он бесполезен, то можете установить такой ответ только на запросы краулеров. Или вы решите, что это затрудняет тестирование или нарушает условия использования поисковой системы.

Баги

Наконец, стоит закончить почётном упоминанием простых ошибок. Заголовок Host имеет смысл в запросе, но если он встречается в ответе, то вероятно ваш сервер неправильно настроен (и я хотел бы знать, как именно). Тем не менее 68 доменов в HTTP Archive возвращают заголовок Host в своих ответах.

Удаление заголовков на edge-сервере CDN

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

Server;
unset resp.http. unset resp.http. X-Generator; X-Powered-By;
unset resp.http.

Cookie:debug && !req.http. if (!req.http. Debug)

В следующей статье я расскажу о лучших практиках для действительно нужных заголовков и как активировать их на edge-сервере CDN.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть