grape 0.6.1 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of grape might be problematic. Click here for more details.
- checksums.yaml +9 -9
- data/.gitignore +7 -0
- data/.rubocop.yml +5 -0
- data/.travis.yml +3 -3
- data/CHANGELOG.md +42 -3
- data/CONTRIBUTING.md +118 -0
- data/Gemfile +4 -4
- data/README.md +312 -52
- data/Rakefile +6 -1
- data/UPGRADING.md +124 -0
- data/lib/grape.rb +2 -0
- data/lib/grape/api.rb +95 -44
- data/lib/grape/cookies.rb +0 -2
- data/lib/grape/endpoint.rb +63 -39
- data/lib/grape/error_formatter/base.rb +0 -3
- data/lib/grape/error_formatter/json.rb +0 -2
- data/lib/grape/error_formatter/txt.rb +0 -2
- data/lib/grape/error_formatter/xml.rb +0 -2
- data/lib/grape/exceptions/base.rb +0 -2
- data/lib/grape/exceptions/incompatible_option_values.rb +0 -3
- data/lib/grape/exceptions/invalid_formatter.rb +0 -3
- data/lib/grape/exceptions/invalid_versioner_option.rb +0 -4
- data/lib/grape/exceptions/invalid_with_option_for_represent.rb +0 -2
- data/lib/grape/exceptions/missing_mime_type.rb +0 -4
- data/lib/grape/exceptions/missing_option.rb +0 -3
- data/lib/grape/exceptions/missing_vendor_option.rb +0 -3
- data/lib/grape/exceptions/unknown_options.rb +0 -4
- data/lib/grape/exceptions/unknown_validator.rb +0 -2
- data/lib/grape/exceptions/validation_errors.rb +6 -5
- data/lib/grape/formatter/base.rb +0 -3
- data/lib/grape/formatter/json.rb +0 -2
- data/lib/grape/formatter/serializable_hash.rb +15 -16
- data/lib/grape/formatter/txt.rb +0 -2
- data/lib/grape/formatter/xml.rb +0 -2
- data/lib/grape/http/request.rb +2 -4
- data/lib/grape/locale/en.yml +1 -1
- data/lib/grape/middleware/auth/oauth2.rb +15 -6
- data/lib/grape/middleware/base.rb +7 -7
- data/lib/grape/middleware/error.rb +11 -6
- data/lib/grape/middleware/formatter.rb +80 -78
- data/lib/grape/middleware/globals.rb +13 -0
- data/lib/grape/middleware/versioner/accept_version_header.rb +0 -2
- data/lib/grape/middleware/versioner/header.rb +5 -3
- data/lib/grape/middleware/versioner/param.rb +2 -4
- data/lib/grape/middleware/versioner/path.rb +3 -4
- data/lib/grape/namespace.rb +0 -1
- data/lib/grape/parser/base.rb +0 -3
- data/lib/grape/parser/json.rb +0 -2
- data/lib/grape/parser/xml.rb +0 -2
- data/lib/grape/path.rb +1 -3
- data/lib/grape/route.rb +0 -3
- data/lib/grape/util/hash_stack.rb +1 -1
- data/lib/grape/validations.rb +72 -22
- data/lib/grape/validations/coerce.rb +5 -4
- data/lib/grape/validations/default.rb +5 -3
- data/lib/grape/validations/presence.rb +1 -1
- data/lib/grape/validations/regexp.rb +0 -2
- data/lib/grape/validations/values.rb +2 -1
- data/lib/grape/version.rb +1 -1
- data/spec/grape/api_spec.rb +385 -96
- data/spec/grape/endpoint_spec.rb +162 -15
- data/spec/grape/entity_spec.rb +25 -0
- data/spec/grape/exceptions/validation_errors_spec.rb +19 -0
- data/spec/grape/middleware/auth/oauth2_spec.rb +60 -15
- data/spec/grape/middleware/base_spec.rb +3 -8
- data/spec/grape/middleware/error_spec.rb +2 -2
- data/spec/grape/middleware/exception_spec.rb +4 -4
- data/spec/grape/middleware/formatter_spec.rb +7 -4
- data/spec/grape/middleware/versioner/param_spec.rb +8 -7
- data/spec/grape/path_spec.rb +24 -14
- data/spec/grape/util/hash_stack_spec.rb +8 -8
- data/spec/grape/validations/coerce_spec.rb +75 -33
- data/spec/grape/validations/default_spec.rb +57 -0
- data/spec/grape/validations/presence_spec.rb +13 -11
- data/spec/grape/validations/values_spec.rb +76 -2
- data/spec/grape/validations_spec.rb +443 -20
- data/spec/spec_helper.rb +2 -2
- data/spec/support/content_type_helpers.rb +11 -0
- metadata +9 -38
data/spec/grape/endpoint_spec.rb
CHANGED
@@ -9,7 +9,7 @@ describe Grape::Endpoint do
|
|
9
9
|
|
10
10
|
describe '#initialize' do
|
11
11
|
it 'takes a settings stack, options, and a block' do
|
12
|
-
p = proc {
|
12
|
+
p = proc {}
|
13
13
|
expect {
|
14
14
|
Grape::Endpoint.new(Grape::Util::HashStack.new, {
|
15
15
|
path: '/',
|
@@ -64,7 +64,7 @@ describe Grape::Endpoint do
|
|
64
64
|
}
|
65
65
|
end
|
66
66
|
it 'includes additional request headers' do
|
67
|
-
get '/headers', nil,
|
67
|
+
get '/headers', nil, "HTTP_X_GRAPE_CLIENT" => "1"
|
68
68
|
JSON.parse(last_response.body)["X-Grape-Client"].should == "1"
|
69
69
|
end
|
70
70
|
it 'includes headers passed as symbols' do
|
@@ -141,7 +141,7 @@ describe Grape::Endpoint do
|
|
141
141
|
cookie = cookies[cookie_name]
|
142
142
|
cookie.should_not be_nil
|
143
143
|
cookie.value.should == "deleted"
|
144
|
-
cookie.expired?.should
|
144
|
+
cookie.expired?.should be true
|
145
145
|
end
|
146
146
|
end
|
147
147
|
|
@@ -150,7 +150,7 @@ describe Grape::Endpoint do
|
|
150
150
|
sum = 0
|
151
151
|
cookies.each do |name, val|
|
152
152
|
sum += val.to_i
|
153
|
-
cookies.delete name,
|
153
|
+
cookies.delete name, path: '/test'
|
154
154
|
end
|
155
155
|
sum
|
156
156
|
end
|
@@ -166,7 +166,7 @@ describe Grape::Endpoint do
|
|
166
166
|
cookie.should_not be_nil
|
167
167
|
cookie.value.should == "deleted"
|
168
168
|
cookie.path.should == "/test"
|
169
|
-
cookie.expired?.should
|
169
|
+
cookie.expired?.should be true
|
170
170
|
end
|
171
171
|
end
|
172
172
|
end
|
@@ -177,7 +177,7 @@ describe Grape::Endpoint do
|
|
177
177
|
requires :first
|
178
178
|
optional :second
|
179
179
|
optional :third, default: 'third-default'
|
180
|
-
|
180
|
+
optional :nested, type: Hash do
|
181
181
|
optional :fourth
|
182
182
|
end
|
183
183
|
end
|
@@ -214,6 +214,16 @@ describe Grape::Endpoint do
|
|
214
214
|
end
|
215
215
|
|
216
216
|
it 'builds nested params when given array' do
|
217
|
+
subject.get '/dummy' do
|
218
|
+
end
|
219
|
+
subject.params do
|
220
|
+
requires :first
|
221
|
+
optional :second
|
222
|
+
optional :third, default: 'third-default'
|
223
|
+
optional :nested, type: Array do
|
224
|
+
optional :fourth
|
225
|
+
end
|
226
|
+
end
|
217
227
|
subject.get '/declared' do
|
218
228
|
declared(params)[:nested].size.should == 2
|
219
229
|
""
|
@@ -254,6 +264,55 @@ describe Grape::Endpoint do
|
|
254
264
|
end
|
255
265
|
end
|
256
266
|
|
267
|
+
describe '#declared; call from child namespace' do
|
268
|
+
before do
|
269
|
+
subject.format :json
|
270
|
+
subject.namespace :something do
|
271
|
+
params do
|
272
|
+
requires :id, type: Integer
|
273
|
+
end
|
274
|
+
resource ':id' do
|
275
|
+
params do
|
276
|
+
requires :foo
|
277
|
+
optional :bar
|
278
|
+
end
|
279
|
+
get do
|
280
|
+
{
|
281
|
+
params: params,
|
282
|
+
declared_params: declared(params)
|
283
|
+
}
|
284
|
+
end
|
285
|
+
params do
|
286
|
+
requires :happy
|
287
|
+
optional :days
|
288
|
+
end
|
289
|
+
get '/test' do
|
290
|
+
{
|
291
|
+
params: params,
|
292
|
+
declared_params: declared(params, include_parent_namespaces: false)
|
293
|
+
}
|
294
|
+
end
|
295
|
+
end
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
it 'should include params defined in the parent namespace' do
|
300
|
+
get '/something/123', foo: 'test', extra: 'hello'
|
301
|
+
expect(last_response.status).to eq 200
|
302
|
+
json = JSON.parse(last_response.body, symbolize_names: true)
|
303
|
+
expect(json[:params][:id]).to eq 123
|
304
|
+
expect(json[:declared_params].keys).to match_array [:foo, :bar, :id]
|
305
|
+
end
|
306
|
+
|
307
|
+
it 'does not include params defined in the parent namespace with include_parent_namespaces: false' do
|
308
|
+
get '/something/123/test', happy: 'test', extra: 'hello'
|
309
|
+
expect(last_response.status).to eq 200
|
310
|
+
json = JSON.parse(last_response.body, symbolize_names: true)
|
311
|
+
expect(json[:params][:id]).to eq 123
|
312
|
+
expect(json[:declared_params].keys).to match_array [:happy, :days]
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
257
316
|
describe '#params' do
|
258
317
|
it 'is available to the caller' do
|
259
318
|
subject.get('/hey') do
|
@@ -354,22 +413,22 @@ describe Grape::Endpoint do
|
|
354
413
|
end
|
355
414
|
|
356
415
|
it 'converts JSON bodies to params' do
|
357
|
-
post '/request_body', MultiJson.dump(user: 'Bobby T.'),
|
416
|
+
post '/request_body', MultiJson.dump(user: 'Bobby T.'), 'CONTENT_TYPE' => 'application/json'
|
358
417
|
last_response.body.should == 'Bobby T.'
|
359
418
|
end
|
360
419
|
|
361
420
|
it 'does not convert empty JSON bodies to params' do
|
362
|
-
put '/request_body', '',
|
421
|
+
put '/request_body', '', 'CONTENT_TYPE' => 'application/json'
|
363
422
|
last_response.body.should == ''
|
364
423
|
end
|
365
424
|
|
366
425
|
it 'converts XML bodies to params' do
|
367
|
-
post '/request_body', '<user>Bobby T.</user>',
|
426
|
+
post '/request_body', '<user>Bobby T.</user>', 'CONTENT_TYPE' => 'application/xml'
|
368
427
|
last_response.body.should == 'Bobby T.'
|
369
428
|
end
|
370
429
|
|
371
430
|
it 'converts XML bodies to params' do
|
372
|
-
put '/request_body', '<user>Bobby T.</user>',
|
431
|
+
put '/request_body', '<user>Bobby T.</user>', 'CONTENT_TYPE' => 'application/xml'
|
373
432
|
last_response.body.should == 'Bobby T.'
|
374
433
|
end
|
375
434
|
|
@@ -378,7 +437,7 @@ describe Grape::Endpoint do
|
|
378
437
|
error! 400, "expected nil" if params[:version]
|
379
438
|
params[:user]
|
380
439
|
end
|
381
|
-
post '/omitted_params', MultiJson.dump(user: 'Bob'),
|
440
|
+
post '/omitted_params', MultiJson.dump(user: 'Bob'), 'CONTENT_TYPE' => 'application/json'
|
382
441
|
last_response.status.should == 201
|
383
442
|
last_response.body.should == "Bob"
|
384
443
|
end
|
@@ -390,11 +449,70 @@ describe Grape::Endpoint do
|
|
390
449
|
subject.put '/request_body' do
|
391
450
|
params[:user]
|
392
451
|
end
|
393
|
-
put '/request_body', '<user>Bobby T.</user>',
|
452
|
+
put '/request_body', '<user>Bobby T.</user>', 'CONTENT_TYPE' => 'application/xml'
|
394
453
|
last_response.status.should == 406
|
395
454
|
last_response.body.should == '{"error":"The requested content-type \'application/xml\' is not supported."}'
|
396
455
|
end
|
397
456
|
|
457
|
+
context 'content type with params' do
|
458
|
+
before do
|
459
|
+
subject.format :json
|
460
|
+
subject.content_type :json, 'application/json; charset=utf-8'
|
461
|
+
|
462
|
+
subject.post do
|
463
|
+
params[:data]
|
464
|
+
end
|
465
|
+
post '/', MultiJson.dump(data: { some: 'payload' }), 'CONTENT_TYPE' => 'application/json'
|
466
|
+
end
|
467
|
+
|
468
|
+
it "should not response with 406 for same type without params" do
|
469
|
+
last_response.status.should_not be 406
|
470
|
+
end
|
471
|
+
|
472
|
+
it "should response with given content type in headers" do
|
473
|
+
last_response.headers['Content-Type'].should eq 'application/json; charset=utf-8'
|
474
|
+
end
|
475
|
+
|
476
|
+
end
|
477
|
+
|
478
|
+
context 'precedence' do
|
479
|
+
|
480
|
+
before do
|
481
|
+
subject.format :json
|
482
|
+
subject.namespace '/:id' do
|
483
|
+
get do
|
484
|
+
{
|
485
|
+
params: params[:id]
|
486
|
+
}
|
487
|
+
end
|
488
|
+
post do
|
489
|
+
{
|
490
|
+
params: params[:id]
|
491
|
+
}
|
492
|
+
end
|
493
|
+
put do
|
494
|
+
{
|
495
|
+
params: params[:id]
|
496
|
+
}
|
497
|
+
end
|
498
|
+
end
|
499
|
+
end
|
500
|
+
|
501
|
+
it 'route string params have higher precedence than body params' do
|
502
|
+
post '/123', { id: 456 }.to_json
|
503
|
+
expect(JSON.parse(last_response.body)['params']).to eq '123'
|
504
|
+
put '/123', { id: 456 }.to_json
|
505
|
+
expect(JSON.parse(last_response.body)['params']).to eq '123'
|
506
|
+
end
|
507
|
+
|
508
|
+
it 'route string params have higher precedence than URL params' do
|
509
|
+
get '/123?id=456'
|
510
|
+
expect(JSON.parse(last_response.body)['params']).to eq '123'
|
511
|
+
post '/123?id=456'
|
512
|
+
expect(JSON.parse(last_response.body)['params']).to eq '123'
|
513
|
+
end
|
514
|
+
end
|
515
|
+
|
398
516
|
end
|
399
517
|
|
400
518
|
describe '#error!' do
|
@@ -405,7 +523,7 @@ describe Grape::Endpoint do
|
|
405
523
|
end
|
406
524
|
|
407
525
|
get '/hey'
|
408
|
-
last_response.status.should ==
|
526
|
+
last_response.status.should == 500
|
409
527
|
last_response.body.should == "This is not valid."
|
410
528
|
end
|
411
529
|
|
@@ -428,6 +546,16 @@ describe Grape::Endpoint do
|
|
428
546
|
last_response.status.should == 403
|
429
547
|
last_response.body.should == '{"dude":"rad"}'
|
430
548
|
end
|
549
|
+
|
550
|
+
it 'can specifiy headers' do
|
551
|
+
subject.get '/hey' do
|
552
|
+
error!({ 'dude' => 'rad' }, 403, 'X-Custom' => 'value')
|
553
|
+
end
|
554
|
+
|
555
|
+
get '/hey.json'
|
556
|
+
last_response.status.should == 403
|
557
|
+
last_response.headers['X-Custom'].should == 'value'
|
558
|
+
end
|
431
559
|
end
|
432
560
|
|
433
561
|
describe '#redirect' do
|
@@ -503,7 +631,7 @@ describe Grape::Endpoint do
|
|
503
631
|
describe '.generate_api_method' do
|
504
632
|
it 'raises NameError if the method name is already in use' do
|
505
633
|
expect {
|
506
|
-
Grape::Endpoint.generate_api_method("version", &proc {
|
634
|
+
Grape::Endpoint.generate_api_method("version", &proc {})
|
507
635
|
}.to raise_error(NameError)
|
508
636
|
end
|
509
637
|
it 'raises ArgumentError if a block is not given' do
|
@@ -512,7 +640,7 @@ describe Grape::Endpoint do
|
|
512
640
|
}.to raise_error(ArgumentError)
|
513
641
|
end
|
514
642
|
it 'returns a Proc' do
|
515
|
-
Grape::Endpoint.generate_api_method("GET test for a proc", &proc {
|
643
|
+
Grape::Endpoint.generate_api_method("GET test for a proc", &proc {}).should be_a Proc
|
516
644
|
end
|
517
645
|
end
|
518
646
|
|
@@ -604,4 +732,23 @@ describe Grape::Endpoint do
|
|
604
732
|
end
|
605
733
|
end
|
606
734
|
|
735
|
+
context 'version headers' do
|
736
|
+
before do
|
737
|
+
# NOTE: a 404 is returned instead of the 406 if cascade: false is not set.
|
738
|
+
subject.version 'v1', using: :header, vendor: 'ohanapi', cascade: false
|
739
|
+
subject.get '/test' do
|
740
|
+
"Hello!"
|
741
|
+
end
|
742
|
+
end
|
743
|
+
|
744
|
+
it 'result in a 406 response if they are invalid' do
|
745
|
+
get '/test', {}, 'HTTP_ACCEPT' => 'application/vnd.ohanapi.v1+json'
|
746
|
+
last_response.status.should == 406
|
747
|
+
end
|
748
|
+
|
749
|
+
it 'result in a 406 response if they cannot be parsed by rack-accept' do
|
750
|
+
get '/test', {}, 'HTTP_ACCEPT' => 'application/vnd.ohanapi.v1+json; version=1'
|
751
|
+
last_response.status.should == 406
|
752
|
+
end
|
753
|
+
end
|
607
754
|
end
|
data/spec/grape/entity_spec.rb
CHANGED
@@ -109,6 +109,31 @@ describe Grape::Entity do
|
|
109
109
|
last_response.body.should == 'Auto-detect!'
|
110
110
|
end
|
111
111
|
|
112
|
+
it 'does not run autodetection for Entity when explicitely provided' do
|
113
|
+
entity = Class.new(Grape::Entity)
|
114
|
+
some_array = Array.new
|
115
|
+
|
116
|
+
subject.get '/example' do
|
117
|
+
present some_array, with: entity
|
118
|
+
end
|
119
|
+
|
120
|
+
some_array.should_not_receive(:first)
|
121
|
+
get '/example'
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'autodetection does not use Entity if it is not a presenter' do
|
125
|
+
some_model = Class.new
|
126
|
+
entity = Class.new
|
127
|
+
|
128
|
+
some_model.class.const_set :Entity, entity
|
129
|
+
|
130
|
+
subject.get '/example' do
|
131
|
+
present some_model
|
132
|
+
end
|
133
|
+
get '/example'
|
134
|
+
entity.should_not_receive(:represent)
|
135
|
+
end
|
136
|
+
|
112
137
|
it 'adds a root key to the output if one is given' do
|
113
138
|
subject.get '/example' do
|
114
139
|
present({ abc: 'def' }, root: :root)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
describe Grape::Exceptions::ValidationErrors do
|
5
|
+
let(:validation_message) { "FooBar is invalid" }
|
6
|
+
let(:validation_error) { OpenStruct.new(param: validation_message) }
|
7
|
+
|
8
|
+
context "message" do
|
9
|
+
context "is not repeated" do
|
10
|
+
let(:error) do
|
11
|
+
described_class.new(errors: [validation_error, validation_error])
|
12
|
+
end
|
13
|
+
subject(:message) { error.message.split(',').map(&:strip) }
|
14
|
+
|
15
|
+
it { expect(message).to include validation_message }
|
16
|
+
it { expect(message.size).to eq 1 }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -5,7 +5,7 @@ describe Grape::Middleware::Auth::OAuth2 do
|
|
5
5
|
attr_accessor :token
|
6
6
|
|
7
7
|
def self.verify(token)
|
8
|
-
FakeToken.new(token) if %w(g e).include?(token[0..0])
|
8
|
+
FakeToken.new(token) if !!token && %w(g e).include?(token[0..0])
|
9
9
|
end
|
10
10
|
|
11
11
|
def initialize(token)
|
@@ -30,7 +30,7 @@ describe Grape::Middleware::Auth::OAuth2 do
|
|
30
30
|
|
31
31
|
context 'with the token in the query string' do
|
32
32
|
context 'and a valid token' do
|
33
|
-
before { get '/awesome?
|
33
|
+
before { get '/awesome?access_token=g123' }
|
34
34
|
|
35
35
|
it 'sets env["api.token"]' do
|
36
36
|
last_response.body.should == 'g123'
|
@@ -40,7 +40,7 @@ describe Grape::Middleware::Auth::OAuth2 do
|
|
40
40
|
context 'and an invalid token' do
|
41
41
|
before do
|
42
42
|
@err = catch :error do
|
43
|
-
get '/awesome?
|
43
|
+
get '/awesome?access_token=b123'
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
@@ -49,7 +49,7 @@ describe Grape::Middleware::Auth::OAuth2 do
|
|
49
49
|
end
|
50
50
|
|
51
51
|
it 'sets the WWW-Authenticate header in the response' do
|
52
|
-
@err[:headers]['WWW-Authenticate'].should == "OAuth realm='OAuth API', error='
|
52
|
+
@err[:headers]['WWW-Authenticate'].should == "OAuth realm='OAuth API', error='invalid_grant'"
|
53
53
|
end
|
54
54
|
end
|
55
55
|
end
|
@@ -57,34 +57,79 @@ describe Grape::Middleware::Auth::OAuth2 do
|
|
57
57
|
context 'with an expired token' do
|
58
58
|
before do
|
59
59
|
@err = catch :error do
|
60
|
-
get '/awesome?
|
60
|
+
get '/awesome?access_token=e123'
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
|
-
it
|
65
|
-
|
64
|
+
it 'throws an error' do
|
65
|
+
@err[:status].should == 401
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'sets the WWW-Authenticate header in the response to error' do
|
69
|
+
@err[:headers]['WWW-Authenticate'].should == "OAuth realm='OAuth API', error='invalid_grant'"
|
70
|
+
end
|
66
71
|
end
|
67
72
|
|
68
73
|
%w(HTTP_AUTHORIZATION X_HTTP_AUTHORIZATION X-HTTP_AUTHORIZATION REDIRECT_X_HTTP_AUTHORIZATION).each do |head|
|
69
|
-
context
|
70
|
-
before
|
71
|
-
|
74
|
+
context "with the token in the #{head} header" do
|
75
|
+
before do
|
76
|
+
get '/awesome', {}, head => 'OAuth g123'
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'sets env["api.token"]' do
|
80
|
+
last_response.body.should == 'g123'
|
81
|
+
end
|
72
82
|
end
|
73
83
|
end
|
74
84
|
|
75
85
|
context 'with the token in the POST body' do
|
76
|
-
before
|
77
|
-
|
86
|
+
before do
|
87
|
+
post '/awesome', 'access_token' => 'g123'
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'sets env["api.token"]' do
|
91
|
+
last_response.body.should == 'g123'
|
92
|
+
end
|
78
93
|
end
|
79
94
|
|
80
95
|
context 'when accessing something outside its scope' do
|
81
96
|
before do
|
82
97
|
@err = catch :error do
|
83
|
-
get '/forbidden?
|
98
|
+
get '/forbidden?access_token=g123'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'throws an error' do
|
103
|
+
@err[:status].should == 403
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'sets the WWW-Authenticate header in the response to error' do
|
107
|
+
@err[:headers]['WWW-Authenticate'].should == "OAuth realm='OAuth API', error='insufficient_scope'"
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'when authorization is not required' do
|
112
|
+
def app
|
113
|
+
Rack::Builder.app do
|
114
|
+
use Grape::Middleware::Auth::OAuth2, token_class: 'FakeToken', required: false
|
115
|
+
run lambda { |env| [200, {}, [(env['api.token'].token if env['api.token'])]] }
|
84
116
|
end
|
85
117
|
end
|
86
118
|
|
87
|
-
|
88
|
-
|
119
|
+
context 'with no token' do
|
120
|
+
before { post '/awesome' }
|
121
|
+
|
122
|
+
it 'succeeds anyway' do
|
123
|
+
last_response.status.should == 200
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
context 'with a valid token' do
|
128
|
+
before { get '/awesome?access_token=g123' }
|
129
|
+
|
130
|
+
it 'sets env["api.token"]' do
|
131
|
+
last_response.body.should == 'g123'
|
132
|
+
end
|
133
|
+
end
|
89
134
|
end
|
90
135
|
end
|