Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do i configure the django rest framework pagination url

when I get an object in django rest framework the urls always come absolute with localhost, but in production im going through a proxy on nginx, is there a way to set this url in the settings

Example

count: 11
next: "http://localhost:8000/api/accounts/?ordering=-date_registered&page=2"
previous: null

I need it to be

count: 11
next: "http:/example.com/api/accounts/?ordering=-date_registered&page=2"
previous: null

---------- edit --------------------------

please see my complete nginx config

server {
    listen 80;
    server_name 123.123.123.123;
    root            /home/admin/www/site-web/dist;
    index           index.html;
    charset         utf-8;


    location /static/ {
        alias /home/admin/www/site/static/;
    }

    location /media/  {
        alias /home/admin/www/site/media/;
    }

    location /nginx_status/ {
        # Turn on nginx stats
        stub_status on;
        # I do not need logs for stats
        access_log  off;
        # Security: Only allow access from 192.168.1.100 IP #
        # allow 192.168.1.100;
        # Send rest of the world to /dev/null #
        # deny all;
   }

    location / {
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        try_files $uri $uri/ /index.html;

       if ($request_method = 'OPTIONS') {
            add_header 'Access-Control-Allow-Origin' '*';
            #
            # Om nom nom cookies
            #
            add_header 'Access-Control-Allow-Credentials' 'true';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            #
            # Custom headers and headers various browsers *should* be OK with but aren't
            #
            add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
            #
            # Tell client that this pre-flight info is valid for 20 days
            #
            add_header 'Access-Control-Max-Age' 1728000;
            add_header 'Content-Type' 'text/plain charset=UTF-8';
            add_header 'Content-Length' 0;
            return 204;
             }

        if ($request_method = 'POST') {
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Credentials' 'true';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
        }

        if ($request_method = 'GET') {
            add_header 'Access-Control-Allow-Origin' '*';
            add_header 'Access-Control-Allow-Credentials' 'true';
            add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
            add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
         }
    }

   location /docs/ {
       proxy_pass http://127.0.0.1:8000/docs/;
       break;
   }

   location /api/ {
       underscores_in_headers on;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header Host $http_host;
       proxy_redirect off;
       proxy_pass http://127.0.0.1:8000/api/;
       break;
   }

   location /admin/ {
       proxy_pass http://127.0.0.1:8000/admin/;
       break;
   }

}

==== super edit====

Sorry guys, i had 'underscores_in_headers on;' i removed it and all is working

================

like image 870
Brandon Swallow Avatar asked Aug 23 '15 12:08

Brandon Swallow


2 Answers

Set USE_X_FORWARDED_HOST in your settings to True and make sure you pass it along using your web server(proxy) as well.

When django does build_absolute_uri() it calls get_host() - see below in django.http.request:

def get_host(self):
    """Returns the HTTP host using the environment or request headers."""
    # We try three options, in order of decreasing preference.
    if settings.USE_X_FORWARDED_HOST and (
            'HTTP_X_FORWARDED_HOST' in self.META):
        host = self.META['HTTP_X_FORWARDED_HOST']
        ...

See Real life usage of the X-Forwarded-Host header?

like image 53
Incognos Avatar answered Oct 18 '22 10:10

Incognos


It sounds like your Host header is not being set properly, which would be an issue in your nginx configuration. The issue is that your Host header that is being sent includes the port number, so Django is including the port number when building out urls. This will cause future issues with CSRF, because CSRF checks do strict port checking when you are not debugging.

This is known to cause issues with SSL for similar reasons.

You can fix this by setting the Host header within Nginx to not include the proxied port.

proxy_set_header Host $http_host;

Note that I used the $http_host variable instead of $host or $host:$server_port. This will ensure that Django will still respect CSRF requests on non-standard ports, while still giving you the correct absolute urls.

like image 21
Kevin Brown-Silva Avatar answered Oct 18 '22 08:10

Kevin Brown-Silva