From 3fc99b10831a7a5e429174b9ef27e3abf5ffe369 Mon Sep 17 00:00:00 2001 From: Eric Proulx Date: Sun, 20 Oct 2024 15:25:34 +0200 Subject: [PATCH 1/4] Add `api_format` function accessible from inside_route fetch_formatter will look api.format first Use fetch {} instead of [] || Update spec Add HTTP_VERSION in Grape::Http::Headers Update README --- README.md | 4 ++-- lib/grape/dsl/inside_route.rb | 6 +++++- lib/grape/http/headers.rb | 1 + lib/grape/middleware/formatter.rb | 2 +- spec/grape/api_spec.rb | 4 ++-- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 9d46af651..0c6c56aff 100644 --- a/README.md +++ b/README.md @@ -3066,7 +3066,7 @@ end * `GET /hello.xls` with an `Accept: application/xml` header has an unrecognized extension, but the `Accept` header corresponds to a recognized format, so it will respond with XML. * `GET /hello.xls` with an `Accept: text/plain` header has an unrecognized extension *and* an unrecognized `Accept` header, so it will respond with JSON (the default format). -You can override this process explicitly by specifying `env['api.format']` in the API itself. +You can override this process explicitly by calling `api_format` in the API itself. For example, the following API will let you upload arbitrary files and return their contents as an attachment with the correct MIME type. ```ruby @@ -3074,7 +3074,7 @@ class Twitter::API < Grape::API post 'attachment' do filename = params[:file][:filename] content_type MIME::Types.type_for(filename)[0].to_s - env['api.format'] = :binary # there's no formatter for :binary, data will be returned "as is" + api_format :binary # there's no formatter for :binary, data will be returned "as is" header 'Content-Disposition', "attachment; filename*=UTF-8''#{CGI.escape(filename)}" params[:file][:tempfile].read end diff --git a/lib/grape/dsl/inside_route.rb b/lib/grape/dsl/inside_route.rb index 72b365bc4..a7efcd490 100644 --- a/lib/grape/dsl/inside_route.rb +++ b/lib/grape/dsl/inside_route.rb @@ -452,7 +452,11 @@ def entity_representation_for(entity_class, object, options) end def http_version - env['HTTP_VERSION'] || env[Rack::SERVER_PROTOCOL] + env.fetch(Grape::Http::Headers::HTTP_VERSION) { env[Rack::SERVER_PROTOCOL] } + end + + def api_format(format) + env[Grape::Env::API_FORMAT] = format end def context diff --git a/lib/grape/http/headers.rb b/lib/grape/http/headers.rb index ab8770ab4..eb4d38915 100644 --- a/lib/grape/http/headers.rb +++ b/lib/grape/http/headers.rb @@ -6,6 +6,7 @@ module Headers HTTP_ACCEPT_VERSION = 'HTTP_ACCEPT_VERSION' HTTP_ACCEPT = 'HTTP_ACCEPT' HTTP_TRANSFER_ENCODING = 'HTTP_TRANSFER_ENCODING' + HTTP_VERSION = 'HTTP_VERSION' ALLOW = 'Allow' LOCATION = 'Location' diff --git a/lib/grape/middleware/formatter.rb b/lib/grape/middleware/formatter.rb index 4de1af02e..5cb761463 100644 --- a/lib/grape/middleware/formatter.rb +++ b/lib/grape/middleware/formatter.rb @@ -53,7 +53,7 @@ def build_formatted_response(status, headers, bodies) end def fetch_formatter(headers, options) - api_format = mime_types[headers[Rack::CONTENT_TYPE]] || env[Grape::Env::API_FORMAT] + api_format = env.fetch(Grape::Env::API_FORMAT) { mime_types[headers[Rack::CONTENT_TYPE]] } Grape::Formatter.formatter_for(api_format, options[:formatters]) end diff --git a/spec/grape/api_spec.rb b/spec/grape/api_spec.rb index 14e2c9257..5aa8ef5eb 100644 --- a/spec/grape/api_spec.rb +++ b/spec/grape/api_spec.rb @@ -4092,9 +4092,9 @@ def my_method expect(last_response.body).to eq({ meaning_of_life: 42 }.to_json) end - it 'can be overwritten with an explicit content type' do + it 'can be overwritten with an explicit api_format' do subject.get '/meaning_of_life_with_content_type' do - content_type 'text/plain' + api_format 'text/plain' { meaning_of_life: 42 }.to_s end get '/meaning_of_life_with_content_type' From af11a32665d59da169905db268be1618bbae26d6 Mon Sep 17 00:00:00 2001 From: Eric Proulx Date: Sun, 20 Oct 2024 15:41:53 +0200 Subject: [PATCH 2/4] Add CHANGELOG and UPGRADING.md --- CHANGELOG.md | 1 + UPGRADING.md | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e5d85dfec..7aea93408 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ #### Fixes * [#2504](https://github.com/ruby-grape/grape/pull/2504): Fix leaky modules in specs - [@ericproulx](https://github.com/ericproulx). +* [#2506](https://github.com/ruby-grape/grape/pull/2506): Fix fetch_formatter api_format - [@ericproulx](https://github.com/ericproulx). * Your contribution here. ### 2.2.0 (2024-09-14) diff --git a/UPGRADING.md b/UPGRADING.md index ab80fe4cb..f1826c7b9 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -3,6 +3,12 @@ Upgrading Grape ### Upgrading to >= 2.3.0 +### `content_type` vs `api.format` inside API + +Before 2.3.0, `content_type` would have priority over `env['api.format']` when set in an API. The priority has been flipped and `env['api.format']` will be checked first. +In addition, the function `api_format` has been added. Instead of setting `env['api.format']` directly, you can call `api_format`. +See [#2506] (https://github.com/ruby-grape/grape/pull/2506) for more information. + #### Remove Deprecated Methods and Options - Deprecated `file` method has been removed. Use `send_file` or `stream`. From d5eb38d7aa65af93886e8d2bbf335825f0633b62 Mon Sep 17 00:00:00 2001 From: Eric Proulx Date: Sun, 20 Oct 2024 15:53:06 +0200 Subject: [PATCH 3/4] Change `api_format` to ':txt' --- spec/grape/api_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/grape/api_spec.rb b/spec/grape/api_spec.rb index 5aa8ef5eb..bd6398780 100644 --- a/spec/grape/api_spec.rb +++ b/spec/grape/api_spec.rb @@ -4094,7 +4094,7 @@ def my_method it 'can be overwritten with an explicit api_format' do subject.get '/meaning_of_life_with_content_type' do - api_format 'text/plain' + api_format :txt { meaning_of_life: 42 }.to_s end get '/meaning_of_life_with_content_type' From 7cd02b901c2a1651af87ab6efe065605143d7346 Mon Sep 17 00:00:00 2001 From: Eric Proulx Date: Sun, 20 Oct 2024 15:57:39 +0200 Subject: [PATCH 4/4] Fix upgrading --- UPGRADING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index f1826c7b9..0c6c54f6e 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -5,9 +5,9 @@ Upgrading Grape ### `content_type` vs `api.format` inside API -Before 2.3.0, `content_type` would have priority over `env['api.format']` when set in an API. The priority has been flipped and `env['api.format']` will be checked first. +Before 2.3.0, `content_type` had priority over `env['api.format']` when set in an API, which was incorrect. The priority has been flipped and `env['api.format']` will be checked first. In addition, the function `api_format` has been added. Instead of setting `env['api.format']` directly, you can call `api_format`. -See [#2506] (https://github.com/ruby-grape/grape/pull/2506) for more information. +See [#2506](https://github.com/ruby-grape/grape/pull/2506) for more information. #### Remove Deprecated Methods and Options