缺少 django、nginx 和 Gunicorn 的自定义标头
免责声明:
我正在一个项目中工作,其中存在一个“巨大”的 Web 应用程序,该应用程序具有适用于手机的 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 只了解一点,我不知道如何告诉它记录请求的标头。
谢谢
更新
Disclaimer:
I'm working in a project where exist an "huge" webapp that have an api for mobiles, so change the api is not an option.
This application was developed time ago and several developers have worked on it,
Having said that, the problem is this;
In the api for mobile of this site (just views than returns json data), the code is looking for a token but does in the headers of request:
token = request.META.get('HTTP_TOKEN')
When I test this api locally, works fine, but in production doesn't, so, I try to figure out whats going on and found this:
django converts headers, even custom headers to keys in request.META, I use urllib2 and requests for test the api and the problem in production is that in production server the request.META never has a key called HTTP_TOKEN, so, doing a little of debug I seriously think the problem is the way we serve the django application.
We are using django1.3, nginx, gunicorn, virtualenvwrapper, python2.7.
My prime suspect is nginx, I think, in someway nginx receive the header but don' forward it to django, I try to do some research about this, but I only found infor about security headers and custom headers from nginx, but I dont find doc or something about how to tell nginx that allows that header and don't remove it.
I need help here, the first thing is test if nginx receives the header, but I just know a little about nginx and I don't know how to tell it to log the headers of requests.
Thanks
Update
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
如果使用 uwsgi_pass 访问 Django,则在适当的位置 ...
如果使用 fastcgi_pass 访问 Django,则在适当的位置 ...
如果使用 proxy_pass 访问 Django,则在适当的位置)...
这些应该有助于消除 Nginx 没有从您的问题中传递信息的可能性。
If Django is accessed using uwsgi_pass, then in the appropriate location(s) ...
If Django is accessed using fastcgi_pass, then in the appropriate location(s) ...
If Django is accessed using proxy_pass, then in the appropriate location(s) ...
These should help eliminate the possibility that Nginx is not passing things along from your issue.
在 nginx 配置文件 (fe mysite_nginx.conf) 的 server 部分中添加以下参数:
uwsgi_pass_request_headers on;
。例如:
如果通过uwsgi_pass访问Django,则需要在location部分添加
uwsgi_pass_request_headers on;
这一参数。例如:
In your nginx configuration file (f.e. mysite_nginx.conf) in the server section add this parameter:
uwsgi_pass_request_headers on;
.For example:
And if access to Django goes through uwsgi_pass, you need to add this one parameter
uwsgi_pass_request_headers on;
in location section.For example:
我认为这就是您所需要的:
记录正在发生的事情。
您可以更深入地查看上游代理模块上的 proxy_set_header 部分,以了解如何传递所需的标头。
您可以在此处找到文档:
最后一项似乎表明 nginx 默认传递大多数标头
I think this is what you need:
to log what is happening.
You might look deeper into the proxy_set_header section on the upstream proxy module to see how to pass on the headers you need.
You can find the documentation here:
The last entry seems to indicate that nginx passes most headers by default
我没有找到真正的答案,但能够找到解决方法。我在使用 RFC 标准标头 if-none-match 和 if-modified-since 时遇到了同样的问题,因此我的解决方案针对这些标头进行了测试。
添加到我的 nginx 配置中:
我无法解释为什么 nginx 默认拒绝将这些标头传递给 uwsgi。这个配置强制它。页面现在会根据情况生成 304。
对于有关非标准“令牌”标头的原始问题,这应该可以解决问题:
I didn't find a real answer, but was able to make a workaround. I was having the same problem with RFC standard headers if-none-match and if-modified-since, so my solution is tested for those headers.
Added to my nginx config:
I cannot explain why nginx refuses to pass these headers to uwsgi by default. This config forces it. Pages generate 304s as appropriate now.
For the original question about the non-standard "token" header, this should do the trick:
上面的答案足以让我们找到出路。但还有一个令人烦恼的问题我们需要知道。是的,这很烦人。
所以你明白了。自定义变量名中不能出现下划线。请改用连字符。
也许 Nginx 在某些语法情况下使用下划线。有人指出官方参考将不胜感激。
The answers above are enough for us to figure out the way. But there is still an annoying point we need to know. Yes, it is very annoying.
So you get it. Underscore could never appear in the customized variable name. Use a hyphen instead.
Maybe
Nginx
uses underscores in some grammar cases. Someone pointed out the official reference will be appreciated.这取决于自定义标头的命名方式。我的格式为“SomethingLike.this”,它包含一个点。无法重命名请求中的标头,因为它不是我们的代码。所以这样写是行不通的:
这也行不通:
因为我需要不存在的
dots_in_headers
指令。但我发现我可以通过添加以下内容来传递所有标头:
传递所有标头可能不安全,请谨慎使用。
It depends on how the custom header is named. My was in format "SomethingLike.this", it contains a dot. It was not possible to rename the header in the request, because it is not our code. So writing this would not work:
Also this would not work:
because I would need
dots_in_headers
directive which does not exist.But I found I can pass ALL headers simply by adding:
It may be insecure to pass all headers, please use with caution.