Назад | Перейти на главную страницу

NGINX 301 и 302 обслуживают небольшое тело документа nginx. Любой способ удалить это поведение?

Мы заметили, что при использовании внутренней обработки 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, но вы должны осознавать все последствия:

  • Вы делаете много работы практически без пользы. Единственная логическая причина, по которой я могу отключить тело объекта, - это сэкономить на расходах на полосу пропускания, и действительно, это причина, о которой вы упомянули, но разница настолько минимальна, что маловероятно, что вы даже увидите разницу на графиках полосы пропускания.
  • Очень крошечная часть веб-клиентов не выполняет автоматически перенаправления 3xx. Эта доля была намного больше, когда был написан 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- *.

http://wiki.nginx.org/NginxHttpProxyModule#proxy_method