[Перевод] Пара HTTP-заголовков, о которых, похоже, не знают разработчики
Вот какое дело: как показывают мои изыскания, большинство веб-разработчиков поразительно мало знают об HTTP-заголовках или, в целом, о стандарте HTTP. Я имею в виду, что я понимаю то, что во многих университетах и школах, вероятно, этому не учат (там, где я учился, определённо, так и было). А кто будет, сидя дома праздным воскресным утром, думать о том, чтобы развлечь себя чтением стандарта HTTP? Да никто. Знаю, но… есть одно важное обстоятельство: отсутствие хоть какого-то понимания стандарта HTTP — это зияющая дыра в знаниях веб-разработчиков, в знаниях многих из тех, кто это читает. Предлагаю это исправить.
Что представляют собой HTTP-заголовки
HTTP-заголовки предназначены для организации обмена метаданными о запросах и ответах между клиентами и серверами.
Клиент и сервер передают друг другу в заголовках дополнительную информацию. Заголовки имеются и в запросах, и в ответах.
Клиент (браузер, команда curl
и так далее) может отправить серверу заголовок Accept: text/html
для того чтобы указать на то, что ему хотелось бы, чтобы запрос оформлялся бы в виде HTML-документа. Или заголовок может быть таким: Accept: /
. Тем самым клиент сообщит серверу о том, что сервер может отправить ему всё что угодно, так как клиент способен разобраться с любыми данными, которые получит от сервера.
Сервер может отправить клиенту ответ с заголовком Cache-Control: public, max-age=600
. Фрагмент public
этого заголовка указывает на то, что возвращённый документ может быть кеширован в любом кеше. Ответ сервера не предназначен лишь для одного конкретного пользователя. А фрагмент max-age=600
говорит о том, что через 600 секунд материал необходимо из кеша удалить.
В результате мы можем сказать, что HTTP-заголовки состоят из двух частей, разделённых двоеточием. Это — имя заголовка, за которым следует значение. Имена заголовков нечувствительны к регистру.
Изучение существующих заголовков
Лучший способ изучения HTTP-заголовков, у которых уже имеются определённые имена, которым уже назначены роли в клиент-серверном взаимодействии, заключается в посещении соответствующего раздела сайта MDN.
Дело в том, что сервер и клиент могут договориться об использовании любого количества HTTP-заголовков, имеющих произвольные имена и значения. Но я полагаю, что нет смысла в изобретении новых HTTP-заголовков для своего приложения до проверки официального списка существующих заголовков. Высока вероятность того, что кому-то уже был нужен заголовок для решения точно такой же задачи, которую нужно решить «изобретателю».
Главная причина, по которой нежелательно «изобретать колесо» в сфере HTTP-заголовков, используемых неким приложением, заключается в том, чтобы не усложнять жизнь пользователям этого приложения. Есть и ещё одна причина — к существующим HTTP-заголовкам уже имеется документация.
Я сейчас работаю над приложением, которому нужно обращаться к множеству различных API. И я могу сказать, что я возблагодарил бы судьбу, если бы все разработчики всех приложений могли бы в один прекрасный день начать пользоваться одними и теми же заголовками. Многие из этих API придерживаются стандартов. На самом деле — большая их часть. Их, определённо, больше 50%. Но, по моим скромным оценкам, около 30% API стандартов не придерживается. Один из трёх API, который я интегрировал в свой проект, вынуждает меня использовать заголовки, созданные специально для него его разработчиками, а документация подобных API никогда в полной мере не объясняет особенности поведения таких заголовков.
Необоснованно сложным оказывается написание кода обработки заголовков для API, когда для работы с разными API требуется отправлять одну и ту же информацию, оформленную множеством различных способов. Особенно — если все эти «различные способы» как следует не документированы. А дело тут в том, что, будем откровенны, документацию мы писать не умеем. Поэтому предлагаю сделать жизнь пользователей наших систем чуть лучше и просто использовать заголовки, которые уже хорошо документированы.
Первый HTTP-заголовок, о котором знает слишком мало разработчиков: Authorization
Не знаю, как ещё это выразить, но… заголовок Authorization
предназначен для авторизации. Знаю — это шокирующая правда. А если серьёзно, то, если вы ожидаете запросов к серверу, в которых клиент должен отправлять какую-то аутентификационную информацию, вроде ключей API, то, пожалуйста, используйте этот заголовок. Давайте просто все решим, что с этого момента мы будем помещать данные для авторизации во всех API в заголовок Authorization
. Это позволит нам сделать нашу жизнь намного проще.
Давайте не будем изобретать собственные заголовки вроде PRIVATE-TOKEN
, или DD-API-KEY
, или X-SF-Token
и не будем запихивать токены авторизации в параметры GET
или POST
. Давайте просто остановимся на заголовке Authorization
. Пользоваться им очень просто. Данные в нём передаются так:
Authorization:
Так как существует множество способов аутентификации на сервере, заголовок Authorization
поддерживает несколько стандартных типов аутентификации. Именно по этой причине тут имеется фрагмент
. Самыми распространёнными типами аутентификации являются Basic
и Bearer
. Последний используется для OAuth2
.
Фрагмент authorisation-parameters
— это конкретные данные, имеющие отношение к авторизации (имя пользователя и пароль, токены и так далее), закодированные в соответствии с правилами выбранного типа авторизации.
Второй HTTP-заголовок, о котором знает слишком мало разработчиков: Retry-After
Когда вы реализуете в своём API систему ограничения частоты запросов, используйте этот заголовок для того чтобы сообщить вызывающей стороне о том, сколько времени она должна ждать прежде чем делать новый запрос к вашему API.
Вообще — заголовок Retry-After
был спроектирован для использования в следующих ответах:
503
—Service Unavailable
.429
—Too Many Requests
. Этот код ответа используется для ограничения частоты запросов.Очень редко им пользуются в ответе с кодом
301
—Moved Permanently
.
В этом заголовке сервер должен вернуть либо целое число, представляющее количество секунд, которое должно пройти перед повторным выполнением запроса, либо значение, содержащее дату и время, после наступления которых можно выполнить повторный запрос.
Retry-After:
Retry-After:
Всё это значит, что для решения подобных задач не нужно изобретать собственные заголовки, которые могут называться X-Rate-Limit-Remaining-Seconds
или X-RateLimit-Reset
. Ведь тот, кому это нужно, всегда может воспользоваться заголовком Retry-After
.
Итоги
Итак, теперь вы кое-что знаете об HTTP-заголовках, и о том, как с ними разумнее всего обращаться. А теперь расскажите об этом другим. И, пожалуйста, пользуйтесь описанными тут двумя заголовками для решения задач авторизации и ограничения частоты запросов к серверу, вместо того, чтобы изобретать что-то своё.
О, а приходите к нам работать?