diff --git a/CHANGELOG.md b/CHANGELOG.md index 719265202..b804bea27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ * [#2733](https://github.com/ruby-grape/grape/pull/2733): Drop the dead `active_support/core_ext/hash/reverse_merge` require; call `ActiveSupport::HashWithIndifferentAccess.new(...)` directly at call sites - [@ericproulx](https://github.com/ericproulx). * [#2734](https://github.com/ruby-grape/grape/pull/2734): Extract `options_route_enabled` from the Endpoint options Hash into a dedicated `attr_accessor` - [@ericproulx](https://github.com/ericproulx). * [#2736](https://github.com/ruby-grape/grape/pull/2736): Collapse `Endpoint#run_validators` rescue branches via `ValidationErrors` flatten; `ValidationErrors#initialize` keyword renamed `errors:` → `exceptions:` - [@ericproulx](https://github.com/ericproulx). +* [#2749](https://github.com/ruby-grape/grape/pull/2749): Middleware tidy-up — dedupe `Versioner::Base#build_available_media_types` (was emitting `application/vnd.-` once per content_type) and assorted `Formatter` cleanups (guard clauses, in-place merges, drop a no-op splat) - [@ericproulx](https://github.com/ericproulx). * [#2746](https://github.com/ruby-grape/grape/pull/2746): Hoist `using:` / `except:` from `**opts` to explicit kwargs on `DSL::Parameters#requires` and `#optional` - [@ericproulx](https://github.com/ericproulx). * [#2742](https://github.com/ruby-grape/grape/pull/2742): Prune unused requires in `lib/grape.rb`; narrow `active_support/inflector` to `core_ext/string/inflections` - [@ericproulx](https://github.com/ericproulx). * [#2741](https://github.com/ruby-grape/grape/pull/2741): Readability pass: guard clauses and small extractions across `lib/` - [@ericproulx](https://github.com/ericproulx). diff --git a/lib/grape/middleware/formatter.rb b/lib/grape/middleware/formatter.rb index 51c660bff..ae9f05aef 100644 --- a/lib/grape/middleware/formatter.rb +++ b/lib/grape/middleware/formatter.rb @@ -33,7 +33,7 @@ def before def after return unless @app_response - status, headers, bodies = *@app_response + status, headers, bodies = @app_response return [status, headers, []] if Rack::Utils::STATUS_WITH_NO_ENTITY_BODY.include?(status) @@ -73,7 +73,8 @@ def fetch_formatter(headers) def ensure_content_type(headers) return headers if headers[Rack::CONTENT_TYPE] - headers.merge(Rack::CONTENT_TYPE => content_type_for(env[Grape::Env::API_FORMAT])) + headers[Rack::CONTENT_TYPE] = content_type_for(env[Grape::Env::API_FORMAT]) + headers end def read_body_input @@ -105,11 +106,11 @@ def read_rack_input(body) begin body = (env[Grape::Env::API_REQUEST_BODY] = parser.call(body, env)) if body.is_a?(Hash) - env[Rack::RACK_REQUEST_FORM_HASH] = if env.key?(Rack::RACK_REQUEST_FORM_HASH) - env[Rack::RACK_REQUEST_FORM_HASH].merge(body) - else - body - end + if (form_hash = env[Rack::RACK_REQUEST_FORM_HASH]) + form_hash.merge!(body) + else + env[Rack::RACK_REQUEST_FORM_HASH] = body + end env[Rack::RACK_REQUEST_FORM_INPUT] = env[Rack::RACK_INPUT] end rescue Grape::Exceptions::Base => e @@ -126,10 +127,11 @@ def read_rack_input(body) # - multipart/related # - multipart/mixed def read_body_input? - (rack_request.post? || rack_request.put? || rack_request.patch? || rack_request.delete?) && - !(rack_request.form_data? && rack_request.content_type) && - !rack_request.parseable_data? && - (rack_request.content_length.to_i.positive? || rack_request.env['HTTP_TRANSFER_ENCODING'] == 'chunked') + return false unless rack_request.post? || rack_request.put? || rack_request.patch? || rack_request.delete? + return false if rack_request.form_data? && rack_request.content_type + return false if rack_request.parseable_data? + + rack_request.content_length.to_i.positive? || rack_request.env['HTTP_TRANSFER_ENCODING'] == 'chunked' end def negotiate_content_type diff --git a/lib/grape/middleware/versioner/base.rb b/lib/grape/middleware/versioner/base.rb index 8b807e681..9f57664d7 100644 --- a/lib/grape/middleware/versioner/base.rb +++ b/lib/grape/middleware/versioner/base.rb @@ -50,14 +50,12 @@ def version_not_found! def build_available_media_types media_types = [] base_media_type = "application/vnd.#{vendor}" - content_types.each_key do |extension| - versions&.reverse_each do |version| - media_types << "#{base_media_type}-#{version}+#{extension}" - media_types << "#{base_media_type}-#{version}" - end - media_types << "#{base_media_type}+#{extension}" + versions&.reverse_each do |version| + versioned_base = "#{base_media_type}-#{version}" + content_types.each_key { |extension| media_types << "#{versioned_base}+#{extension}" } + media_types << versioned_base end - + content_types.each_key { |extension| media_types << "#{base_media_type}+#{extension}" } media_types << base_media_type media_types.concat(content_types.values.flatten) media_types