cyu / rack-cors

Rack Middleware for handling Cross-Origin Resource Sharing (CORS), which makes cross-origin AJAX possible.
MIT License
3.26k stars 263 forks source link

expose header is empty #185

Closed mongeta closed 4 years ago

mongeta commented 5 years ago

Given those details:

ruby 2.4.0 rails: 5.2.1 rack-cors: 1.0.2 and 1.0.3

active_model_serializers: 0.10.7 api-pagination: 4.8.2 pagy: 3.2.1

config/initializers/cors.rb

Rails.application.config.middleware.insert_before 0, Rack::Cors, debug: true do
    allow do
    origins '*' # TODO remember to update this
    resource '*',
      headers: :any,
      expose: ['Per-Page', 'Total', 'Link', 'ETag'],
      methods: [:get, :post, :put, :patch, :delete, :options, :head]
  end
end
bundle exec rake middleware

use Rack::Cors
use Rack::Cors
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
run StarterProjectApi::Application.routes

The headers for expose are blank.

What I see is two calls to use Rack::Cors. Debugging the gem, I found that when the self.expos is informed, the first time that it does, it fills correct, but at the same time is called, it's empty.

lib/rack/cors.rb (gem)
row 353: self.expose = opts[:expose] ? [opts[:expose]].flatten : nil

The first iteration is informed, I can see the expose details, but at the next iteration, they are gone. I say two iterations from the same connection, there is only ONE connection, but two iterations.

What can be the error of the two consequent calls of it?

But, if I use this code, the expose headers are exposed, but with other problems:

Rails.application.config.middleware.use Rack::Cors do
    allow do
    origins '*'
    resource '*',
      headers: :any,
      expose: ['Per-Page', 'Total', 'Link', 'ETag'],
      methods: [:get, :post, :put, :patch, :delete, :options, :head]
  end
end
bundle exec rake middleware

use Rack::Cors
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 Rack::Cors

This is what I get in Chrome Network Inspector

The debug mode adds de X-Rack-CORS-...... and I can see there my expose headers. Even the allow-methods are different

Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: 
Access-Control-Max-Age: 1728000
Cache-Control: max-age=0, private, must-revalidate
Content-Type: application/vnd.api+json; charset=utf-8
ETag: W/"276e5bd150f2ad894c30a5f23d13b13c"
Link: <http://localhost:3000/api/v1/posts?filter%5Btags%5D=ocean&page=21>; rel="last", <http://localhost:3000/api/v1/posts?filter%5Btags%5D=ocean&page=2>; rel="next"
Per-Page: 10
Total: 204
Transfer-Encoding: chunked
Vary: Origin
X-Rack-CORS: hit
X-Rack-CORS-Original-Access-Control-Allow-Methods: GET, POST, PUT, PATCH, DELETE, OPTIONS, HEAD
X-Rack-CORS-Original-Access-Control-Allow-Origin: *
X-Rack-CORS-Original-Access-Control-Expose-Headers: Per-Page, Total, Link, ETag
X-Rack-CORS-Original-Access-Control-Max-Age: 1728000
X-Request-Id: e97aba03-f730-4f5c-90d0-ca92c70047c5
X-Runtime: 0.171081
mongeta commented 5 years ago
cors
cyu commented 4 years ago

@mongeta My guess is that you have another instance of Rack::Cors somewhere. I'm not sure how that would cause these issues, but I would try to clear that up first. Perhaps it is also defined in config.ru or application.rb?

raimon-kantox commented 4 years ago

Ok, I'll try to have a look, it was a very old legacy app, thanks for the idea.

eitches commented 4 years ago

Hi, I'm developing app with Rails and Nuxt.js. I faced the same error so here my solutions:

Rails 6.0.0.2
Nuxt.js

I wrote this code in Nuxt.js. ($axios posts and gets response from rails server if successfully did)

  async login(vuexContext, data) {
    await this.$axios.post("/api/v1/auth/sign_in", data)
      .then( response => {
        console.log(response.headers)
      })
      .catch(e => {
        console.log(e)
      })
  }

my rack-cors settings below(in config/application.rb):

Rails.application.config.middleware.use Rack::Cors do
    allow do
    origins 'localhost:3001' #my nuxt app on localhost:3001
    resource '*',
      headers: :any,
      expose: ['access-token', 'client', 'expiry'],
      methods: [:get, :post, :put, :patch, :delete, :options, :head]
  end
end

with above settings, my result of console.log(response.headers) is:

headers:
  cache-control: "max-age=0, private, must-revalidate"
  content-type: "application/json; charset=utf-8"

I googled this trouble and I got @cyu 's reply below: https://github.com/cyu/rack-cors/issues/185#issuecomment-555842186

I checked my files with git grep Rack, and I found the same setting in config/initializers/cors.rb!

So I moved this setting to config/initializers/cors.rb, and works!!! :-D here's my result:

headers:
  access-token: "VPPrzn2DnJuqJi_uDEI4hg"
  cache-control: "max-age=0, private, must-revalidate"
  client: "TVmLwY1GM23koi9r9HY17g"
  content-type: "application/json; charset=utf-8"
  expiry: "1587634926"
cyu commented 4 years ago

Closing this issue. @raimon-kantox If you're still having this issue, please feel free to re-open (with more information of course).