Skip to content

Commit f4e2af5

Browse files
authored
Fix fetch_formatter api_format (#2506)
* 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 * Add CHANGELOG and UPGRADING.md * Change `api_format` to ':txt' * Fix upgrading
1 parent 277fe3e commit f4e2af5

File tree

7 files changed

+18
-6
lines changed

7 files changed

+18
-6
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#### Fixes
1212

1313
* [#2504](https://github.com/ruby-grape/grape/pull/2504): Fix leaky modules in specs - [@ericproulx](https://github.com/ericproulx).
14+
* [#2506](https://github.com/ruby-grape/grape/pull/2506): Fix fetch_formatter api_format - [@ericproulx](https://github.com/ericproulx).
1415
* Your contribution here.
1516

1617
### 2.2.0 (2024-09-14)

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -3066,15 +3066,15 @@ end
30663066
* `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.
30673067
* `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).
30683068

3069-
You can override this process explicitly by specifying `env['api.format']` in the API itself.
3069+
You can override this process explicitly by calling `api_format` in the API itself.
30703070
For example, the following API will let you upload arbitrary files and return their contents as an attachment with the correct MIME type.
30713071

30723072
```ruby
30733073
class Twitter::API < Grape::API
30743074
post 'attachment' do
30753075
filename = params[:file][:filename]
30763076
content_type MIME::Types.type_for(filename)[0].to_s
3077-
env['api.format'] = :binary # there's no formatter for :binary, data will be returned "as is"
3077+
api_format :binary # there's no formatter for :binary, data will be returned "as is"
30783078
header 'Content-Disposition', "attachment; filename*=UTF-8''#{CGI.escape(filename)}"
30793079
params[:file][:tempfile].read
30803080
end

UPGRADING.md

+6
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ Upgrading Grape
33

44
### Upgrading to >= 2.3.0
55

6+
### `content_type` vs `api.format` inside API
7+
8+
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.
9+
In addition, the function `api_format` has been added. Instead of setting `env['api.format']` directly, you can call `api_format`.
10+
See [#2506](https://github.com/ruby-grape/grape/pull/2506) for more information.
11+
612
#### Remove Deprecated Methods and Options
713

814
- Deprecated `file` method has been removed. Use `send_file` or `stream`.

lib/grape/dsl/inside_route.rb

+5-1
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,11 @@ def entity_representation_for(entity_class, object, options)
452452
end
453453

454454
def http_version
455-
env['HTTP_VERSION'] || env[Rack::SERVER_PROTOCOL]
455+
env.fetch(Grape::Http::Headers::HTTP_VERSION) { env[Rack::SERVER_PROTOCOL] }
456+
end
457+
458+
def api_format(format)
459+
env[Grape::Env::API_FORMAT] = format
456460
end
457461

458462
def context

lib/grape/http/headers.rb

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ module Headers
66
HTTP_ACCEPT_VERSION = 'HTTP_ACCEPT_VERSION'
77
HTTP_ACCEPT = 'HTTP_ACCEPT'
88
HTTP_TRANSFER_ENCODING = 'HTTP_TRANSFER_ENCODING'
9+
HTTP_VERSION = 'HTTP_VERSION'
910

1011
ALLOW = 'Allow'
1112
LOCATION = 'Location'

lib/grape/middleware/formatter.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def build_formatted_response(status, headers, bodies)
5353
end
5454

5555
def fetch_formatter(headers, options)
56-
api_format = mime_types[headers[Rack::CONTENT_TYPE]] || env[Grape::Env::API_FORMAT]
56+
api_format = env.fetch(Grape::Env::API_FORMAT) { mime_types[headers[Rack::CONTENT_TYPE]] }
5757
Grape::Formatter.formatter_for(api_format, options[:formatters])
5858
end
5959

spec/grape/api_spec.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -4092,9 +4092,9 @@ def my_method
40924092
expect(last_response.body).to eq({ meaning_of_life: 42 }.to_json)
40934093
end
40944094

4095-
it 'can be overwritten with an explicit content type' do
4095+
it 'can be overwritten with an explicit api_format' do
40964096
subject.get '/meaning_of_life_with_content_type' do
4097-
content_type 'text/plain'
4097+
api_format :txt
40984098
{ meaning_of_life: 42 }.to_s
40994099
end
41004100
get '/meaning_of_life_with_content_type'

0 commit comments

Comments
 (0)