Domanda

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

nginx conf file

È stato utile?

Soluzione

If Django is accessed using uwsgi_pass, then in the appropriate location(s) ...

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

If Django is accessed using fastcgi_pass, then in the appropriate location(s) ...

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

If Django is accessed using proxy_pass, then in the appropriate location(s) ...

# 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;

These should help eliminate the possibility that Nginx is not passing things along from your issue.

Altri suggerimenti

In your nginx configuration file (f.e. mysite_nginx.conf) in the server section add this parameter: uwsgi_pass_request_headers on;.

For example:

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

    ...

    underscores_in_headers on;
}

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:

location / {
    include     /etc/nginx/uwsgi_params; # the uwsgi_params file you installed
    uwsgi_pass_request_headers on;
    uwsgi_pass  django;
}

I think this is what you need:

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"'

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

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:

uwsgi_param HTTP_IF_NONE_MATCH $http_if_none_match;
uwsgi_param HTTP_IF_MODIFIED_SINCE $http_if_modified_since;

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:

uwsgi_param HTTP_TOKEN $http_token;

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.

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

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top