2

So I have been pulling my hair out for a couple of days now. I have a backend server, using Nginx, Gunicorn and Django. I use it as a REST server, with Django Rest Framework, and using token authentication with Django Rest Auth. The address of this server is api.dev.mysite.com

This server is called from a frontend interface using AngularJS, also handled by Nginx, with the address dev.mysite.com

Everything is running locally, and as you can see the two domains are different. Whenever I try to make a request from the fronted to the backend, I get the following error:

Failed to load resource: Origin https://dev.mysite.com is not allowed by Access-Control-Allow-Origin.

I know what you think: Easy, just add add_header 'Access-Control-Allow-Origin' 'http://dev.mysite.com'; to your nginx.conf file on the backend, and everything will work, like here. or here.

But it doesn't. I tried everything, moving it to different locations, putting a '*' instead of the address, enabling and disabling SSL... The only thing that works is when I manually disable Cross-Origin restrictions in the browser. And the best part is that when I do disable those restrictions, I can see the Access-Control-Allow-Origin header set to http://dev.mysite.com in the debug console of my browser!

Any idea of what might be going wrong?

Here is my nginx.conf file:

worker_processes 1;

user me staff;
error_log /tmp/nginx.error.log;

events {
  worker_connections 1024; # increase if you have lots of clients
  accept_mutex off; # set to 'on' if nginx worker_processes > 1
}

http {
  include mime.types;
  default_type application/octet-stream;
  access_log /tmp/nginx.access.log;
  sendfile on;

  upstream app_server {
    # for UNIX domain socket setups
     server unix:/tmp/gunicorn.sock fail_timeout=0;
  }

  # Common SSL Settings
  ssl_session_cache shared:SSL:10m;
  ssl_session_timeout 10m;

  ssl_prefer_server_ciphers on;
  ssl_ciphers ALL:!ADH:!EXP:!LOW:!RC2:!3DES:!SEED:!RC4:+HIGH:+MEDIUM:!kEDH;
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

  server {
    # if no Host match, close the connection to prevent host spoofing
     listen 80 default_server;
     return 444;
  }

  server {
     listen 443 ssl;
     server_name api.dev.mysite.com;

     # Self-signed certificate.
     ssl_certificate ssl/nginx-selfsigned.crt;
     ssl_certificate_key ssl/nginx-selfsigned.key;

     access_log /tmp/api.dev.intelligence.access.log;
     error_log /tmp/api.dev.intelligence.error.log;

     location / {
        add_header 'Access-Control-Allow-Origin' 'https://dev.mysite.com';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT';
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Accept-Encoding';

        if ($request_method = 'OPTIONS') {
          add_header 'Access-Control-Max-Age' 1728000;
          add_header 'Content-Type' 'text/plain charset=UTF-8';
          add_header 'Content-Length' 0;
          return 204;
        }

        proxy_pass http://127.0.0.1:9000;
        proxy_set_header    Host            $host;
        proxy_set_header    X-Real-IP       $remote_addr;
        proxy_set_header    X-Forwarded-for $remote_addr;
        proxy_set_header    X-Forwarded-Protocol $scheme;
      }
  }

  server {
    client_max_body_size 4G;

    # Self-signed certificate.
    ssl_certificate ssl/nginx-selfsigned-front.crt;
    ssl_certificate_key ssl/nginx-selfsigned-front.key;

    # Listen on 80 and 443
    listen 80;
    listen 443 ssl;
    listen [::]:443 ssl;

    # set the correct host(s) for your site
    server_name dev.mysite.com;

    # Redirect all non-SSL traffic to SSL.
    if ($ssl_protocol = "") {
      rewrite ^ https://$host$request_uri? permanent;
    }

    keepalive_timeout 5;

    access_log /tmp/dev.intelligence.access.log;
    error_log /tmp/dev.intelligence.error.log;

    location / {
        root /path/to/app/current/;
        index index.html index.htm;   
    }

    error_page 500 502 503 504 /500.html;
    location = /500.html {
      root /path/to/app/current/public;
    }
  }
}
3
  • Not the specific answer to your question but django-cors-middleware makes this easier by configuring on the django side vs. nginx. Commented Jul 13, 2016 at 23:06
  • For CORS to allow your request, you need to CORS whitelist your client on the server side. See this, if it could help. Commented Jul 14, 2016 at 6:47
  • Thanks for your advice. I installed Django CORS Middleware, and added the following lines to my settings.py: CORS_ORIGIN_WHITELIST = ('dev.mysite.com') but doesn't solve the problem. I also tried with CORS_ORIGIN_ALLOW_ALL = True. Commented Jul 14, 2016 at 14:32

1 Answer 1

4

Alright so I found the solution to my problem. I did three things:

  1. Deleting all 'add_header' lines from my nginx.conf file. It now looks like that:

    location / {
        proxy_pass http://127.0.0.1:9000;
        proxy_set_header    Host            $host;
        proxy_set_header    X-Real-IP       $remote_addr;
        proxy_set_header    X-Forwarded-for $remote_addr;
        proxy_set_header    X-Forwarded-Protocol $scheme;
    }
    
  2. Installing Django Cors header, and adding the following lines to my settings.py:

    CORS_ORIGIN_ALLOW_ALL = False
    CORS_ALLOW_CREDENTIALS = True
    CORS_ORIGIN_WHITELIST = (
        'dev.myapp.com'
    )
    
  3. Added the following lines to my .config file in Angular:

    $httpProvider.defaults.useXDomain = true;
    $httpProvider.defaults.withCredentials = true;
    delete $httpProvider.defaults.headers.common['X-Requested-With'];
    

    I tried all of those things separately, but I guess all three were needed.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.