Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't get rack-cors to work in production environment using nginx/unicorn. #29

Closed
calvinl opened this issue Jun 26, 2013 · 11 comments
Closed

Comments

@calvinl
Copy link

calvinl commented Jun 26, 2013

It works in development, but setting the same in production or staging environments, rack-cors doesn't seem to add the appropriate headers. The preflight stuff looks okay.

Is there a specific problem with nginx configuration that causes the middleware to not work?

Here's my nginx config file:

# this can be any application server, not just Unicorn/Rainbows!
upstream mysite {
  # fail_timeout=0 means we always retry an upstream even if it failed
  # to return a good HTTP response (in case the Unicorn master nukes a
  # single worker for timing out).

  # for UNIX domain socket setups (configured in unicorn.rb)
  server unix:/tmp/.sock fail_timeout=0;

  # for TCP setups, point these to your backend servers
  # server 192.168.0.7:8080 fail_timeout=0;
  # server 192.168.0.8:8080 fail_timeout=0;
  # server 192.168.0.9:8080 fail_timeout=0;
}

server {

  client_max_body_size 4G;
  listen 443;
  server_name  mysite.com www.mysite.com;
  root /var/www/mysite/current/public;

  keepalive_timeout 5;
  try_files $uri/index.html $uri.html $uri @app;
  location @app {
    # an HTTP header important enough to have its own Wikipedia entry:
    # http://en.wikipedia.org/wiki/X-Forwarded-For
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    # enable this if you forward HTTPS traffic to unicorn,
    # this helps Rack set the proper URL scheme for doing redirects:
    proxy_set_header X-Forwarded-Proto $scheme;

    # pass the Host: header from the client right along so redirects
    # can be set properly within the Rack application
    proxy_set_header Host $http_host;

    # we don't want nginx trying to do something clever with
    # redirects, we set the Host: header above already.
    proxy_redirect off;

    # set "proxy_buffering off" *only* for Rainbows! when doing
    # Comet/long-poll/streaming.  It's also safe to set if you're using
    # only serving fast clients with Unicorn + nginx, but not slow
    # clients.  You normally want nginx to buffer responses to slow
    # clients, even with Rails 3.1 streaming because otherwise a slow
    # client can become a bottleneck of Unicorn.
    #
    # The Rack application may also set "X-Accel-Buffering (yes|no)"
    # in the response headers do disable/enable buffering on a
    # per-response basis.
    # proxy_buffering off;

    proxy_pass http://mysite;
  }

  # Cross domain webfont access
  location ~* \.(?:ttf|ttc|otf|eot|woff|font.css)$ {
    add_header "Access-Control-Allow-Origin" "mysite.com";
    add_header "Access-Control-Allow-Origin" "www.mysite.com";

    # Also, set cache rules for webfonts.
    # See http://wiki.nginx.org/HttpCoreModule#location
    # And https://github.com/h5bp/server-configs/issues/85
    # And https://github.com/h5bp/server-configs/issues/86
    expires 1M;
    access_log off;
    add_header Cache-Control "public";
  }

  ssl on;
  ssl_certificate /home/ubuntu/ssl/mysite.com.crt;
  ssl_certificate_key /home/ubuntu/ssl/mysite.com.key;

}
@cyu
Copy link
Owner

cyu commented Jun 26, 2013

How is the middleware configured?

@calvinl
Copy link
Author

calvinl commented Jun 26, 2013

In staging.rb:

  config.middleware.insert_before Warden::Manager, Rack::Cors do
    allow do
      origins '*'
      resource '*', :headers => :any, :methods => [:get, :post, :options]
    end
  end

@cyu
Copy link
Owner

cyu commented Jun 26, 2013

What's the resource you're trying to access? Unfortunately, files in the public folder will be served directly from nginx, bypassing rails altogether. You can try altering your try_files command like this:

# removed $uri
try_files $uri/index.html $uri.html @app;

This will force all non-html resource through the app. Unfortunately, this will put extra load on the unicorn. You should be able to re-configure nginx to send just the resources you want through the app. Unfortunately, I've never done that before so I don't have any examples of how one would do this.

@calvinl
Copy link
Author

calvinl commented Jun 26, 2013

It's an API controller route. The OPTIONS request gets in, but it returns a 404 because the rails app doesn't know what to do with it.

@jesseadams
Copy link

I am having this exact same problem. Same stack (nginx+unicorn). Works great in via thin but not in production. I tried @cyu 's suggestion above and it had no effect.

@toxaq
Copy link

toxaq commented Apr 21, 2014

+1

1 similar comment
@ksiomelo
Copy link

+1

@cyu
Copy link
Owner

cyu commented May 14, 2014

I just did a clean Unicorn/Nginx install of the example Rails app (in examples/rails3) and was able to get my tests to pass. One thing to watch out for is to make sure Rack::Cors is inserted before the ActionDispatch::Static:

config.middleware.insert_before "ActionDispatch::Static", "Rack::Cors" do
  ...
end

If you are still having issues, please provide some more information, like:

  • Output of rake middleware
  • Rack::Cors config'
  • The route you're hitting
  • The Nginx configuration

@jagthedrummer
Copy link

I'm having this same problem. It seems like nginx is not passing through the headers set by Rack::Cors.

Output of rake middleware

use Rack::Sendfile
use Rack::Cors
use ActionDispatch::Static
use Rack::Lock
use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x00000002126568>
use Rack::Runtime
use Rack::MethodOverride
use ActionDispatch::RequestId
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use ActionDispatch::DebugExceptions
use ActionDispatch::RemoteIp
use ActionDispatch::Reloader
use ActionDispatch::Callbacks
use ActiveRecord::Migration::CheckPending
use ActiveRecord::ConnectionAdapters::ConnectionManagement
use ActiveRecord::QueryCache
use ActionDispatch::Cookies
use ActionDispatch::Session::CookieStore
use ActionDispatch::Flash
use ActionDispatch::ParamsParser
use Rack::Head
use Rack::ConditionalGet
use Rack::ETag
run RetailerPortal::Application.routes

Rack::Cors config in config/application.rb

    config.middleware.insert_before "ActionDispatch::Static", "Rack::Cors" do
      allow do
        origins(/http:\/\/localhost:(\d*)/,
                /http:\/\/*\.newecx\.com/,
                /http:\/\/*\.ritani\.com/,
                /https:\/\/*\.newecx\.com/,
                /https:\/\/*\.ritani\.com/
               )
        resource '/api/v1/*', :headers => :any, :methods => [:get, :post, :put, :delete, :options]
      end
    end

The route I'm hitting : /api/v1/retailers

The Nginx configuration:

upstream unicorn_retailer_portal {
 server unix:/srv/www/retailer_portal/shared/sockets/unicorn.sock fail_timeout=0;
}

server {
  listen 80;
  server_name retailer_portal oberon;

  access_log /var/log/nginx/retailer_portal.access.log;

  keepalive_timeout 5;

  root /srv/www/retailer_portal/current/public/;


  location / {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;

    proxy_read_timeout 60;
    proxy_send_timeout 60;

    # If you don't find the filename in the static files
    # Then request it from the unicorn server
    if (!-f $request_filename) {
      proxy_pass http://unicorn_retailer_portal;
      break;
    }
  }

  location /nginx_status {
    stub_status on;
    access_log off;
    allow 127.0.0.1;
    deny all;
  }

  error_page 500 502 503 504 /500.html;
  location = /500.html {
    root /srv/www/retailer_portal/current/public/;
  }
}

@jagthedrummer
Copy link

Well, my problem turned out to be my own fault. I borked the regexes for some of my origins. Instead of /http:\/\/*\.newecx\.com/ I should have had /http:\/\/.*\.newecx\.com/.

@cyu
Copy link
Owner

cyu commented Sep 7, 2014

Closing this as this is an old issue. I have made at fix wrt OPTIONS requests in the past. Feel free to reopen if this is still happening.

@cyu cyu closed this as completed Sep 7, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants