Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix fetch_formatter api_format #2506

Merged
merged 4 commits into from
Oct 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3066,15 +3066,15 @@ 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
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
Expand Down
6 changes: 6 additions & 0 deletions UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ Upgrading Grape

### Upgrading to >= 2.3.0

### `content_type` vs `api.format` inside API

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.

#### Remove Deprecated Methods and Options

- Deprecated `file` method has been removed. Use `send_file` or `stream`.
Expand Down
6 changes: 5 additions & 1 deletion lib/grape/dsl/inside_route.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions lib/grape/http/headers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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'
Expand Down
2 changes: 1 addition & 1 deletion lib/grape/middleware/formatter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 2 additions & 2 deletions spec/grape/api_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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 :txt
{ meaning_of_life: 42 }.to_s
end
get '/meaning_of_life_with_content_type'
Expand Down