Request header or cookie too large - nginx

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

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

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

Техническая составляющая

Часто даже крупные компании не следят за количеством Cookies и их размером на своем сайте, в итоге посетители сайта получают ошибку:

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

Лимиты в браузерах

Согласно исследованию, в настоящий момент мы знаем, что браузер должен иметь возможность принимать не менее 300 файлов cookie с максимальным размером 4096 байт , как предусмотрено RFC 2109 (#6.3), RFC 2965 (#5.3) и RFC 6265. (включая все параметры, а не только само значение). В то время как большинство браузеров придерживаются RFC (вы можете проверить фактические ограничения браузеров и даже протестировать свой браузер в режиме реального времени здесь ).

Несмотря на RFC по размеру файлов cookie, разные браузеры реализуют эти ограничения по-разному:

  • Google Chrome - 4096 байт
  • Internet Explorer - 5117 байт
  • Firefox - 4097 байт
  • Microsoft Edge — 4097 байт

Обычно разрешено следующее:

  • Всего 300 куки
  • 4096 байт на куки
  • 20 файлов cookie на домен
  • 81920 байт на домен

Лимиты в nginx

По-умолчанию nginx может обработать только 8 килобайт, фактически это 2 полностью заполненных куки-значения (2 куки):

large_client_header_buffers 4 8k

где:

  • 4 - максимальное количество буферов (нас не особо волнует)
  • 8k - максимальный размер одного буфера, используемого для чтения одного заголовка запроса клиента

Напоминаю: все наши куки это один заголовок, именно поэтому 2 куки * 4096 байт = 8k

Что говорит документация:

  1. размер строки запроса не может превышать размер одного буфера, в противном случае клиенту возвращается ошибка 414 (Request-URI Too Large).
  2. поле заголовка запроса также не может превышать размер одного буфера, в противном случае клиенту будет возвращена ошибка 400 (Bad Request).

Нюансы, как мне кажется несущественные для нас в настоящий момент: 

  • буферы выделяются только по запросу.
  • если после завершения обработки запроса соединение переходит в состояние keep-alive, эти буферы освобождаются.
  • если директива указана на уровне сервера, можно использовать значение с сервера по умолчанию. Подробности приведены в разделе “Virtual server selection”.

Что делать

Мы знаем, что браузер может отправить нам 600 cookies по 4096 байт каждую, что в итоге 2457600 байт или 2.4576 мегабайта.

Поэтому, мы сконфигурируем nginx увеличивая значение размера буфера до 2 мегабайт:

server {
  ...
  large_client_header_buffers 4 3m;
  ...
}

А если вдруг браузер отправит нам больше, то я могу предложить такой подход:

  • каждый раз, когда браузер нам отправляет кукиес, мы проверяем strlen(serialize($_COOKIE))
  • если значение получается более 50% ожидания (например больше 1 мб, то удаляем старые cookies)

И не забываем, что например в chrome куки теперь хранятся 400 дней. На этом все, всем удачки.


11.09.2021 07:08

Комментарии

Комментариев пока нет.


Copyrights © 2007 - 2026 YaPro.Ru