diff --git a/CHANGELOG.md b/CHANGELOG.md index 31b6c971..17824f9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,9 @@ # Changelog ## Unreleased -- No longer merge parameter schemas per of the same location (for example "query") in order to fix https://github.com/ahx/openapi_first/issues/320 +- Middlewares now accept the OAD as a first positional argument instead of `:spec` inside the options hash. +- No longer merge parameter schemas per of the same location (for example "query") in order to fix https://github.com/ahx/openapi_first/issues/320 - `OpenapiFirst::Test::Methods[MyApplication]` returns a Module which adds an `app` method to be used by rack-test alonside the `assert_api_conform` method. - Make default coverage report less verbose The default formatter (TerminalFormatter) no longer prints all un-requested requests by default. You can set `test.coverage_formatter_options = { focused: false }` to get back the old behavior diff --git a/lib/openapi_first/middlewares/request_validation.rb b/lib/openapi_first/middlewares/request_validation.rb index eddf44f2..bfca5ebe 100644 --- a/lib/openapi_first/middlewares/request_validation.rb +++ b/lib/openapi_first/middlewares/request_validation.rb @@ -6,19 +6,26 @@ module Middlewares # A Rack middleware to validate requests against an OpenAPI API description class RequestValidation # @param app The parent Rack application - # @param options An optional Hash of configuration options to override defaults + # @param spec [String, OpenapiFirst::Definition] Path to the OpenAPI file or an instance of Definition. + # @param options Hash + # :spec [String, OpenapiFirst::Definition] Path to the OpenAPI file or an instance of Definition. + # This will be deprecated. Please use spec argument instead. # :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 = {}) + def initialize(app, spec = nil, options = {}) @app = app + if spec.is_a?(Hash) + options = spec + spec = options.fetch(:spec) + end @raise = options.fetch(:raise_error, OpenapiFirst.configuration.request_validation_raise_error) @error_response_class = error_response_option(options[:error_response]) - spec = options.fetch(:spec) + spec ||= options.fetch(:spec) raise "You have to pass spec: when initializing #{self.class}" unless spec @definition = spec.is_a?(Definition) ? spec : OpenapiFirst.load(spec) diff --git a/lib/openapi_first/middlewares/response_validation.rb b/lib/openapi_first/middlewares/response_validation.rb index 454dda2c..21fe7dcb 100644 --- a/lib/openapi_first/middlewares/response_validation.rb +++ b/lib/openapi_first/middlewares/response_validation.rb @@ -6,15 +6,19 @@ module OpenapiFirst module Middlewares # A Rack middleware to validate requests against an OpenAPI API description class ResponseValidation - # @param app The parent Rack application + # @param spec [String, OpenapiFirst::Definition] Path to the OpenAPI file or an instance of Definition # @param options Hash - # :spec [String, OpenapiFirst::Definition] Path to the OpenAPI file or an instance of Definition + # :spec [String, OpenapiFirst::Definition] Path to the OpenAPI file or an instance of Definition. + # This will be deprecated. Please use spec argument instead. # :raise_error [Boolean] Whether to raise an error if validation fails. default: true - def initialize(app, options = {}) + def initialize(app, spec = nil, options = {}) @app = app + if spec.is_a?(Hash) + options = spec + spec = options.fetch(:spec) + end @raise = options.fetch(:raise_error, OpenapiFirst.configuration.response_validation_raise_error) - spec = options.fetch(:spec) raise "You have to pass spec: when initializing #{self.class}" unless spec @definition = spec.is_a?(Definition) ? spec : OpenapiFirst.load(spec) diff --git a/spec/middlewares/request_validation_spec.rb b/spec/middlewares/request_validation_spec.rb index 96793de9..258d4057 100644 --- a/spec/middlewares/request_validation_spec.rb +++ b/spec/middlewares/request_validation_spec.rb @@ -32,6 +32,22 @@ end end + context 'when OAD is passed as first argument' do + let(:app) do + Rack::Builder.app do + use(OpenapiFirst::Middlewares::RequestValidation, File.expand_path('../data/petstore-expanded.yaml', __dir__)) + run ->(_) {} + end + end + + it 'returns 400 is request is invalid' do + header 'Content-Type', 'application/json' + post '/pets', 'not json' + + expect(last_response.status).to eq 400 + end + end + context 'when parameter is invalid' do it 'returns 400' do get '/pets?limit=three' diff --git a/spec/middlewares/response_validation_spec.rb b/spec/middlewares/response_validation_spec.rb index a777b2ac..dacb5076 100644 --- a/spec/middlewares/response_validation_spec.rb +++ b/spec/middlewares/response_validation_spec.rb @@ -25,6 +25,26 @@ end let(:response) { Rack::Response.new(response_body, status, headers) } + context 'with path to OAD as first argument' do + let(:response_body) { '2' } + + let(:app) do + res = response + definition = spec + Rack::Builder.app do + use Rack::Lint + use OpenapiFirst::Middlewares::ResponseValidation, definition + run ->(_env) { res.finish } + end + end + + it 'fails if request is inavlid' do + expect do + get '/pets' + end.to raise_error OpenapiFirst::ResponseInvalidError + end + end + context 'without content-type header' do let(:headers) do { 'X-HEAD' => '/api/next-page' }