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

rails-api & rails 4 not working with rack-cors? #33

Closed
limitingfactor opened this issue Oct 6, 2013 · 90 comments
Closed

rails-api & rails 4 not working with rack-cors? #33

limitingfactor opened this issue Oct 6, 2013 · 90 comments
Assignees

Comments

@limitingfactor
Copy link

I've added rack-cors to my gemfile and put in my development.rb and production.rb (I also tried application.rb):

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

When I run rake middleware, I can see Rack::Cors. When I do a curl request for development or production no CORS headers are added to the requests. There's no errors to try to track, so I'm at a loss for why this isn't working.

@yonkeltron
Copy link

+1 from me.

Using rack-cors as per the readme in a rails-api project and I see no headers added by the gem if I do a GET. If I do a POST, I can get the headers properly when I tested using the Chrome Postman app.

Code for middleware insertion (copied verbatim from README):

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

All headers returned:

Access-Control-Allow-Credentials →true
Access-Control-Allow-Methods →GET, POST, OPTIONS
Access-Control-Allow-Origin →chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop
Access-Control-Max-Age →1728000
Cache-Control →max-age=0, private, must-revalidate
Content-Type →text/html
ETag →"7215ee9c7d9dc229d2921a40e899ec5f"
Transfer-Encoding →chunked
Vary →Origin
X-Content-Type-Options →nosniff
X-Frame-Options →SAMEORIGIN
X-Request-Id →72f58d72-e89c-48a4-a80e-1f8f52c2b5fe
X-Runtime →0.017717
X-UA-Compatible →chrome=1
X-XSS-Protection →1; mode=block

Environment information:

ruby 2.0.0p247 (2013-06-27 revision 41674) [x86_64-darwin12.3.0]

Rails 4.0.0

Darwin A-strong-preference-for-raincoats.local 12.5.0 Darwin Kernel Version 12.5.0: Sun Sep 29 13:33:47 PDT 2013; root:xnu-2050.48.12~1/RELEASE_X86_64 x86_64

Please let me know if I can provide any additional information. Thanks!

@zigomir
Copy link

zigomir commented Oct 20, 2013

I have same problem, but only when running in production mode. For development it works OK. I'm using vanilla Rails 4.

Edit:
Ah, I needed to use config.middleware.insert_before ActionDispatch::Static, Rack::Cors do and this to work you need to set config.serve_static_assets = true in production.rb.

@jhdavids8
Copy link

Thanks @zigomir, that did it for me in Rails 4!

@limitingfactor
Copy link
Author

Master works for me

@jbutz
Copy link

jbutz commented Nov 13, 2013

@zigomir's solution works for me, though I tweaked it and I am using
config.middleware.insert_after Rails::Rack::Logger, Rack::Cors, :logger => Rails.logger do
so that I can get log messages. Has anyone managed to get this working on Heroku?

@mgodwin
Copy link

mgodwin commented Dec 5, 2013

I have had it working off and on, but I can't seem to isolate what causes it to fail and succeed.

@sulphur
Copy link

sulphur commented Dec 6, 2013

i use the same solution as @jbutz too and seems to work for me too

@scottillogical
Copy link

Should we change the README to insert_after ?

@ghost
Copy link

ghost commented Feb 6, 2014

Using config.middleware.insert_after Rails::Rack::Logger, Rack::Cors, :logger => Rails.logger with rails-api does not appear to work for me for GET requests.

@jtomaszewski
Copy link

It should be definitely set in README - I searched the whole internet until I found a fix for that ..

@codeablehq
Copy link

Thanks @zigomir that did it for me as well, although without static assets (since we're not serving them from Rails).

@gabriel403
Copy link

This worked for me thanks, was driving me mental

@germs12
Copy link

germs12 commented Jul 24, 2014

I used config.middleware.insert_before ActionDispatch::Static, Rack::Cors do and it worked. Thanks @zigomir

nickjs referenced this issue in nickjs/rack-zippy Aug 7, 2014
@flauwekeul
Copy link

So, to summarize: currently the only way to fix this is to use config.middleware.insert_before ActionDispatch::Static, Rack::Cors do and enable config.serve_static_assets in production.rb?

It works, but I really don't want to enable static assets 😞

@cyu
Copy link
Owner

cyu commented Aug 12, 2014

You shouldn't need to set config.serve_static_assets unless you need the CORS headers for static assets.

jamiefolsom added a commit to hyperstudio/artbot-api that referenced this issue Aug 28, 2014
@germs12
Copy link

germs12 commented Sep 5, 2014

@cyu Any idea why this isn't working in rails 4? The "solution" stopped working for me recently (as well as others too from what I can see on the interwebs).

@cyu
Copy link
Owner

cyu commented Sep 7, 2014

I create an example in examples/rails4 and it seems to work. Granted it's a very simple example, so if you can give me some more details I can try to reproduce the issue.

@visoft
Copy link

visoft commented Sep 25, 2014

I copied the code verbatim from your application.rb file, yet I can't get it to work in my application. I still get "No 'Access-Control-Allow-Origin' header is present on the requested resource" from my client. Using Rails 4.2.beta1 and rails-api.

@simondelorean
Copy link

@visoft Did you manage to solve this issue? I'm using standard Rails 4.1.2, but can't get it to work either.

@visoft
Copy link

visoft commented Oct 1, 2014

@simonbogarde, I haven't. I hacked my ApplicationController to do the CORs stuff using this approach. I really would like to use rack-cors instead.

@simondelorean
Copy link

@visoft Thanks. When I manage to fix this, I'll post the solution here.

@jessesanford
Copy link

I am also now having the same "No 'Access-Control-Allow-Origin' header is present on the requested resource" issue with rails 4.1.5 when using

config.middleware.insert_after Rails::Rack::Logger, Rack::Cors, :logger => Rails.logger do

and also

config.middleware.insert_before "ActionDispatch::Static", "Rack::Cors", :debug => true, :logger => (-> { Rails.logger }) do

@dcunited001
Copy link

i had this working on heroku about a year ago, then several months later, it stopped working, but only on heroku. before, it seemed to process my rackup file, but now it's not. just now looking into it.

@dcunited001
Copy link

I donno, it's working for me on Heroku with Rails 4.2.0.beta2, when I configure CORS in a Rackup file, as below.

  • However, this app is API only and not serving any static assets.
  • Also, I'm using the Devise Token Auth gem.
# This file is used by Rack-based servers to start the application.

require ::File.expand_path('../config/environment',  __FILE__)
run Rails.application

cors_origins = ENV.fetch('RAILS42_CORS_ORIGINS', '*')

require 'rack/cors'
use Rack::Cors do
  # TODO: secure
  allow do
    origins cors_origins
    resource '*',
             :headers => :any,
             :expose  => ['access-token', 'expiry', 'token-type', 'uid', 'client'],
             :methods => [:get, :post, :options, :delete, :put]
  end
end

@a2f0
Copy link

a2f0 commented Oct 14, 2014

I have the same issue on Rails 4.0.8, no additional headers being supplied in HTTP get requests after following the installation instructions.

@Think4866
Copy link

I'm chiming in to say that I also have this issue after following the install instructions. I've also tried adding @dcunited001's code snippet to my config.ru as well.

@zeeshan-m
Copy link

@cyu It's not blank, I deleted it. The request url was:

https://base_url/v2/api/partner.json

Which is the specified Rack::Cors url. On top of that, I've tried enabling debug mode which did output headers of the request. The headers however were blank.

@zeeshan-m
Copy link

zeeshan-m commented Oct 25, 2016

@cyu Server debug output is:

D, [2016-10-25T15:04:20.265932 #1330] DEBUG -- : Incoming Headers:
  Origin: http://localhost:8100
  Access-Control-Request-Method: 
  Access-Control-Request-Headers: 
I, [2016-10-25T15:04:20.266485 #1330]  INFO -- : Started GET "/v2/api/event.json" for 8.18.218.175 at 2016-10-25 15:04:20 -0400
I, [2016-10-25T15:04:20.269529 #1330]  INFO -- : Processing by ApiController#event as JSON
I, [2016-10-25T15:04:20.389085 #1330]  INFO -- : Completed 200 OK in 119ms (Views: 0.3ms | ActiveRecord: 5.5ms)

A temporary work around for this is to add the following into your controller:

  before_action :set_headers

  def set_headers
    headers['Access-Control-Allow-Origin'] = '*'
    headers['Access-Control-Allow-Methods'] = 'GET'
    headers['Access-Control-Request-Method'] = '*'
    headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, Authorization' 
  end

Modify the headers to be specific to your situation, but that should do the job.

@cyu
Copy link
Owner

cyu commented Oct 27, 2016

@zeeshan-m with debug turned on in the middleware, you sure be getting a X-Rack-Cors header returned to your browser. What does that value look like?

Also, in your first post, you're getting a error message where the Origin is from port 8080, but it seems like most of your recent examples are from port 8100. Why is that?

@zeeshan-m
Copy link

zeeshan-m commented Oct 27, 2016

@cyu I was testing the issue with the different apps that we have that make api calls, they run on different ports so thats most likely why you saw the 8080 vs 8100 issue.

Full response headers in debug mode are:

HTTP/1.1 304 Not Modified
Server: nginx/1.10.1
Date: Thu, 27 Oct 2016 21:07:23 GMT
Connection: keep-alive
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
ETag: W/"f20ae7bd4000b0d0bbfe917e48a7d6ee"
Cache-Control: max-age=0, private, must-revalidate
X-Request-Id: bd0316bb-3aa9-4caf-930f-0418b54404cc
X-Runtime: 0.153243
Strict-Transport-Security: max-age=31536000
X-Rack-CORS: preflight-hit; no-path

@23ranjan
Copy link

@yonkeltron Did you find any way out for this?
I am also facing issue with GET requests.

@cyu
Copy link
Owner

cyu commented Jan 31, 2017

@zeeshan-m weird – that X-Rack-CORS response implies that it was a preflight request (OPTIONS HTTP method). You shouldn't need that if you're doing a GET.

@23ranjan
Copy link

@cyu Any idea why the headers are not coming for GET request ?

@cyu
Copy link
Owner

cyu commented Jan 31, 2017

@23ranjan what version of rails and rails-api are you running? What does your middleware stack look like (rake middleware)? What server are you testing against?

@jtibbertsma
Copy link

@cyu I'm having this issue as well. I can do a post request, but no Access-Control headers are sent with get requests.

I'm running rails 5.0.2. My middleware stack:

use Rack::Cors
use ActionDispatch::Static
use ActionDispatch::Executor
use ActiveSupport::Cache::Strategy::LocalCache::Middleware
use Rack::Runtime
use ActionDispatch::RequestId
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use ActionDispatch::DebugExceptions
use BetterErrors::Middleware
use ActionDispatch::RemoteIp
use ActionDispatch::Reloader
use ActionDispatch::Callbacks
use ActiveRecord::Migration::CheckPending
use Rack::Head
use Rack::ConditionalGet
use Rack::ETag

The value the X-Rack-CORS header is "miss; no-origin".

@cyu
Copy link
Owner

cyu commented Mar 10, 2017

@jtibbertsma How are you testing? The header suggests that the user agent isn't providing an Origin header.

@jtibbertsma
Copy link

I'm using Postman

@jtibbertsma
Copy link

Ok, it's working from localhost now, I just had to fix my settings :)

@cyu
Copy link
Owner

cyu commented Mar 10, 2017

@jtibbertsma ok – FYI Postman doesn't send the required Origin header to trigger a CORS response

@jtibbertsma
Copy link

It works for post requests tho

@soynog
Copy link

soynog commented Apr 26, 2017

I came across a similar issue: OPTIONS requests being sent from my Angular front end weren't getting CORS headers attached by rack-cors. Setting headers: :any seems to have solved the problem, vs. headers: 'Origin, X-Requested-With, Content-Type, Accept, Authorization, X-User-Token, X-User-Email' or ['Origin', 'X-Requested-With', 'Content-Type', 'Accept', 'Authorization', 'X-User-Token', 'X-User-Email']

Seems like possibly because I was missing these two headers (which were in the OPTIONS request but not the other requests: Access-Control-Request-Headers, Access-Control-Request-Method

@thebravoman
Copy link

thebravoman commented Feb 6, 2018

No Access-Control-Allow-Origin on my side also.

This is the configuration

  config.middleware.insert_before 0, "Rack::Cors", :debug => true, :logger => (-> { Rails.logger })  do
      allow do
        origins "https://mysite.com/"
        resource "/api/v1/resources/*", :headers => :any, :methods => [:get, :options]
      end
    end

This is the curl request for a test

curl -I --header "Origin: https://mysite.com" https://www.myothersite.com/api/v1/resources/393.json

This is the output in the log on the server side:

heroku[router]: at=info method=HEAD path="/api/v1/resources/393.json" host=www.myothersite.com
Incoming Headers:
   Origin: https://mysite.com
   Access-Control-Request-Method: 
   Access-Control-Request-Headers: 

This is the curl response

HTTP/1.1 200 OK
Server: Cowboy
Connection: keep-alive
Date: Tue, 06 Feb 2018 14:29:03 GMT
X-Frame-Options: SAMEORIGIN
X-Xss-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Content-Type: application/json; charset=utf-8
Etag: W/"2ba14ede7ef89cbe92bc6b6ac94ecf98"
Cache-Control: max-age=0, private, must-revalidate
Set-Cookie: ahoy_visitor=e7744ebf-5f88-4378-81d0-edf7dc86f138; path=/; expires=Thu, 06 Feb 2020 14:29:03 -0000
Set-Cookie: ahoy_visit=d4e0722f-642f-4a14-8383-e9d1294732e4; path=/; expires=Tue, 06 Feb 2018 18:29:03 -0000
X-Request-Id: 882deeb4-44df-49b9-a225-26b2d58a7889
X-Runtime: 0.022971
Vary: Accept-Encoding, Origin
X-Rack-Cors: miss; no-origin
Via: 1.1 vegur

It is not setting the Access-Controll-Allow-Origin

@cyu
Copy link
Owner

cyu commented Feb 6, 2018

@thebravoman the miss; no-origin means that the middleware never received the Origin: - maybe it's getting stripped out by something running upstream?

@cyu
Copy link
Owner

cyu commented Feb 6, 2018

@thebravoman sorry no-origin can also mean that the no matching origin.

Since your origin is 'https://mysite.com/', that does an exact string match with the Origin header. The origin in your curl command should therefore be 'https://mysite.com' (minus trailing slash), or you should change the configured origin to not have the trailing slash.

@thebravoman
Copy link

@cyu Thanks. This seems to be the problem. Quite funny. I spent a lot of time on this.

@cyu
Copy link
Owner

cyu commented Feb 6, 2018

@thebravoman glad that was it.

Looking at the spec, it looks like the Origin header format is <scheme> "://" <hostname> [ ":" <port> ]. Maybe I should automatically strip out any starting slash by default.

@thebravoman
Copy link

thebravoman commented Feb 8, 2018 via email

@LucasCioffi
Copy link

I was able to fix the error locally and on Heroku. I was getting a 401 when making a GET request through the browser.

I was able to make progress in figuring out the problem by making the same request using Postman. That showed me the body of the response which wasn't visible in the log when debug mode was on: "You need to sign in or sign up before continuing."

Seeing an unexpected message about authentication helped me realize that I had a typo in my URL (/admin/widgets instead of /widgets), and I was requesting a route in my app that was protected by ActiveAdmin.

I'm writing this explanation, because people can also get in this same situation of receiving 401s and thinking it's related to rack-cors if they are using Devise and they are requesting a route protected by before_action :authenticate_user!

This is what worked for me in application.rb:

config.middleware.insert_before ActionDispatch::Static, Rack::Cors, debug: true do
  allow do
    origins '*'
    resource '*', headers: :any, methods: [:get, :post, :options]
  end
end

@a0x
Copy link

a0x commented Feb 20, 2019

I think I met this problem in Rails 5.

Versions:

  • Ruby 2.6.1
  • Rails 5.2.2
  • rack-cors 1.0.2

Server is running under development env.

Results come first, as shown in the picture, I tried two requests with different origins, and the server gave me almost the same response(only with little difference in the headers).
image

Server SHOULD give 401, right?

Here's my config:

# config/initializers/cors.rb
Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins 'foobar.com'

    resource '*',
             headers: :any,
             methods: %i[get post put patch delete options head]
  end
end

Here're middlewares:

 $ rails middleware
use Rack::Cors
use Raven::Rack
use Rack::Sendfile
use ActionDispatch::Static
use ActionDispatch::Executor
use ActiveSupport::Cache::Strategy::LocalCache::Middleware
use Rack::Runtime
use ActionDispatch::RequestId
use ActionDispatch::RemoteIp
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use ActionDispatch::DebugExceptions
use ActionDispatch::Reloader
use ActionDispatch::Callbacks
use ActiveRecord::Migration::CheckPending
use Rack::Head
use Rack::ConditionalGet
use Rack::ETag
use Bullet::Rack
run Hermes::Application.routes

@jattoabdul
Copy link

Has there been any fix or workaround for this error? I am having a similar error where I am getting No route (404) error when making an OPTIONS requests to any of my endpoints.

I am using rails v6, rack-cors ~>1.0

in my application.rb I have

config.middleware.insert_before 0, Rack::Cors, debug: true do
      allow do
        origins '*'

        resource '*', headers: :any, expose: ['access-token', 'expiry', 'token-type', 'uid', 'client'], methods: [:get, :post, :put, :patch, :delete, :options, :head]
      end
    end

@cyu
Copy link
Owner

cyu commented Apr 23, 2020

@jattoabdul how are you testing this? Are you sure your requests are passing in an Origin header?

@alispat
Copy link

alispat commented May 7, 2020

Same issue here :(

@cyu
Copy link
Owner

cyu commented May 7, 2020

I'm closing this issue because there are different issues at play (some legit, some invalid).

If you're still having problems. Please create a new issue and provide the specifics.

@cyu cyu closed this as completed May 7, 2020
@swathi-ally
Copy link

Has there been a fix or workaround for this?
I have specified a random origin, but still, all the origins are allowed, instead of CORS error.
Rails: 5.2.
CORS: 1.1.1

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