Skip to content

Commit 046450e

Browse files
croeckdblock
authored andcommitted
Fixed that invalid accept headers are (1) not processed by rescue handlers and (2) result in status 500 (no method) when http_codes are defined.
1 parent 6d8b803 commit 046450e

File tree

8 files changed

+434
-107
lines changed

8 files changed

+434
-107
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ Next Release
1010
* [#886](https://github.com/intridea/grape/pull/886): Group of parameters made to require an explicit type of Hash or Array - [@jrichter1](https://github.com/jrichter1).
1111
* [#912](https://github.com/intridea/grape/pull/912): Extended the `:using` feature for param documentation to `optional` fields - [@croeck](https://github.com/croeck).
1212
* [#906](https://github.com/intridea/grape/pull/906): Fix: invalid body parse errors are not rescued by handlers - [@croeck](https://github.com/croeck).
13+
* [#913](https://github.com/intridea/grape/pull/913): Fix: Invalid accept headers are not processed by rescue handlers - [@croeck](https://github.com/croeck).
14+
* [#913](https://github.com/intridea/grape/pull/913): Fix: Invalid accept headers cause internal processing errors (500) when http_codes are defined - [@croeck](https://github.com/croeck).
1315
* Your contribution here.
1416

1517
0.10.1 (12/28/2014)

lib/grape.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ module Exceptions
5858
autoload :MissingGroupTypeError, 'grape/exceptions/missing_group_type'
5959
autoload :UnsupportedGroupTypeError, 'grape/exceptions/unsupported_group_type'
6060
autoload :InvalidMessageBody, 'grape/exceptions/invalid_message_body'
61+
autoload :InvalidAcceptHeader, 'grape/exceptions/invalid_accept_header'
6162
end
6263

6364
module ErrorFormatter

lib/grape/error_formatter/base.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def present(message, env)
4141
http_codes = env['rack.routing_args'][:route_info].route_http_codes || []
4242
found_code = http_codes.find do |http_code|
4343
(http_code[0].to_i == env['api.endpoint'].status) && http_code[2].respond_to?(:represent)
44-
end
44+
end if env['api.endpoint'].request
4545

4646
presenter = found_code[2] if found_code
4747
end
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# encoding: utf-8
2+
module Grape
3+
module Exceptions
4+
class InvalidAcceptHeader < Base
5+
def initialize(message, headers)
6+
super(message: compose_message('invalid_accept_header', message: message), status: 406, headers: headers)
7+
end
8+
end
9+
end
10+
end

lib/grape/locale/en.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,7 @@ en:
4141
"when specifying %{body_format} as content-type, you must pass valid
4242
%{body_format} in the request's 'body'
4343
"
44+
invalid_accept_header:
45+
problem: 'Invalid accept header'
46+
resolution: '%{message}'
4447

lib/grape/middleware/versioner/header.rb

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,24 +23,21 @@ module Versioner
2323
# route.
2424
class Header < Base
2525
def before
26-
begin
27-
header = Rack::Accept::MediaType.new env['HTTP_ACCEPT']
28-
rescue RuntimeError => e
29-
throw :error, status: 406, headers: error_headers, message: e.message
30-
end
26+
header = rack_accept_header
3127

3228
if strict?
3329
# If no Accept header:
3430
if header.qvalues.empty?
35-
throw :error, status: 406, headers: error_headers, message: 'Accept header must be set.'
31+
fail Grape::Exceptions::InvalidAcceptHeader.new('Accept header must be set.', error_headers)
3632
end
3733
# Remove any acceptable content types with ranges.
3834
header.qvalues.reject! do |media_type, _|
3935
Rack::Accept::Header.parse_media_type(media_type).find { |s| s == '*' }
4036
end
4137
# If all Accept headers included a range:
4238
if header.qvalues.empty?
43-
throw :error, status: 406, headers: error_headers, message: 'Accept header must not contain ranges ("*").'
39+
fail Grape::Exceptions::InvalidAcceptHeader.new('Accept header must not contain ranges ("*").',
40+
error_headers)
4441
end
4542
end
4643

@@ -58,10 +55,10 @@ def before
5855
end
5956
# If none of the available content types are acceptable:
6057
elsif strict?
61-
throw :error, status: 406, headers: error_headers, message: '406 Not Acceptable'
58+
fail Grape::Exceptions::InvalidAcceptHeader.new('406 Not Acceptable', error_headers)
6259
# If all acceptable content types specify a vendor or version that doesn't exist:
6360
elsif header.values.all? { |header_value| has_vendor?(header_value) || version?(header_value) }
64-
throw :error, status: 406, headers: error_headers, message: 'API vendor or version not found.'
61+
fail Grape::Exceptions::InvalidAcceptHeader.new('API vendor or version not found.', error_headers)
6562
end
6663
end
6764

@@ -83,7 +80,13 @@ def available_media_types
8380
available_media_types << media_type
8481
end
8582

86-
available_media_types = available_media_types.flatten
83+
available_media_types.flatten
84+
end
85+
86+
def rack_accept_header
87+
Rack::Accept::MediaType.new env['HTTP_ACCEPT']
88+
rescue RuntimeError => e
89+
raise Grape::Exceptions::InvalidAcceptHeader.new(e.message, error_headers)
8790
end
8891

8992
def versions

0 commit comments

Comments
 (0)