#django #configuration #http-headers #nginx #gunicorn
#django #конфигурация #http-заголовки #nginx #gunicorn
Вопрос:
Отказ от ответственности:
Я работаю в проекте, где существует «огромное» веб-приложение, у которого есть API для мобильных телефонов, поэтому изменить API не вариант.
Это приложение было разработано давно, и над ним работали несколько разработчиков,
Сказав это, проблема заключается в следующем;
В API для мобильных устройств этого сайта (просто просматривает, а не возвращает данные json) код ищет токен, но делает это в заголовках запроса:
token = request.META.get('HTTP_TOKEN')
Когда я тестирую этот API локально, работает нормально, но в рабочей среде нет, поэтому я пытаюсь выяснить, что происходит, и нашел это:
django преобразует заголовки, даже пользовательские заголовки, в ключи в запросе.МЕТА, я использую urllib2 и запросы для тестирования api, и проблема в производстве заключается в том, что на рабочем сервере запрос.У META никогда не было ключа с именем HTTP_TOKEN, поэтому, выполнив небольшую отладку, я серьезно думаю, что проблема заключается в том, как мы обслуживаем приложение django.
Мы используем django1.3, nginx, gunicorn, virtualenvwrapper, python2.7.
Мой главный подозреваемый — nginx, я думаю, каким-то образом nginx получает заголовок, но не пересылает его в django, я пытаюсь провести некоторое исследование по этому поводу, но я нашел только информацию о заголовках безопасности и пользовательских заголовках из nginx, но я не нахожу документ или что-то о том, как сообщить nginx, что этот заголовок разрешен, и не удалять его.
Мне нужна помощь здесь, первое, что нужно проверить, получает ли nginx заголовок, но я просто немного знаю о nginx, и я не знаю, как указать ему регистрировать заголовки запросов.
Спасибо
Обновить
Комментарии:
1. Можете ли вы доказать это предположение? Зарегистрируйте запрос как от nginx, так и от django и убедитесь, что в заголовках HTTP действительно есть разница.
2. Частично это проблема, при тестировании скрипта с использованием urllib2 и запросов я определяю заголовки, которые я отправляю, в представлении я печатаю заголовки, которые я получаю, на сервере разработки заголовки в порядке, но на производстве django не получает заголовок HTTP_TOKEN.
3. При этом я ищу способ указать заголовки запросов на печать nginx, но документ немного ужасен
4. Заголовок запроса буквально HTTP_TOKEN? Или просто токен?
5. ТОКЕН, но django добавляет HTTP_
Ответ №1:
Если доступ к 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 не передает информацию из вашей проблемы.
Комментарии:
1. Предполагая, что вы имели в виду «gunicorn или …», тогда ответ заключается в том, что это директивы nginx. повсеместно они дали вам несколько ссылок ранее.
2. Интересно отметить, что у меня лично были проблемы с передачей заголовков, имя которых содержит символы подчеркивания при использовании uwsgi_pass_header. Например, заголовок AUTH_TOKEN никогда не достигнет Django, но при использовании AUTHTOKEN это произойдет!
Ответ №2:
В вашем файле конфигурации nginx (например, mysite_nginx.conf) в разделе server добавьте этот параметр: 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;
}
Ответ №3:
Я думаю, это то, что вам нужно:
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 в модуле восходящего прокси, чтобы узнать, как передавать нужные вам заголовки.
Вы можете найти документацию здесь:
- http://wiki.nginx.org/HttpLogModule
- http://wiki.nginx.org/NginxHttpUpstreamModule
- http://wiki.nginx.org/NginxHttpProxyModule#proxy_set_header
- http://wiki.nginx.org/HttpProxyModule#proxy_pass_request_headers
Последняя запись, похоже, указывает на то, что nginx передает большинство заголовков по умолчанию
Ответ №4:
Я не нашел реального ответа, но смог найти обходной путь. У меня была такая же проблема со стандартными заголовками RFC, если они не совпадают и если изменены с тех пор, поэтому мое решение протестировано для этих заголовков.
Добавлено в мою конфигурацию nginx:
uwsgi_param HTTP_IF_NONE_MATCH $http_if_none_match;
uwsgi_param HTTP_IF_MODIFIED_SINCE $http_if_modified_since;
Я не могу объяснить, почему nginx отказывается передавать эти заголовки в uwsgi по умолчанию. Эта конфигурация вызывает его. Теперь страницы генерируют 304 по мере необходимости.
Для исходного вопроса о нестандартном заголовке «token» это должно сработать:
uwsgi_param HTTP_TOKEN $http_token;
Ответ №5:
Приведенных выше ответов достаточно, чтобы мы могли найти способ. Но все еще есть досадный момент, который нам нужно знать. Да, это очень раздражает.
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
в некоторых грамматических случаях используются символы подчеркивания. Кто-то указал, что официальная ссылка будет оценена.
Ответ №6:
Это зависит от того, как называется пользовательский заголовок. Мой был в формате «SomethingLike.this», он содержит точку. Не удалось переименовать заголовок в запросе, потому что это не наш код. Так что написание этого не сработало бы:
proxy_set_header SomethingLike.this $http_somethinglike.this;
proxy_pass_header SomethingLike.this;
Также это не сработало бы:
underscores_in_headers on;
потому что мне понадобится dots_in_headers
директива, которой не существует.
Но я обнаружил, что могу передать ВСЕ заголовки, просто добавив:
ignore_invalid_headers off;
Передача всех заголовков может быть небезопасной, пожалуйста, используйте с осторожностью.