Closed BlancoSebastianEzequiel closed 3 years ago
@BlancoSebastianEzequiel You can get the same effect with the example able by passing a proxy of @app
instead of the @app
as-is. The Proxy would inspect env
on call and not call the real @app.call
Something like this:
module ApiUtils
module Middlewares
class CorsEnforcer
def initialize(app)
@app = app
end
def call(env)
cors_result = env[Rack::Cors::RACK_CORS]
return [401, {}, [{ error: cors_result.miss_reason }.to_json]] unless cors_result.hit
@app.call(env)
end
end
class CorsPolicy
def initialize(app, cors_policy_options)
@app = CorsEnforcer.new(app)
@cors_policy_options = cors_policy_options
end
def call(env)
cors_middleware = Rack::Cors.new(@app, debug: @cors_policy_options[:debug], &method(:cors_options))
cors_middleware.call(env)
rescue Rack::Cors::Resource::CorsMisconfigurationError => e
[500, {}, [{ error: e.message }.to_json]]
end
private
def cors_options(config)
config.allow do |allow|
allow.origins(@cors_policy_options[:origins])
allow.resource(
@cors_policy_options.resource[:path],
methods: @cors_policy_options.resource[:methods],
headers: @cors_policy_options.resource[:headers],
expose: @cors_policy_options.resource[:expose],
credentials: @cors_policy_options.resource[:credentials]
)
end
end
end
end
end
I end up doing something very similar. I have two middlewares instead of one like in your example.
Maybe your example is better because it uses only one middleware. In my case the order of the two middlewares is important. So i'll take it into account. Thank you!
Closing this since there is a viable solution.
The idea would be to separate to a public method the logic that is in charge of generating the Result, since in case of a miss I want to avoid calling the app.call (env).
The idea behind this, is that i would like to have one custom middleware that call this public method and in case of miss, return an error. Without this feature i have to have two middlewares, one for creating the result (whis is basically having Rack::Cors as a middleware) and another for validating it and returning and error in case of miss. This is because, the method
call
ofRack::Cors
calls toapp.call(env)
anyway. And i would like to return anunauthorized error (401)
and avoid callingapp.call(env)
This is what is was trying to achieve: