Мы заметили, что при использовании внутренней обработки 301 и 302 nginx nginx будет обслуживать небольшое тело документа с соответствующим заголовком Location: ...
Что-то вроде (в html): 301 редирект - nginx.
В соответствии с приведенным выше поведением также отправляется заголовок типа содержимого text / html и содержимого.
Мы делаем много 302 и около 301 редиректов, вышеупомянутое поведение, на наш взгляд, является потерей полосы пропускания.
Есть ли способ отключить это поведение?
Одна идея, которая пришла нам в голову, заключалась в том, чтобы установить error_page 301 302 в пустой текстовый файл. Мы еще не тестировали это, но я предполагаю, что даже с учетом вышеизложенного будут отправлены заголовки content-type и content-length (0).
Итак, есть ли чистый способ отправить «без тела» 301/302 редирект с помощью nginx?
Тщательно обдумайте, о чем вы просите, и решительно подумайте не делаю этого.
RFC 2616 указывает, что должны присутствовать тела сущностей, которые вы хотите удалить.
10.3.2 301 перемещен навсегда
Новый постоянный URI ДОЛЖЕН быть указан в поле Location в ответе. Если метод запроса не был HEAD, объект ответа ДОЛЖЕН содержать короткую гипертекстовую заметку с гиперссылкой на новый URI.
и...
10.3.3 302 Найдено
Временный URI СЛЕДУЕТ указывать в поле Location в ответе. Если метод запроса не был HEAD, объект ответа ДОЛЖЕН содержать короткую гипертекстовую заметку с гиперссылкой на новый URI.
В этом контексте СЛЕДУЕТ определять в RFC 2119:
Это слово или прилагательное «РЕКОМЕНДУЕТСЯ» означает, что при определенных обстоятельствах могут существовать веские причины для игнорирования конкретного пункта, но все последствия должны быть поняты и тщательно взвешены, прежде чем выбирать другой курс.
Теперь вы можете сделать это, не нарушая RFC, но вы должны осознавать все последствия:
curl
, который до сих пор широко используется.Эта рекомендация была несколько смягчена RFC 7231, который просто говорит (как для 301, так и для 302):
Полезные данные ответа сервера обычно содержат короткую гипертекстовую заметку с гиперссылкой на новый URI.
Полезные данные ответа сервера обычно содержат короткую гипертекстовую заметку с гиперссылкой на разные URI.
Да, ты можешь АБСОЛЮТНО сделай это с NGINX!
Просто установите обработчик исключений, a.k.a. error_page
, чтобы обработать необходимые ответы. Обязательно установите его таким образом, чтобы страница с ошибкой не изменила код состояния HTTP, например, не используйте =
параметр (или используйте его для жесткого кодирования любого кода, который вам нужен).
Убедись в return
ответ с кодом состояния возврата, который позволяет вам дополнительно установить [text]
, не URL
.
Уточнить default_type
из ""
, который, кажется, удаляет Content-Type
заголовок
Вот полный код, также у меня GitHub в StackOverflow.cnst.nginx.conf
репозиторий:
# cat sf.421976.301-302-redirect-w-no-http-body-text.nginx.conf | sed 's#^#\t#g'
server {
listen 1976;
error_page 301 302 @30x; # keep original HTTP status code w/o `=`
location @30x {
default_type ""; # will remove Content-Type completely
# `300` is a filler: client will get the original HTTP status code
return 300;
}
return 301 http://example.su/test;
}
Вот подтверждение того, что он работает правильно:
% curl -i localhost:1976 | sed 's#^#\t#g'
HTTP/1.1 301 Moved Permanently
Server: nginx/1.2.1
Date: Mon, 28 Aug 2017 22:02:41 GMT
Content-Length: 0
Connection: keep-alive
Location: http://example.su/test
%
Я пробовал это в браузерах, и там он тоже работал нормально.
P.S. Другой вариант - изменить исходный код и отредактировать ngx_http_error_301_page
и другие переменные, но зачем идти по сложному пути ?! ^ _ ^
Это немного уродливо, но, возможно, вы могли бы проксировать запросы 301/302 и использовать proxy_method для изменения запросов GET на HEAD. Я не тестировал его, но запросы заголовка должны отправлять только заголовки без ответов или (надеюсь) заголовки content- *.