Отсутствует пользовательский заголовок с django, nginx и gunicorn

Отказ от ответственности:

Я работаю над проектом, в котором существует «огромное» веб-приложение с API для мобильных устройств, поэтому изменить API невозможно.

Это приложение было разработано давно, и над ним работали несколько разработчиков,

Сказав это, проблема заключается в следующем;

В API для мобильных устройств этого сайта (просто просматривает, чем возвращает данные json) код ищет токен, но делает это в заголовках запроса:

token = request.META.get('HTTP_TOKEN')

Когда я тестирую этот API локально, он работает нормально, но в продакшне нет, поэтому я пытаюсь выяснить, что происходит, и нашел это:

django преобразует заголовки, даже пользовательские заголовки, в ключи в request.META, я использую urllib2 и запросы для тестирования API, и проблема в производстве заключается в том, что на рабочем сервере request.META никогда не имеет ключа с именем HTTP_TOKEN, поэтому, выполняя небольшую отладку, я серьезно думаю, что проблема заключается в том, как мы обслуживаем приложение django.

Мы используем django1.3, nginx, gunicorn, virtualenvwrapper, python2.7.

Мой главный подозреваемый - nginx, я думаю, что nginx каким-то образом получает заголовок, но не пересылает его в django, я пытаюсь провести некоторое исследование по этому поводу, но я нашел только информацию о заголовках безопасности и пользовательских заголовках от nginx, но я не нашел doc или что-то о том, как сообщить nginx, что он разрешает этот заголовок, и не удалять его.

Мне нужна помощь здесь, первое, что нужно проверить, получает ли nginx заголовок, но я просто немного разбираюсь в nginx и не знаю, как сказать ему регистрировать заголовки запросов.

Спасибо

Обновить

файл конфигурации nginx


person diegueus9    schedule 04.11.2011    source источник
comment
Вы можете доказать это предположение? Зарегистрируйте запрос как от nginx, так и от django и убедитесь, что в заголовках HTTP действительно есть различия.   -  person Yuval Adam    schedule 04.11.2011
comment
Частично это проблема, при тестировании скрипт с использованием urllib2 и запросов я определяю заголовки, которые я отправляю, в представлении я печатаю заголовки, которые я получаю, на сервере разработки заголовки в порядке, но в производстве django не получает HTTP_TOKEN заголовок.   -  person diegueus9    schedule 04.11.2011
comment
С этим я ищу способ сказать заголовки запроса на печать nginx, но документ немного ужасен   -  person diegueus9    schedule 04.11.2011
comment
Является ли заголовок запроса буквально HTTP_TOKEN? Или только Токен?   -  person kolbyjack    schedule 11.11.2011
comment
TOKEN, но django добавляет HTTP_   -  person diegueus9    schedule 11.11.2011
comment
Ах, если бы это было первое, я бы не предложил underscores_in_headers. Если это просто токен, nginx должен передать его. Можете ли вы предоставить конфигурацию, которую вы используете для отправки запроса на ваш сервер?   -  person kolbyjack    schedule 11.11.2011
comment
Вы когда-нибудь понимали это @diegueus9? Кажется, у меня такая же проблема, когда я пытаюсь получить стандартный заголовок If-None-Match и If-Modified-Since. uwsgi_pass_header не помогает.   -  person Julian    schedule 07.06.2012
comment
@ Джулиан, на самом деле, ты не проверяешь ответ @ubiquitousthey?   -  person diegueus9    schedule 07.06.2012
comment
@diegues9 diegues9: ответ ubiquitousthey просто указывает, как решить проблему. Я попробовал это на короткое время, и казалось, что это не помогло, но я не слишком старался и, возможно, сделал это неправильно. Я нашел приемлемое обходное решение - см. мой ответ.   -  person Julian    schedule 07.06.2012
comment
@diegues9: я попробовал совет proxy_set_header, данный Dayo и ubiquitousthey, но он не сработал, хотя, как говорит Dayo, должен. Просто на практике так не бывает.   -  person Julian    schedule 08.06.2012


Ответы (5)


Если доступ к Django осуществляется с использованием uwsgi_pass, то в соответствующих местах...

# All request headers should be passed on by default     
# Make sure "Token" response header is passed to user 
uwsgi_pass_header  Token;

Если доступ к Django осуществляется с помощью fastcgi_pass, то в соответствующих местах...

# All request headers should be passed on by default     
# Make sure "Token" response header is passed to user 
fastcgi_pass_header  Token;

Если доступ к Django осуществляется с помощью proxy_pass, то в соответствующих местах...

# All request headers should be passed on by default
# but we can make sure "Token" request header is passed to Django 
proxy_set_header Token $http_token;

# Make sure "Token" response header is passed to user 
proxy_pass_header  Token;

Это должно помочь исключить возможность того, что Nginx не передает вещи из вашей проблемы.

person Dayo    schedule 11.11.2011
comment
Предполагая, что вы имели в виду gunicorn или ..., тогда ответ таков, что это директивы nginx. вездесущие вам давали какие-то ссылки ранее. - person Dayo; 12.11.2011
comment
Интересно отметить, что у меня лично были проблемы с передачей заголовков, имя которых содержит символы подчеркивания, при использовании uwsgi_pass_header. Например, заголовок AUTH_TOKEN никогда не достигнет Django, но при использовании AUTHTOKEN это произойдет! - person stephenmuss; 19.04.2012

В файле конфигурации nginx (например, mysite_nginx.conf) в разделе сервер добавьте этот параметр: uwsgi_pass_request_headers on;.

Например:

server {
    # the port your site will be served on
    listen      8000;

    ...

    underscores_in_headers on;
}

И если доступ к Django идет через uwsgi_pass, вам нужно добавить этот параметр uwsgi_pass_request_headers on; в раздел location.

Например:

location / {
    include     /etc/nginx/uwsgi_params; # the uwsgi_params file you installed
    uwsgi_pass_request_headers on;
    uwsgi_pass  django;
}
person M.Void    schedule 18.10.2016

Я думаю, это то, что вам нужно:

log_format combined '$remote_addr - $remote_user [$time_local]  '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent" "$http_http_token" "$upstream_http_http_token"'

чтобы логировать происходящее.

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

Вы можете найти документацию здесь:

Последняя запись, по-видимому, указывает на то, что nginx по умолчанию пропускает большинство заголовков.

person ubiquitousthey    schedule 08.11.2011

Я не нашел настоящего ответа, но смог найти обходной путь. У меня была такая же проблема со стандартными заголовками RFC if-none-match и if-modified-since, поэтому мое решение проверено для этих заголовков.

Добавлено в мою конфигурацию nginx:

uwsgi_param HTTP_IF_NONE_MATCH $http_if_none_match;
uwsgi_param HTTP_IF_MODIFIED_SINCE $http_if_modified_since;

Я не могу объяснить, почему nginx по умолчанию отказывается передавать эти заголовки в uwsgi. Этот конфиг заставляет это. Страницы теперь генерируют ошибки 304 по мере необходимости.

Для исходного вопроса о нестандартном заголовке «токен» это должно помочь:

uwsgi_param HTTP_TOKEN $http_token;
person Julian    schedule 07.06.2012

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

proxy_set_header X_FORWARDED_FOR # oops it never works. 1.16.1 on centos7
proxy_set_header X-FORWARDED-FOR # this will do the job

Итак, вы поняли. Подчеркивание никогда не могло появиться в настраиваемом имени переменной. Вместо этого используйте дефис.

Возможно, Nginx использует символы подчеркивания в некоторых грамматических случаях. Кто-то указал, что официальная ссылка будет оценена.

person W.Perrin    schedule 29.02.2020