diff --git a/CHANGELOG.md b/CHANGELOG.md index 61e3e6eca..5a2aa11c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ * [#2710](https://github.com/ruby-grape/grape/pull/2710): Tidy up `Grape::DeclaredParamsHandler` - [@ericproulx](https://github.com/ericproulx). * [#2714](https://github.com/ruby-grape/grape/pull/2714): Drop unused `Grape::Middleware::Globals` and its `grape.request*` env constants - [@ericproulx](https://github.com/ericproulx). * [#2717](https://github.com/ruby-grape/grape/pull/2717): Convert `Grape::Exceptions::ErrorResponse` to a `Data` value object - [@ericproulx](https://github.com/ericproulx). +* [#2719](https://github.com/ruby-grape/grape/pull/2719): Move content-type helpers from `Middleware::Base` into `PrecomputedContentTypes` - [@ericproulx](https://github.com/ericproulx). * Your contribution here. #### Fixes diff --git a/lib/grape/middleware/base.rb b/lib/grape/middleware/base.rb index a0c8ee9a9..05316a563 100644 --- a/lib/grape/middleware/base.rb +++ b/lib/grape/middleware/base.rb @@ -61,22 +61,6 @@ def response @app_response = Rack::Response[*@app_response] end - def content_types - @content_types ||= Grape::ContentTypes.content_types_for(options[:content_types]) - end - - def mime_types - @mime_types ||= Grape::ContentTypes.mime_types_for(content_types) - end - - def content_type_for(format) - content_types_indifferent_access[format] - end - - def content_type - content_type_for(env[Grape::Env::API_FORMAT] || options[:format]) || 'text/html' - end - def query_params rack_request.GET rescue *Grape::RACK_ERRORS @@ -85,10 +69,6 @@ def query_params private - def content_types_indifferent_access - @content_types_indifferent_access ||= content_types.with_indifferent_access - end - def merge_headers(response) return if @header.blank? diff --git a/lib/grape/middleware/precomputed_content_types.rb b/lib/grape/middleware/precomputed_content_types.rb index e8dc1b641..ca6b1f7c4 100644 --- a/lib/grape/middleware/precomputed_content_types.rb +++ b/lib/grape/middleware/precomputed_content_types.rb @@ -2,14 +2,15 @@ module Grape module Middleware - # Include in a middleware subclass to warm the content-type caches on the - # parent instance at initialization. Per-request dups inherit the cached - # values via +dup+'s ivar copy, avoiding ~1 µs per request of - # +with_indifferent_access+ recomputation. + # Include in a middleware subclass that needs content-type negotiation. + # Provides +content_types+ / +mime_types+ / +content_type_for+ / + # +content_type+ resolved from +options[:content_types]+ and + # +options[:format]+, and warms those caches on the parent instance at + # initialization so per-request +dup+s inherit them (avoiding + # ~1 µs/request of +with_indifferent_access+ recomputation). # - # Opt-in: plain +Grape::Middleware::Base+ subclasses continue to compute - # +content_types+ / +mime_types+ / +content_type_for+ lazily on first - # access. + # Opt-in: plain +Grape::Middleware::Base+ subclasses that don't need + # content-type-aware helpers don't pay for them. module PrecomputedContentTypes def initialize(app, **options) super @@ -17,6 +18,28 @@ def initialize(app, **options) mime_types content_types_indifferent_access end + + def content_types + @content_types ||= Grape::ContentTypes.content_types_for(options[:content_types]) + end + + def mime_types + @mime_types ||= Grape::ContentTypes.mime_types_for(content_types) + end + + def content_type_for(format) + content_types_indifferent_access[format] + end + + def content_type + content_type_for(env[Grape::Env::API_FORMAT] || options[:format]) || 'text/html' + end + + private + + def content_types_indifferent_access + @content_types_indifferent_access ||= content_types.with_indifferent_access + end end end end