Skip to content

Commit d24bd2f

Browse files
author
Daniel Doubrovkine (dB.)
committed
Merge pull request ruby-grape#144 from rodzyn/accept_header_strict
Accept header strict
2 parents 6c9f971 + dc71118 commit d24bd2f

File tree

2 files changed

+51
-15
lines changed

2 files changed

+51
-15
lines changed

lib/grape/middleware/versioner/header.rb

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,16 @@ module Versioner
1818
# env['api.version] => 'v1'
1919
# env['api.format] => 'format'
2020
#
21-
# If version does not match this route, then a 404 is throw with
21+
# If version does not match this route, then a 406 is throw with
2222
# X-Cascade header to alert Rack::Mount to attempt the next matched
2323
# route.
2424
class Header < Base
2525
def before
2626
accept = env['HTTP_ACCEPT'] || ""
2727

2828
if options[:version_options] && options[:version_options].keys.include?(:strict) && options[:version_options][:strict]
29-
if (accept.nil? || accept.empty?) && options[:versions] && options[:version_options][:using] == :header
30-
throw :error, :status => 404, :headers => {'X-Cascade' => 'pass'}, :message => "404 API Version Not Found"
29+
if (is_accept_header_valid?(accept)) && options[:version_options][:using] == :header
30+
throw :error, :status => 406, :headers => {'X-Cascade' => 'pass'}, :message => "406 API Version Not Found"
3131
end
3232
end
3333
accept.strip.scan(/^(.+?)\/(.+?)$/) do |type, subtype|
@@ -39,7 +39,7 @@ def before
3939
is_vendored_match = is_vendored ? options[:version_options][:vendor] == vendor : true
4040

4141
if (options[:versions] && !options[:versions].include?(version)) || !is_vendored_match
42-
throw :error, :status => 404, :headers => {'X-Cascade' => 'pass'}, :message => "404 API Version Not Found"
42+
throw :error, :status => 406, :headers => {'X-Cascade' => 'pass'}, :message => "406 API Version Not Found"
4343
end
4444

4545
env['api.version'] = version
@@ -48,6 +48,11 @@ def before
4848
end
4949
end
5050
end
51+
52+
protected
53+
def is_accept_header_valid?(header)
54+
(header.strip =~ /application\/vnd\.(.+?)-(.+?)\+(.+?)/).nil?
55+
end
5156
end
5257
end
5358
end

spec/grape/middleware/versioner/header_spec.rb

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -69,15 +69,46 @@
6969
subject.call({}).first.should == 200
7070
end
7171

72-
it 'should return a 404 when no header is set but strict header based versioning is used' do
73-
@options = {
74-
:versions => ['v1'],
75-
:version_options => {:using => :header, :strict => true}
76-
}
77-
expect {
78-
env = subject.call('HTTP_ACCEPT' => '').last
79-
}.to throw_symbol(:error, :status => 404, :headers => {'X-Cascade' => 'pass'}, :message => "404 API Version Not Found")
72+
context 'when strict header versioning is used' do
73+
it 'should return a 406 when no header' do
74+
@options = {
75+
:versions => ['v1'],
76+
:version_options => {:using => :header, :strict => true}
77+
}
78+
expect {
79+
env = subject.call('HTTP_ACCEPT' => '').last
80+
}.to throw_symbol(
81+
:error,
82+
:status => 406,
83+
:headers => {'X-Cascade' => 'pass'},
84+
:message => "406 API Version Not Found"
85+
)
86+
end
87+
88+
it 'should return a 406 when incorrect header format is used' do
89+
@options = {
90+
:versions => ['v1'],
91+
:version_options => {:using => :header, :strict => true}
92+
}
93+
expect {
94+
env = subject.call('HTTP_ACCEPT' => '*/*').last
95+
}.to throw_symbol(
96+
:error,
97+
:status => 406,
98+
:headers => {'X-Cascade' => 'pass'},
99+
:message => "406 API Version Not Found"
100+
)
101+
end
102+
103+
it 'should return a 200 when proper header is set' do
104+
@options = {
105+
:versions => ['v1'],
106+
:version_options => {:using => :header, :strict => true}
107+
}
108+
subject.call('HTTP_ACCEPT' => 'application/vnd.testing-v1+json').first.should == 200
109+
end
80110
end
111+
81112
end
82113

83114
context 'vendors' do
@@ -96,7 +127,7 @@
96127
it 'should not match with an incorrect vendor' do
97128
expect {
98129
env = subject.call('HTTP_ACCEPT' => 'application/vnd.othervendor-v1+json').last
99-
}.to throw_symbol(:error, :status => 404, :headers => {'X-Cascade' => 'pass'}, :message => "404 API Version Not Found")
130+
}.to throw_symbol(:error, :status => 406, :headers => {'X-Cascade' => 'pass'}, :message => "406 API Version Not Found")
100131
end
101132
end
102133

@@ -108,10 +139,10 @@
108139
}
109140
end
110141

111-
it 'should throw 404 error with X-Cascade header set to pass' do
142+
it 'should throw 406 error with X-Cascade header set to pass' do
112143
expect {
113144
env = subject.call('HTTP_ACCEPT' => accept).last
114-
}.to throw_symbol(:error, :status => 404, :headers => {'X-Cascade' => 'pass'}, :message => "404 API Version Not Found")
145+
}.to throw_symbol(:error, :status => 406, :headers => {'X-Cascade' => 'pass'}, :message => "406 API Version Not Found")
115146
end
116147
end
117148
end

0 commit comments

Comments
 (0)