Skip to content

Commit

Permalink
Merge pull request #275 from ahx/disable-error-response
Browse files Browse the repository at this point in the history
Add a middleware option to skip rendering a response
  • Loading branch information
ahx authored Jun 27, 2024
2 parents aa70632 + f067c36 commit 3024b5c
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 10 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Unreleased

- Request validation middleware now accepts `error_response: false` do disable rendering a response. This is useful if you just want to collect metrics (via hooks) during a migration phase.

## 2.0.2

- Fix setting custom error response (thanks @gobijan)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ use OpenapiFirst::Middlewares::RequestValidation, spec: 'openapi.yaml'
| :---------------- | ------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------- |
| `spec:` | | The path to the spec file or spec loaded via `OpenapiFirst.load` |
| `raise_error:` | `false` (default), `true` | If set to true the middleware raises `OpenapiFirst::RequestInvalidError` or `OpenapiFirst::NotFoundError` instead of returning 4xx. |
| `error_response:` | `:default` (default), `:jsonapi`, Your implementation of `ErrorResponse` |
| `error_response:` | `:default` (default), `:jsonapi`, Your implementation of `ErrorResponse` or `false` to disable responding |

#### Error responses

Expand Down
13 changes: 8 additions & 5 deletions lib/openapi_first/middlewares/request_validation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ class RequestValidation
# :raise_error A Boolean indicating whether to raise an error if validation fails.
# default: false
# :error_response The Class to use for error responses.
# This can be a Symbol-name of an registered error response (:default, :jsonapi)
# or it can be set to false to disable returning a response.
# default: OpenapiFirst::Plugins::Default::ErrorResponse (Config.default_options.error_response)
def initialize(app, options = {})
@app = app
@raise = options.fetch(:raise_error, OpenapiFirst.configuration.request_validation_raise_error)
@error_response_class = error_response(options[:error_response])
@error_response_class = error_response_option(options[:error_response])

spec = options.fetch(:spec)
raise "You have to pass spec: when initializing #{self.class}" unless spec
Expand All @@ -29,17 +31,18 @@ def call(env)
validated = @definition.validate_request(Rack::Request.new(env), raise_error: @raise)
env[REQUEST] = validated
failure = validated.error
return @error_response_class.new(failure:).render if failure
return @error_response_class.new(failure:).render if failure && @error_response_class

@app.call(env)
end

private

def error_response(mod)
return OpenapiFirst.find_error_response(mod) if mod.is_a?(Symbol)
def error_response_option(value)
return if value == false
return OpenapiFirst.find_error_response(value) if value.is_a?(Symbol)

mod || OpenapiFirst.configuration.request_validation_error_response
value || OpenapiFirst.configuration.request_validation_error_response
end
end
end
Expand Down
53 changes: 49 additions & 4 deletions spec/middlewares/request_validation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,25 @@
end
end

context 'with custom error_response option' do
context 'with error_response: :default' do
let(:app) do
Rack::Builder.app do
use OpenapiFirst::Middlewares::RequestValidation, spec: './spec/data/request-body-validation.yaml',
error_response: :default
run lambda { |_env|
Rack::Response.new('hello', 200).finish
}
end
end

it 'returns 400' do
header 'Content-Type', 'application/json'
post '/pets'
expect(last_response.status).to eq 400
end
end

context 'with error_response: MyCustomClass' do
let(:app) do
custom_class = Class.new do
include OpenapiFirst::ErrorResponse
Expand All @@ -101,21 +119,48 @@ def status = 409
end
end

context 'with :default error_response option' do
context 'with error_response: false' do
let(:called) { [] }

let(:app) do
spec = OpenapiFirst.load('./spec/data/request-body-validation.yaml') do |config|
config.after_request_validation do |validated_request|
called << { valid: validated_request.valid? }
end
end
Rack::Builder.app do
use OpenapiFirst::Middlewares::RequestValidation, spec:,
error_response: false
run lambda { |_env|
Rack::Response.new('hello', 200).finish
}
end
end

it 'validates the response, but calls the application' do
header 'Content-Type', 'application/json'
post '/pets'
expect(last_response.status).to eq 200
expect(called).to eq [{ valid: false }]
end
end

context 'with error_response: nil' do
let(:app) do
Rack::Builder.app do
use OpenapiFirst::Middlewares::RequestValidation, spec: './spec/data/request-body-validation.yaml',
error_response: :default
error_response: nil
run lambda { |_env|
Rack::Response.new('hello', 200).finish
}
end
end

it 'returns 400' do
it 'uses the default error reponse class' do
header 'Content-Type', 'application/json'
post '/pets'
expect(last_response.status).to eq 400
expect(last_response.content_type).to eq 'application/problem+json'
end
end

Expand Down

0 comments on commit 3024b5c

Please sign in to comment.