rack-cors 0.4.1 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.travis.yml +5 -3
- data/CHANGELOG.md +73 -0
- data/Gemfile +1 -1
- data/README.md +23 -19
- data/lib/rack/cors/version.rb +1 -1
- data/lib/rack/cors.rb +125 -83
- data/rack-cors.gemspec +7 -6
- data/test/cors/test.cors.coffee +6 -1
- data/test/cors/test.cors.js +17 -9
- data/test/unit/cors_test.rb +222 -57
- data/test/unit/dsl_test.rb +11 -0
- data/test/unit/insecure.ru +8 -0
- data/test/unit/test.ru +12 -0
- metadata +47 -27
- data/CHANGELOG +0 -34
data/test/cors/test.cors.js
CHANGED
@@ -1,26 +1,34 @@
|
|
1
|
-
// Generated by CoffeeScript
|
1
|
+
// Generated by CoffeeScript 2.3.1
|
2
2
|
(function() {
|
3
3
|
var CORS_SERVER;
|
4
4
|
|
5
|
-
CORS_SERVER = '
|
5
|
+
CORS_SERVER = '127.0.0.1.xip.io:9292';
|
6
6
|
|
7
7
|
describe('CORS', function() {
|
8
8
|
it('should allow access to dynamic resource', function(done) {
|
9
|
-
return $.get(
|
9
|
+
return $.get(`http://${CORS_SERVER}/`, function(data, status, xhr) {
|
10
10
|
expect(data).to.eql('Hello world');
|
11
11
|
return done();
|
12
12
|
});
|
13
13
|
});
|
14
14
|
it('should allow PUT access to dynamic resource', function(done) {
|
15
|
-
return $.ajax(
|
15
|
+
return $.ajax(`http://${CORS_SERVER}/`, {
|
16
16
|
type: 'PUT'
|
17
17
|
}).done(function(data, textStatus, jqXHR) {
|
18
18
|
expect(data).to.eql('Hello world');
|
19
19
|
return done();
|
20
20
|
});
|
21
21
|
});
|
22
|
+
it('should allow PATCH access to dynamic resource', function(done) {
|
23
|
+
return $.ajax(`http://${CORS_SERVER}/`, {
|
24
|
+
type: 'PATCH'
|
25
|
+
}).done(function(data, textStatus, jqXHR) {
|
26
|
+
expect(data).to.eql('Hello world');
|
27
|
+
return done();
|
28
|
+
});
|
29
|
+
});
|
22
30
|
it('should allow HEAD access to dynamic resource', function(done) {
|
23
|
-
return $.ajax(
|
31
|
+
return $.ajax(`http://${CORS_SERVER}/`, {
|
24
32
|
type: 'HEAD'
|
25
33
|
}).done(function(data, textStatus, jqXHR) {
|
26
34
|
expect(jqXHR.status).to.eql(200);
|
@@ -28,7 +36,7 @@
|
|
28
36
|
});
|
29
37
|
});
|
30
38
|
it('should allow DELETE access to dynamic resource', function(done) {
|
31
|
-
return $.ajax(
|
39
|
+
return $.ajax(`http://${CORS_SERVER}/`, {
|
32
40
|
type: 'DELETE'
|
33
41
|
}).done(function(data, textStatus, jqXHR) {
|
34
42
|
expect(data).to.eql('Hello world');
|
@@ -36,7 +44,7 @@
|
|
36
44
|
});
|
37
45
|
});
|
38
46
|
it('should allow OPTIONS access to dynamic resource', function(done) {
|
39
|
-
return $.ajax(
|
47
|
+
return $.ajax(`http://${CORS_SERVER}/`, {
|
40
48
|
type: 'OPTIONS'
|
41
49
|
}).done(function(data, textStatus, jqXHR) {
|
42
50
|
expect(jqXHR.status).to.eql(200);
|
@@ -44,7 +52,7 @@
|
|
44
52
|
});
|
45
53
|
});
|
46
54
|
it('should allow access to static resource', function(done) {
|
47
|
-
return $.get(
|
55
|
+
return $.get(`http://${CORS_SERVER}/static.txt`, function(data, status, xhr) {
|
48
56
|
expect($.trim(data)).to.eql("hello world");
|
49
57
|
return done();
|
50
58
|
});
|
@@ -52,7 +60,7 @@
|
|
52
60
|
return it('should allow post resource', function(done) {
|
53
61
|
return $.ajax({
|
54
62
|
type: 'POST',
|
55
|
-
url:
|
63
|
+
url: `http://${CORS_SERVER}/cors`,
|
56
64
|
beforeSend: function(xhr) {
|
57
65
|
return xhr.setRequestHeader('X-Requested-With', 'XMLHTTPRequest');
|
58
66
|
},
|
data/test/unit/cors_test.rb
CHANGED
@@ -17,18 +17,57 @@ Rack::Test::Methods.class_eval do
|
|
17
17
|
def_delegator :current_session, :options
|
18
18
|
end
|
19
19
|
|
20
|
+
module MiniTest::Assertions
|
21
|
+
def assert_cors_success(response)
|
22
|
+
assert !response.headers['Access-Control-Allow-Origin'].nil?, "Expected a successful CORS response"
|
23
|
+
end
|
24
|
+
|
25
|
+
def assert_not_cors_success(response)
|
26
|
+
assert response.headers['Access-Control-Allow-Origin'].nil?, "Expected a failed CORS response"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class CaptureResult
|
31
|
+
def initialize(app, options = {})
|
32
|
+
@app = app
|
33
|
+
@result_holder = options[:holder]
|
34
|
+
end
|
35
|
+
|
36
|
+
def call(env)
|
37
|
+
response = @app.call(env)
|
38
|
+
@result_holder.cors_result = env[Rack::Cors::RACK_CORS]
|
39
|
+
return response
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class FakeProxy
|
44
|
+
def initialize(app, options = {})
|
45
|
+
@app = app
|
46
|
+
end
|
47
|
+
|
48
|
+
def call(env)
|
49
|
+
status, headers, body = @app.call(env)
|
50
|
+
headers['Vary'] = %w(Origin User-Agent)
|
51
|
+
[status, headers, body]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
Rack::MockResponse.infect_an_assertion :assert_cors_success, :must_render_cors_success, :only_one_argument
|
56
|
+
Rack::MockResponse.infect_an_assertion :assert_not_cors_success, :wont_render_cors_success, :only_one_argument
|
57
|
+
|
20
58
|
describe Rack::Cors do
|
21
59
|
include Rack::Test::Methods
|
22
60
|
|
23
61
|
attr_accessor :cors_result
|
24
62
|
|
25
|
-
def load_app(name)
|
63
|
+
def load_app(name, options = {})
|
26
64
|
test = self
|
27
65
|
Rack::Builder.new do
|
66
|
+
use CaptureResult, :holder => test
|
28
67
|
eval File.read(File.dirname(__FILE__) + "/#{name}.ru")
|
68
|
+
use FakeProxy if options[:proxy]
|
29
69
|
map('/') do
|
30
70
|
run proc { |env|
|
31
|
-
test.cors_result = env[Rack::Cors::ENV_KEY]
|
32
71
|
[200, {'Content-Type' => 'text/html'}, ['success']]
|
33
72
|
}
|
34
73
|
end
|
@@ -38,84 +77,108 @@ describe Rack::Cors do
|
|
38
77
|
let(:app) { load_app('test') }
|
39
78
|
|
40
79
|
it 'should support simple CORS request' do
|
41
|
-
|
80
|
+
successful_cors_request
|
42
81
|
cors_result.must_be :hit
|
43
82
|
end
|
44
83
|
|
45
84
|
it "should not return CORS headers if Origin header isn't present" do
|
46
85
|
get '/'
|
47
|
-
|
86
|
+
last_response.wont_render_cors_success
|
48
87
|
cors_result.wont_be :hit
|
49
88
|
end
|
50
89
|
|
51
90
|
it 'should support OPTIONS CORS request' do
|
52
|
-
|
91
|
+
successful_cors_request '/options', :method => :options
|
53
92
|
end
|
54
93
|
|
55
94
|
it 'should support regex origins configuration' do
|
56
|
-
|
95
|
+
successful_cors_request :origin => 'http://192.168.0.1:1234'
|
57
96
|
end
|
58
97
|
|
59
98
|
it 'should support subdomain example' do
|
60
|
-
|
99
|
+
successful_cors_request :origin => 'http://subdomain.example.com'
|
61
100
|
end
|
62
101
|
|
63
102
|
it 'should support proc origins configuration' do
|
64
|
-
|
103
|
+
successful_cors_request '/proc-origin', :origin => 'http://10.10.10.10:3000'
|
104
|
+
end
|
105
|
+
|
106
|
+
it 'should support lambda origin configuration' do
|
107
|
+
successful_cors_request '/lambda-origin', :origin => 'http://10.10.10.10:3000'
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'should support proc origins configuration (inverse)' do
|
111
|
+
cors_request '/proc-origin', :origin => 'http://bad.guy'
|
112
|
+
last_response.wont_render_cors_success
|
65
113
|
end
|
66
114
|
|
67
115
|
it 'should not mix up path rules across origins' do
|
68
116
|
header 'Origin', 'http://10.10.10.10:3000'
|
69
117
|
get '/' # / is configured in a separate rule block
|
70
|
-
|
118
|
+
last_response.wont_render_cors_success
|
71
119
|
end
|
72
120
|
|
73
121
|
it 'should support alternative X-Origin header' do
|
74
122
|
header 'X-Origin', 'http://localhost:3000'
|
75
123
|
get '/'
|
76
|
-
|
124
|
+
last_response.must_render_cors_success
|
77
125
|
end
|
78
126
|
|
79
127
|
it 'should support expose header configuration' do
|
80
|
-
|
128
|
+
successful_cors_request '/expose_single_header'
|
81
129
|
last_response.headers['Access-Control-Expose-Headers'].must_equal 'expose-test'
|
82
130
|
end
|
83
131
|
|
84
132
|
it 'should support expose multiple header configuration' do
|
85
|
-
|
133
|
+
successful_cors_request '/expose_multiple_headers'
|
86
134
|
last_response.headers['Access-Control-Expose-Headers'].must_equal 'expose-test-1, expose-test-2'
|
87
135
|
end
|
88
136
|
|
89
137
|
# Explanation: http://www.fastly.com/blog/best-practices-for-using-the-vary-header/
|
90
138
|
it "should add Vary header if resource matches even if Origin header isn't present" do
|
91
139
|
get '/'
|
92
|
-
|
140
|
+
last_response.wont_render_cors_success
|
93
141
|
last_response.headers['Vary'].must_equal 'Origin'
|
94
142
|
end
|
95
143
|
|
96
144
|
it "should add Vary header based on :vary option" do
|
97
|
-
|
145
|
+
successful_cors_request '/vary_test'
|
98
146
|
last_response.headers['Vary'].must_equal 'Origin, Host'
|
99
147
|
end
|
100
148
|
|
149
|
+
it "decode URL and resolve paths before resource matching" do
|
150
|
+
header 'Origin', 'http://localhost:3000'
|
151
|
+
get '/public/a/..%2F..%2Fprivate/stuff'
|
152
|
+
last_response.wont_render_cors_success
|
153
|
+
end
|
154
|
+
|
155
|
+
describe 'with array of upstream Vary headers' do
|
156
|
+
let(:app) { load_app('test', { proxy: true }) }
|
157
|
+
|
158
|
+
it 'should add to them' do
|
159
|
+
successful_cors_request '/vary_test'
|
160
|
+
last_response.headers['Vary'].must_equal 'Origin, User-Agent, Host'
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
101
164
|
it 'should add Vary header if Access-Control-Allow-Origin header was added and if it is specific' do
|
102
|
-
|
165
|
+
successful_cors_request '/', :origin => "http://192.168.0.3:8080"
|
103
166
|
last_response.headers['Access-Control-Allow-Origin'].must_equal 'http://192.168.0.3:8080'
|
104
167
|
last_response.headers['Vary'].wont_be_nil
|
105
168
|
end
|
106
169
|
|
107
170
|
it 'should add Vary header even if Access-Control-Allow-Origin header was added and it is generic (*)' do
|
108
|
-
|
171
|
+
successful_cors_request '/public_without_credentials', :origin => "http://192.168.1.3:8080"
|
109
172
|
last_response.headers['Access-Control-Allow-Origin'].must_equal '*'
|
110
173
|
last_response.headers['Vary'].must_equal 'Origin'
|
111
174
|
end
|
112
175
|
|
113
176
|
it 'should support multi allow configurations for the same resource' do
|
114
|
-
|
177
|
+
successful_cors_request '/multi-allow-config', :origin => "http://mucho-grande.com"
|
115
178
|
last_response.headers['Access-Control-Allow-Origin'].must_equal 'http://mucho-grande.com'
|
116
179
|
last_response.headers['Vary'].must_equal 'Origin'
|
117
180
|
|
118
|
-
|
181
|
+
successful_cors_request '/multi-allow-config', :origin => "http://192.168.1.3:8080"
|
119
182
|
last_response.headers['Access-Control-Allow-Origin'].must_equal '*'
|
120
183
|
last_response.headers['Vary'].must_equal 'Origin'
|
121
184
|
end
|
@@ -128,15 +191,25 @@ describe Rack::Cors do
|
|
128
191
|
it "should not apply CORS headers if it does not match conditional on resource" do
|
129
192
|
header 'Origin', 'http://192.168.0.1:1234'
|
130
193
|
get '/conditional'
|
131
|
-
|
194
|
+
last_response.wont_render_cors_success
|
132
195
|
end
|
133
196
|
|
134
197
|
it "should apply CORS headers if it does match conditional on resource" do
|
135
198
|
header 'X-OK', '1'
|
136
|
-
|
199
|
+
successful_cors_request '/conditional', :origin => 'http://192.168.0.1:1234'
|
200
|
+
end
|
201
|
+
|
202
|
+
it "should not allow everything if Origin is configured as blank string" do
|
203
|
+
cors_request '/blank-origin', origin: "http://example.net"
|
204
|
+
last_response.wont_render_cors_success
|
205
|
+
end
|
206
|
+
|
207
|
+
it "should not allow credentials for public resources" do
|
208
|
+
successful_cors_request '/public'
|
209
|
+
last_response.headers['Access-Control-Allow-Credentials'].must_be_nil
|
137
210
|
end
|
138
211
|
|
139
|
-
|
212
|
+
describe 'logging' do
|
140
213
|
it 'should not log debug messages if debug option is false' do
|
141
214
|
app = mock
|
142
215
|
app.stubs(:call).returns(200, {}, [''])
|
@@ -199,79 +272,127 @@ describe Rack::Cors do
|
|
199
272
|
cors.call({'HTTP_ORIGIN' => 'test.com'})
|
200
273
|
end
|
201
274
|
end
|
275
|
+
|
276
|
+
it 'should use Logger if none is set' do
|
277
|
+
app = mock
|
278
|
+
app.stubs(:call).returns([200, {}, ['']])
|
279
|
+
|
280
|
+
logger = mock
|
281
|
+
Logger.expects(:new).returns(logger)
|
282
|
+
logger.expects(:tap).returns(logger)
|
283
|
+
logger.expects(:debug)
|
284
|
+
|
285
|
+
cors = Rack::Cors.new(app, :debug => true) {}
|
286
|
+
cors.call({'HTTP_ORIGIN' => 'test.com'})
|
287
|
+
end
|
202
288
|
end
|
203
289
|
|
204
290
|
describe 'preflight requests' do
|
205
291
|
it 'should fail if origin is invalid' do
|
206
292
|
preflight_request('http://allyourdataarebelongtous.com', '/')
|
207
|
-
|
293
|
+
last_response.wont_render_cors_success
|
208
294
|
cors_result.wont_be :hit
|
209
295
|
cors_result.must_be :preflight
|
210
296
|
end
|
211
297
|
|
212
298
|
it 'should fail if Access-Control-Request-Method is not allowed' do
|
213
299
|
preflight_request('http://localhost:3000', '/get-only', :method => :post)
|
214
|
-
|
300
|
+
last_response.wont_render_cors_success
|
301
|
+
cors_result.miss_reason.must_equal Rack::Cors::Result::MISS_DENY_METHOD
|
302
|
+
cors_result.wont_be :hit
|
303
|
+
cors_result.must_be :preflight
|
215
304
|
end
|
216
305
|
|
217
306
|
it 'should fail if header is not allowed' do
|
218
307
|
preflight_request('http://localhost:3000', '/single_header', :headers => 'Fooey')
|
219
|
-
|
308
|
+
last_response.wont_render_cors_success
|
309
|
+
cors_result.miss_reason.must_equal Rack::Cors::Result::MISS_DENY_HEADER
|
310
|
+
cors_result.wont_be :hit
|
311
|
+
cors_result.must_be :preflight
|
220
312
|
end
|
221
313
|
|
222
314
|
it 'should allow any header if headers = :any' do
|
223
315
|
preflight_request('http://localhost:3000', '/', :headers => 'Fooey')
|
224
|
-
|
316
|
+
last_response.must_render_cors_success
|
225
317
|
end
|
226
318
|
|
227
319
|
it 'should allow any method if methods = :any' do
|
228
320
|
preflight_request('http://localhost:3000', '/', :methods => :any)
|
229
|
-
|
321
|
+
last_response.must_render_cors_success
|
322
|
+
end
|
323
|
+
|
324
|
+
it 'allows PATCH method' do
|
325
|
+
preflight_request('http://localhost:3000', '/', :methods => [ :patch ])
|
326
|
+
last_response.must_render_cors_success
|
230
327
|
end
|
231
328
|
|
232
329
|
it 'should allow header case insensitive match' do
|
233
330
|
preflight_request('http://localhost:3000', '/single_header', :headers => 'X-Domain-Token')
|
234
|
-
|
331
|
+
last_response.must_render_cors_success
|
235
332
|
end
|
236
333
|
|
237
334
|
it 'should allow multiple headers match' do
|
238
335
|
# Webkit style
|
239
336
|
preflight_request('http://localhost:3000', '/two_headers', :headers => 'X-Requested-With, X-Domain-Token')
|
240
|
-
|
337
|
+
last_response.must_render_cors_success
|
241
338
|
|
242
339
|
# Gecko style
|
243
340
|
preflight_request('http://localhost:3000', '/two_headers', :headers => 'x-requested-with,x-domain-token')
|
244
|
-
|
341
|
+
last_response.must_render_cors_success
|
245
342
|
end
|
246
343
|
|
247
344
|
it 'should * origin should allow any origin' do
|
248
345
|
preflight_request('http://locohost:3000', '/public')
|
249
|
-
|
250
|
-
last_response.headers['Access-Control-Allow-Origin'].must_equal '
|
346
|
+
last_response.must_render_cors_success
|
347
|
+
last_response.headers['Access-Control-Allow-Origin'].must_equal '*'
|
251
348
|
end
|
252
349
|
|
253
350
|
it 'should * origin should allow any origin, and set * if no credentials required' do
|
254
351
|
preflight_request('http://locohost:3000', '/public_without_credentials')
|
255
|
-
|
352
|
+
last_response.must_render_cors_success
|
256
353
|
last_response.headers['Access-Control-Allow-Origin'].must_equal '*'
|
257
354
|
end
|
258
355
|
|
259
|
-
it 'should "null" origin, allowed as "file://", returned as "null" in header' do
|
260
|
-
preflight_request('null', '/')
|
261
|
-
should_render_cors_success
|
262
|
-
last_response.headers['Access-Control-Allow-Origin'].must_equal 'null'
|
263
|
-
end
|
264
|
-
|
265
356
|
it 'should return "file://" as header with "file://" as origin' do
|
266
357
|
preflight_request('file://', '/')
|
267
|
-
|
358
|
+
last_response.must_render_cors_success
|
268
359
|
last_response.headers['Access-Control-Allow-Origin'].must_equal 'file://'
|
269
360
|
end
|
270
361
|
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
362
|
+
describe '' do
|
363
|
+
|
364
|
+
let(:app) do
|
365
|
+
test = self
|
366
|
+
Rack::Builder.new do
|
367
|
+
use CaptureResult, holder: test
|
368
|
+
use Rack::Cors, debug: true, logger: Logger.new(StringIO.new) do
|
369
|
+
allow do
|
370
|
+
origins '*'
|
371
|
+
resource '/', :methods => :post
|
372
|
+
end
|
373
|
+
end
|
374
|
+
map('/') do
|
375
|
+
run ->(env) { [500, {}, ['FAIL!']] }
|
376
|
+
end
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
it "should not send failed preflight requests thru the app" do
|
381
|
+
preflight_request('http://localhost', '/', :method => :unsupported)
|
382
|
+
last_response.wont_render_cors_success
|
383
|
+
last_response.status.must_equal 200
|
384
|
+
cors_result.must_be :preflight
|
385
|
+
cors_result.wont_be :hit
|
386
|
+
cors_result.miss_reason.must_equal Rack::Cors::Result::MISS_DENY_METHOD
|
387
|
+
end
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
describe "with insecure configuration" do
|
392
|
+
let(:app) { load_app('insecure') }
|
393
|
+
|
394
|
+
it "should raise an error" do
|
395
|
+
proc { cors_request '/public' }.must_raise Rack::Cors::Resource::CorsMisconfigurationError
|
275
396
|
end
|
276
397
|
end
|
277
398
|
|
@@ -279,7 +400,7 @@ describe Rack::Cors do
|
|
279
400
|
let(:app) { load_app("non_http") }
|
280
401
|
|
281
402
|
it 'should support non http/https origins' do
|
282
|
-
|
403
|
+
successful_cors_request '/public', origin: 'content://com.company.app'
|
283
404
|
end
|
284
405
|
end
|
285
406
|
|
@@ -308,19 +429,67 @@ describe Rack::Cors do
|
|
308
429
|
end
|
309
430
|
end
|
310
431
|
map('/') do
|
311
|
-
run ->(env) { [200, {'
|
432
|
+
run ->(env) { [200, {'Access-Control-Allow-Origin' => 'http://foo.net'}, ['success']] }
|
312
433
|
end
|
313
434
|
end
|
314
435
|
end
|
315
436
|
|
316
437
|
it "should return app header" do
|
317
|
-
|
438
|
+
successful_cors_request origin: "http://example.net"
|
318
439
|
last_response.headers['Access-Control-Allow-Origin'].must_equal "http://foo.net"
|
319
440
|
end
|
320
441
|
|
321
442
|
it "should return original headers if in debug" do
|
322
|
-
|
323
|
-
last_response.headers['X-Rack-CORS-Original-Access-Control-Allow-Origin'].must_equal "
|
443
|
+
successful_cors_request origin: "http://example.net"
|
444
|
+
last_response.headers['X-Rack-CORS-Original-Access-Control-Allow-Origin'].must_equal "*"
|
445
|
+
end
|
446
|
+
end
|
447
|
+
|
448
|
+
describe 'with headers set to nil' do
|
449
|
+
let(:app) do
|
450
|
+
Rack::Builder.new do
|
451
|
+
use Rack::Cors do
|
452
|
+
allow do
|
453
|
+
origins '*'
|
454
|
+
resource '/', headers: nil
|
455
|
+
end
|
456
|
+
end
|
457
|
+
map('/') do
|
458
|
+
run ->(env) { [200, {'Content-Type' => 'text/html'}, ['hello']] }
|
459
|
+
end
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
it 'should succeed with CORS simple headers' do
|
464
|
+
preflight_request('http://localhost:3000', '/', :headers => 'Accept')
|
465
|
+
last_response.must_render_cors_success
|
466
|
+
end
|
467
|
+
end
|
468
|
+
|
469
|
+
describe 'with custom allowed headers' do
|
470
|
+
let(:app) do
|
471
|
+
Rack::Builder.new do
|
472
|
+
use Rack::Cors do
|
473
|
+
allow do
|
474
|
+
origins '*'
|
475
|
+
resource '/', headers: []
|
476
|
+
end
|
477
|
+
end
|
478
|
+
map('/') do
|
479
|
+
run ->(env) { [200, {'Content-Type' => 'text/html'}, ['hello']] }
|
480
|
+
end
|
481
|
+
end
|
482
|
+
end
|
483
|
+
|
484
|
+
it 'should succeed with CORS simple headers' do
|
485
|
+
preflight_request('http://localhost:3000', '/', :headers => 'Accept')
|
486
|
+
last_response.must_render_cors_success
|
487
|
+
preflight_request('http://localhost:3000', '/', :headers => 'Accept-Language')
|
488
|
+
last_response.must_render_cors_success
|
489
|
+
preflight_request('http://localhost:3000', '/', :headers => 'Content-Type')
|
490
|
+
last_response.must_render_cors_success
|
491
|
+
preflight_request('http://localhost:3000', '/', :headers => 'Content-Language')
|
492
|
+
last_response.must_render_cors_success
|
324
493
|
end
|
325
494
|
end
|
326
495
|
|
@@ -333,7 +502,11 @@ describe Rack::Cors do
|
|
333
502
|
|
334
503
|
header 'Origin', opts[:origin]
|
335
504
|
current_session.__send__ opts[:method], path, {}, test: self
|
336
|
-
|
505
|
+
end
|
506
|
+
|
507
|
+
def successful_cors_request(*args)
|
508
|
+
cors_request(*args)
|
509
|
+
last_response.must_render_cors_success
|
337
510
|
end
|
338
511
|
|
339
512
|
def preflight_request(origin, path, opts = {})
|
@@ -346,12 +519,4 @@ describe Rack::Cors do
|
|
346
519
|
end
|
347
520
|
options path
|
348
521
|
end
|
349
|
-
|
350
|
-
def should_render_cors_success
|
351
|
-
last_response.headers['Access-Control-Allow-Origin'].wont_be_nil
|
352
|
-
end
|
353
|
-
|
354
|
-
def should_render_cors_failure
|
355
|
-
last_response.headers['Access-Control-Allow-Origin'].must_be_nil
|
356
|
-
end
|
357
522
|
end
|
data/test/unit/dsl_test.rb
CHANGED
@@ -55,4 +55,15 @@ describe Rack::Cors, 'DSL' do
|
|
55
55
|
|
56
56
|
resources.first.allow_origin?('file://').must_equal true
|
57
57
|
end
|
58
|
+
|
59
|
+
it 'should default credentials option to false' do
|
60
|
+
cors = Rack::Cors.new(Proc.new {}) do
|
61
|
+
allow do
|
62
|
+
origins 'example.net'
|
63
|
+
resource '/', :headers => :any
|
64
|
+
end
|
65
|
+
end
|
66
|
+
resources = cors.send :all_resources
|
67
|
+
resources.first.resources.first.credentials.must_equal false
|
68
|
+
end
|
58
69
|
end
|
data/test/unit/test.ru
CHANGED
@@ -19,6 +19,7 @@ use Rack::Cors do
|
|
19
19
|
resource '/expose_multiple_headers', :expose => %w{expose-test-1 expose-test-2}
|
20
20
|
resource '/conditional', :methods => :get, :if => proc { |env| !!env['HTTP_X_OK'] }
|
21
21
|
resource '/vary_test', :methods => :get, :vary => %w{ Origin Host }
|
22
|
+
resource '/patch_test', :methods => :patch
|
22
23
|
# resource '/file/at/*',
|
23
24
|
# :methods => [:get, :post, :put, :delete],
|
24
25
|
# :headers => :any,
|
@@ -32,9 +33,15 @@ use Rack::Cors do
|
|
32
33
|
resource '/proc-origin'
|
33
34
|
end
|
34
35
|
|
36
|
+
allow do
|
37
|
+
origins -> (source, env) { source.end_with?("10.10.10.10:3000") }
|
38
|
+
resource '/lambda-origin'
|
39
|
+
end
|
40
|
+
|
35
41
|
allow do
|
36
42
|
origins '*'
|
37
43
|
resource '/public'
|
44
|
+
resource '/public/*'
|
38
45
|
resource '/public_without_credentials', :credentials => false
|
39
46
|
end
|
40
47
|
|
@@ -47,4 +54,9 @@ use Rack::Cors do
|
|
47
54
|
origins '*'
|
48
55
|
resource '/multi-allow-config', :max_age => 300, :credentials => false
|
49
56
|
end
|
57
|
+
|
58
|
+
allow do
|
59
|
+
origins ''
|
60
|
+
resource '/blank-origin'
|
61
|
+
end
|
50
62
|
end
|