From dd9eaf8a397cf2831f9b08612dcabe6b56687fd3 Mon Sep 17 00:00:00 2001 From: Andreas Haller Date: Thu, 28 May 2026 22:10:59 +0200 Subject: [PATCH] Remove redundant matching of multipart content-type. Lookup of request body parser gets an optional options hash now. If you want to register new body parsers, there are two options 1. passing a callable register('application/x-www-form-urlencoded', lambda(&:POST)) 2. passing a class that accepts an options hash in the initializer register(%r{\Amultipart/form-data\b}i, MultipartBodyParser) --- lib/openapi_first/request.rb | 9 +-------- lib/openapi_first/request_body_parsers.rb | 17 ++++++++--------- spec/request_body_parsers_spec.rb | 5 ++--- 3 files changed, 11 insertions(+), 20 deletions(-) diff --git a/lib/openapi_first/request.rb b/lib/openapi_first/request.rb index e767665f..ed02ce5e 100644 --- a/lib/openapi_first/request.rb +++ b/lib/openapi_first/request.rb @@ -54,9 +54,6 @@ def operation_id @operation['operationId'] end - MULTIPART_CONTENT_TYPE = %r{\Amultipart/form-data\b}i - private_constant :MULTIPART_CONTENT_TYPE - private def parse_request(request, route_params:) @@ -82,11 +79,7 @@ def parse_query(query_string) end def build_body_parser(content_type, encoding) - if content_type.match?(MULTIPART_CONTENT_TYPE) - RequestBodyParsers['multipart/form-data'].new(encoding: encoding || {}) - else - RequestBodyParsers[content_type] - end + RequestBodyParsers[content_type, { encoding: encoding || {} }] end end end diff --git a/lib/openapi_first/request_body_parsers.rb b/lib/openapi_first/request_body_parsers.rb index 5e17e47f..71a4aadd 100644 --- a/lib/openapi_first/request_body_parsers.rb +++ b/lib/openapi_first/request_body_parsers.rb @@ -14,9 +14,12 @@ def register(pattern, parser) parsers[pattern] = parser end - def [](content_type) + def [](content_type, options = {}) key = parsers.keys.find { content_type.match?(_1) } - parsers.fetch(key) { DEFAULT } + parser = parsers.fetch(key) { DEFAULT } + return parser if parser.respond_to?(:call) + + parser.new(options) end end @@ -44,12 +47,8 @@ def self.read_body(request) # `contentType: application/json` (or any */json), the field's raw value # is JSON-parsed before schema validation. class MultipartBodyParser - def initialize(encoding: {}) - @encoding = encoding || {} - end - - def self.call(request) - new.call(request) + def initialize(options) + @encoding = options[:encoding] || {} end def call(request) @@ -89,7 +88,7 @@ def unpack_value(value) end end - register('multipart/form-data', MultipartBodyParser) + register(%r{\Amultipart/form-data\b}i, MultipartBodyParser) register('application/x-www-form-urlencoded', lambda(&:POST)) end diff --git a/spec/request_body_parsers_spec.rb b/spec/request_body_parsers_spec.rb index e9e477f1..6f711633 100644 --- a/spec/request_body_parsers_spec.rb +++ b/spec/request_body_parsers_spec.rb @@ -29,9 +29,8 @@ def app = ->(_env) { Rack::Response.new.finish } context 'with an encoding map' do subject(:parser) do - OpenapiFirst::RequestBodyParsers::MultipartBodyParser.new( - encoding: { 'data' => { 'contentType' => 'application/json' } } - ) + options = { encoding: { 'data' => { 'contentType' => 'application/json' } } } + described_class['multipart/form-data', options] end it 'parses fields whose encoding contentType is JSON' do