rack-cors 1.0.5 → 2.0.1
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.
Potentially problematic release.
This version of rack-cors might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yaml +39 -0
- data/.rubocop.yml +31 -0
- data/CHANGELOG.md +26 -0
- data/Gemfile +2 -0
- data/README.md +56 -35
- data/Rakefile +5 -4
- data/lib/rack/cors/resource.rb +142 -0
- data/lib/rack/cors/resources/cors_misconfiguration_error.rb +14 -0
- data/lib/rack/cors/resources.rb +62 -0
- data/lib/rack/cors/result.rb +63 -0
- data/lib/rack/cors/version.rb +3 -1
- data/lib/rack/cors.rb +105 -346
- data/rack-cors.gemspec +20 -17
- data/test/.rubocop.yml +8 -0
- data/test/cors/test.cors.coffee +4 -2
- data/test/cors/test.cors.js +6 -2
- data/test/unit/cors_test.rb +174 -156
- data/test/unit/dsl_test.rb +30 -29
- data/test/unit/insecure.ru +2 -0
- data/test/unit/non_http.ru +2 -0
- data/test/unit/test.ru +24 -20
- metadata +52 -17
- data/.travis.yml +0 -8
data/lib/rack/cors.rb
CHANGED
@@ -1,36 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'logger'
|
4
|
+
require_relative 'cors/resources'
|
5
|
+
require_relative 'cors/resource'
|
6
|
+
require_relative 'cors/result'
|
7
|
+
require_relative 'cors/version'
|
2
8
|
|
3
9
|
module Rack
|
4
10
|
class Cors
|
5
|
-
HTTP_ORIGIN = 'HTTP_ORIGIN'
|
6
|
-
HTTP_X_ORIGIN = 'HTTP_X_ORIGIN'
|
11
|
+
HTTP_ORIGIN = 'HTTP_ORIGIN'
|
12
|
+
HTTP_X_ORIGIN = 'HTTP_X_ORIGIN'
|
7
13
|
|
8
|
-
HTTP_ACCESS_CONTROL_REQUEST_METHOD = 'HTTP_ACCESS_CONTROL_REQUEST_METHOD'
|
9
|
-
HTTP_ACCESS_CONTROL_REQUEST_HEADERS = 'HTTP_ACCESS_CONTROL_REQUEST_HEADERS'
|
14
|
+
HTTP_ACCESS_CONTROL_REQUEST_METHOD = 'HTTP_ACCESS_CONTROL_REQUEST_METHOD'
|
15
|
+
HTTP_ACCESS_CONTROL_REQUEST_HEADERS = 'HTTP_ACCESS_CONTROL_REQUEST_HEADERS'
|
10
16
|
|
11
|
-
PATH_INFO = 'PATH_INFO'
|
12
|
-
REQUEST_METHOD = 'REQUEST_METHOD'
|
17
|
+
PATH_INFO = 'PATH_INFO'
|
18
|
+
REQUEST_METHOD = 'REQUEST_METHOD'
|
13
19
|
|
14
|
-
RACK_LOGGER = 'rack.logger'
|
20
|
+
RACK_LOGGER = 'rack.logger'
|
15
21
|
RACK_CORS =
|
16
|
-
|
17
|
-
|
22
|
+
# retaining the old key for backwards compatibility
|
23
|
+
ENV_KEY = 'rack.cors'
|
18
24
|
|
19
|
-
OPTIONS = 'OPTIONS'
|
20
|
-
VARY = 'Vary'.freeze
|
25
|
+
OPTIONS = 'OPTIONS'
|
21
26
|
|
22
27
|
DEFAULT_VARY_HEADERS = ['Origin'].freeze
|
23
28
|
|
24
|
-
|
25
|
-
# {https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers}
|
26
|
-
CORS_SIMPLE_HEADERS = ['accept', 'accept-language', 'content-language', 'content-type'].freeze
|
27
|
-
|
28
|
-
def initialize(app, opts={}, &block)
|
29
|
+
def initialize(app, opts = {}, &block)
|
29
30
|
@app = app
|
30
31
|
@debug_mode = !!opts[:debug]
|
31
32
|
@logger = @logger_proc = nil
|
32
33
|
|
33
|
-
|
34
|
+
logger = opts[:logger]
|
35
|
+
if logger
|
34
36
|
if logger.respond_to? :call
|
35
37
|
@logger_proc = opts[:logger]
|
36
38
|
else
|
@@ -38,12 +40,12 @@ module Rack
|
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
43
|
+
return unless block_given?
|
44
|
+
|
45
|
+
if block.arity == 1
|
46
|
+
block.call(self)
|
47
|
+
else
|
48
|
+
instance_eval(&block)
|
47
49
|
end
|
48
50
|
end
|
49
51
|
|
@@ -69,18 +71,20 @@ module Rack
|
|
69
71
|
add_headers = nil
|
70
72
|
if env[HTTP_ORIGIN]
|
71
73
|
debug(env) do
|
72
|
-
[
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
].join("\n")
|
74
|
+
['Incoming Headers:',
|
75
|
+
" Origin: #{env[HTTP_ORIGIN]}",
|
76
|
+
" Path-Info: #{path}",
|
77
|
+
" Access-Control-Request-Method: #{env[HTTP_ACCESS_CONTROL_REQUEST_METHOD]}",
|
78
|
+
" Access-Control-Request-Headers: #{env[HTTP_ACCESS_CONTROL_REQUEST_HEADERS]}"].join("\n")
|
78
79
|
end
|
79
|
-
|
80
|
+
|
81
|
+
if env[REQUEST_METHOD] == OPTIONS && env[HTTP_ACCESS_CONTROL_REQUEST_METHOD]
|
82
|
+
return [400, {}, []] unless Rack::Utils.valid_path?(path)
|
83
|
+
|
80
84
|
headers = process_preflight(env, path)
|
81
85
|
debug(env) do
|
82
86
|
"Preflight Headers:\n" +
|
83
|
-
|
87
|
+
headers.collect { |kv| " #{kv.join(': ')}" }.join("\n")
|
84
88
|
end
|
85
89
|
return [200, headers, []]
|
86
90
|
else
|
@@ -101,9 +105,7 @@ module Rack
|
|
101
105
|
headers = add_headers.merge(headers)
|
102
106
|
debug(env) do
|
103
107
|
add_headers.each_pair do |key, value|
|
104
|
-
if headers.
|
105
|
-
headers["X-Rack-CORS-Original-#{key}"] = value
|
106
|
-
end
|
108
|
+
headers["x-rack-cors-original-#{key}"] = value if headers.key?(key)
|
107
109
|
end
|
108
110
|
end
|
109
111
|
end
|
@@ -112,349 +114,106 @@ module Rack
|
|
112
114
|
# response to be different depending on the Origin header value.
|
113
115
|
# Better explained here: http://www.fastly.com/blog/best-practices-for-using-the-vary-header/
|
114
116
|
if vary_resource
|
115
|
-
vary = headers[
|
116
|
-
cors_vary_headers = if vary_resource.vary_headers
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
headers[
|
117
|
+
vary = headers['vary']
|
118
|
+
cors_vary_headers = if vary_resource.vary_headers&.any?
|
119
|
+
vary_resource.vary_headers
|
120
|
+
else
|
121
|
+
DEFAULT_VARY_HEADERS
|
122
|
+
end
|
123
|
+
headers['vary'] = ((vary ? [vary].flatten.map { |v| v.split(/,\s*/) }.flatten : []) + cors_vary_headers).uniq.join(', ')
|
122
124
|
end
|
123
125
|
|
124
|
-
|
125
|
-
|
126
|
-
end
|
126
|
+
result = env[ENV_KEY]
|
127
|
+
result.append_header(headers) if debug? && result
|
127
128
|
|
128
129
|
[status, headers, body]
|
129
130
|
end
|
130
131
|
|
131
132
|
protected
|
132
|
-
def debug(env, message = nil, &block)
|
133
|
-
(@logger || select_logger(env)).debug(message, &block) if debug?
|
134
|
-
end
|
135
|
-
|
136
|
-
def select_logger(env)
|
137
|
-
@logger = if @logger_proc
|
138
|
-
logger_proc = @logger_proc
|
139
|
-
@logger_proc = nil
|
140
|
-
logger_proc.call
|
141
133
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
elsif env[RACK_LOGGER]
|
146
|
-
env[RACK_LOGGER]
|
147
|
-
|
148
|
-
else
|
149
|
-
::Logger.new(STDOUT).tap { |logger| logger.level = ::Logger::Severity::DEBUG }
|
150
|
-
end
|
151
|
-
end
|
134
|
+
def debug(env, message = nil, &block)
|
135
|
+
(@logger || select_logger(env)).debug(message, &block) if debug?
|
136
|
+
end
|
152
137
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
138
|
+
def select_logger(env)
|
139
|
+
@logger = if @logger_proc
|
140
|
+
logger_proc = @logger_proc
|
141
|
+
@logger_proc = nil
|
142
|
+
logger_proc.call
|
158
143
|
|
159
|
-
|
160
|
-
|
161
|
-
end
|
144
|
+
elsif defined?(Rails) && Rails.respond_to?(:logger) && Rails.logger
|
145
|
+
Rails.logger
|
162
146
|
|
163
|
-
|
164
|
-
|
147
|
+
elsif env[RACK_LOGGER]
|
148
|
+
env[RACK_LOGGER]
|
165
149
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
end
|
150
|
+
else
|
151
|
+
::Logger.new(STDOUT).tap { |logger| logger.level = ::Logger::Severity::DEBUG }
|
152
|
+
end
|
153
|
+
end
|
171
154
|
|
172
|
-
|
173
|
-
|
155
|
+
def evaluate_path(env)
|
156
|
+
path = env[PATH_INFO]
|
174
157
|
|
175
|
-
|
176
|
-
|
177
|
-
if resource
|
178
|
-
Result.hit(env)
|
179
|
-
cors = resource.to_headers(env)
|
180
|
-
cors
|
158
|
+
if path
|
159
|
+
path = Rack::Utils.unescape_path(path)
|
181
160
|
|
182
|
-
|
183
|
-
Result.miss(env, error)
|
184
|
-
nil
|
185
|
-
end
|
161
|
+
path = Rack::Utils.clean_path_info(path) if Rack::Utils.valid_path?(path)
|
186
162
|
end
|
187
163
|
|
188
|
-
|
189
|
-
|
190
|
-
if found = r.resource_for_path(path_info)
|
191
|
-
return found
|
192
|
-
end
|
193
|
-
end
|
194
|
-
nil
|
195
|
-
end
|
164
|
+
path
|
165
|
+
end
|
196
166
|
|
197
|
-
|
198
|
-
|
167
|
+
def all_resources
|
168
|
+
@all_resources ||= []
|
169
|
+
end
|
199
170
|
|
200
|
-
|
201
|
-
|
202
|
-
if r.allow_origin?(origin, env)
|
203
|
-
origin_matched = true
|
204
|
-
if found = r.match_resource(path, env)
|
205
|
-
return [found, nil]
|
206
|
-
end
|
207
|
-
end
|
208
|
-
end
|
171
|
+
def process_preflight(env, path)
|
172
|
+
result = Result.preflight(env)
|
209
173
|
|
210
|
-
|
174
|
+
resource, error = match_resource(path, env)
|
175
|
+
unless resource
|
176
|
+
result.miss(error)
|
177
|
+
return {}
|
211
178
|
end
|
212
179
|
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
MISS_NO_ORIGIN = 'no-origin'.freeze
|
217
|
-
MISS_NO_PATH = 'no-path'.freeze
|
218
|
-
|
219
|
-
MISS_NO_METHOD = 'no-method'.freeze
|
220
|
-
MISS_DENY_METHOD = 'deny-method'.freeze
|
221
|
-
MISS_DENY_HEADER = 'deny-header'.freeze
|
222
|
-
|
223
|
-
attr_accessor :preflight, :hit, :miss_reason
|
224
|
-
|
225
|
-
def hit?
|
226
|
-
!!hit
|
227
|
-
end
|
228
|
-
|
229
|
-
def preflight?
|
230
|
-
!!preflight
|
231
|
-
end
|
232
|
-
|
233
|
-
def miss(reason)
|
234
|
-
self.hit = false
|
235
|
-
self.miss_reason = reason
|
236
|
-
end
|
237
|
-
|
238
|
-
def self.hit(env)
|
239
|
-
r = Result.new
|
240
|
-
r.preflight = false
|
241
|
-
r.hit = true
|
242
|
-
env[RACK_CORS] = r
|
243
|
-
end
|
244
|
-
|
245
|
-
def self.miss(env, reason)
|
246
|
-
r = Result.new
|
247
|
-
r.preflight = false
|
248
|
-
r.hit = false
|
249
|
-
r.miss_reason = reason
|
250
|
-
env[RACK_CORS] = r
|
251
|
-
end
|
252
|
-
|
253
|
-
def self.preflight(env)
|
254
|
-
r = Result.new
|
255
|
-
r.preflight = true
|
256
|
-
env[RACK_CORS] = r
|
257
|
-
end
|
180
|
+
resource.process_preflight(env, result)
|
181
|
+
end
|
258
182
|
|
183
|
+
def process_cors(env, path)
|
184
|
+
resource, error = match_resource(path, env)
|
185
|
+
if resource
|
186
|
+
Result.hit(env)
|
187
|
+
cors = resource.to_headers(env)
|
188
|
+
cors
|
259
189
|
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
else
|
264
|
-
[
|
265
|
-
(preflight? ? 'preflight-miss' : 'miss'),
|
266
|
-
miss_reason
|
267
|
-
].join('; ')
|
268
|
-
end
|
269
|
-
end
|
190
|
+
else
|
191
|
+
Result.miss(env, error)
|
192
|
+
nil
|
270
193
|
end
|
194
|
+
end
|
271
195
|
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
def initialize
|
277
|
-
@origins = []
|
278
|
-
@resources = []
|
279
|
-
@public_resources = false
|
280
|
-
end
|
281
|
-
|
282
|
-
def origins(*args, &blk)
|
283
|
-
@origins = args.flatten.reject{ |s| s == '' }.map do |n|
|
284
|
-
case n
|
285
|
-
when Proc,
|
286
|
-
Regexp,
|
287
|
-
/^https?:\/\//,
|
288
|
-
'file://' then n
|
289
|
-
when '*' then @public_resources = true; n
|
290
|
-
else Regexp.compile("^[a-z][a-z0-9.+-]*:\\\/\\\/#{Regexp.quote(n)}$")
|
291
|
-
end
|
292
|
-
end.flatten
|
293
|
-
@origins.push(blk) if blk
|
294
|
-
end
|
295
|
-
|
296
|
-
def resource(path, opts={})
|
297
|
-
@resources << Resource.new(public_resources?, path, opts)
|
298
|
-
end
|
299
|
-
|
300
|
-
def public_resources?
|
301
|
-
@public_resources
|
302
|
-
end
|
303
|
-
|
304
|
-
def allow_origin?(source,env = {})
|
305
|
-
return true if public_resources?
|
306
|
-
|
307
|
-
return !! @origins.detect do |origin|
|
308
|
-
if origin.is_a?(Proc)
|
309
|
-
origin.call(source,env)
|
310
|
-
else
|
311
|
-
origin === source
|
312
|
-
end
|
313
|
-
end
|
314
|
-
end
|
315
|
-
|
316
|
-
def match_resource(path, env)
|
317
|
-
@resources.detect { |r| r.match?(path, env) }
|
318
|
-
end
|
319
|
-
|
320
|
-
def resource_for_path(path)
|
321
|
-
@resources.detect { |r| r.matches_path?(path) }
|
322
|
-
end
|
323
|
-
|
196
|
+
def resource_for_path(path_info)
|
197
|
+
all_resources.each do |r|
|
198
|
+
found = r.resource_for_path(path_info)
|
199
|
+
return found if found
|
324
200
|
end
|
201
|
+
nil
|
202
|
+
end
|
325
203
|
|
326
|
-
|
327
|
-
|
328
|
-
def message
|
329
|
-
"Allowing credentials for wildcard origins is insecure."\
|
330
|
-
" Please specify more restrictive origins or set 'credentials' to false in your CORS configuration."
|
331
|
-
end
|
332
|
-
end
|
333
|
-
|
334
|
-
attr_accessor :path, :methods, :headers, :expose, :max_age, :credentials, :pattern, :if_proc, :vary_headers
|
335
|
-
|
336
|
-
def initialize(public_resource, path, opts={})
|
337
|
-
raise CorsMisconfigurationError if public_resource && opts[:credentials] == true
|
338
|
-
|
339
|
-
self.path = path
|
340
|
-
self.credentials = public_resource ? false : (opts[:credentials] == true)
|
341
|
-
self.max_age = opts[:max_age] || 7200
|
342
|
-
self.pattern = compile(path)
|
343
|
-
self.if_proc = opts[:if]
|
344
|
-
self.vary_headers = opts[:vary] && [opts[:vary]].flatten
|
345
|
-
@public_resource = public_resource
|
346
|
-
|
347
|
-
self.headers = case opts[:headers]
|
348
|
-
when :any then :any
|
349
|
-
when nil then nil
|
350
|
-
else
|
351
|
-
[opts[:headers]].flatten.collect{|h| h.downcase}
|
352
|
-
end
|
353
|
-
|
354
|
-
self.methods = case opts[:methods]
|
355
|
-
when :any then [:get, :head, :post, :put, :patch, :delete, :options]
|
356
|
-
else
|
357
|
-
ensure_enum(opts[:methods]) || [:get]
|
358
|
-
end.map{|e| e.to_s }
|
359
|
-
|
360
|
-
self.expose = opts[:expose] ? [opts[:expose]].flatten : nil
|
361
|
-
end
|
362
|
-
|
363
|
-
def matches_path?(path)
|
364
|
-
pattern =~ path
|
365
|
-
end
|
366
|
-
|
367
|
-
def match?(path, env)
|
368
|
-
matches_path?(path) && (if_proc.nil? || if_proc.call(env))
|
369
|
-
end
|
370
|
-
|
371
|
-
def process_preflight(env, result)
|
372
|
-
headers = {}
|
373
|
-
|
374
|
-
request_method = env[HTTP_ACCESS_CONTROL_REQUEST_METHOD]
|
375
|
-
if request_method.nil?
|
376
|
-
result.miss(Result::MISS_NO_METHOD) and return headers
|
377
|
-
end
|
378
|
-
if !methods.include?(request_method.downcase)
|
379
|
-
result.miss(Result::MISS_DENY_METHOD) and return headers
|
380
|
-
end
|
381
|
-
|
382
|
-
request_headers = env[HTTP_ACCESS_CONTROL_REQUEST_HEADERS]
|
383
|
-
if request_headers && !allow_headers?(request_headers)
|
384
|
-
result.miss(Result::MISS_DENY_HEADER) and return headers
|
385
|
-
end
|
386
|
-
|
387
|
-
result.hit = true
|
388
|
-
headers.merge(to_preflight_headers(env))
|
389
|
-
end
|
390
|
-
|
391
|
-
def to_headers(env)
|
392
|
-
h = {
|
393
|
-
'Access-Control-Allow-Origin' => origin_for_response_header(env[HTTP_ORIGIN]),
|
394
|
-
'Access-Control-Allow-Methods' => methods.collect{|m| m.to_s.upcase}.join(', '),
|
395
|
-
'Access-Control-Expose-Headers' => expose.nil? ? '' : expose.join(', '),
|
396
|
-
'Access-Control-Max-Age' => max_age.to_s }
|
397
|
-
h['Access-Control-Allow-Credentials'] = 'true' if credentials
|
398
|
-
h
|
399
|
-
end
|
400
|
-
|
401
|
-
protected
|
402
|
-
def public_resource?
|
403
|
-
@public_resource
|
404
|
-
end
|
405
|
-
|
406
|
-
def origin_for_response_header(origin)
|
407
|
-
return '*' if public_resource?
|
408
|
-
origin
|
409
|
-
end
|
410
|
-
|
411
|
-
def to_preflight_headers(env)
|
412
|
-
h = to_headers(env)
|
413
|
-
if env[HTTP_ACCESS_CONTROL_REQUEST_HEADERS]
|
414
|
-
h.merge!('Access-Control-Allow-Headers' => env[HTTP_ACCESS_CONTROL_REQUEST_HEADERS])
|
415
|
-
end
|
416
|
-
h
|
417
|
-
end
|
418
|
-
|
419
|
-
def allow_headers?(request_headers)
|
420
|
-
headers = self.headers || []
|
421
|
-
if headers == :any
|
422
|
-
return true
|
423
|
-
end
|
424
|
-
request_headers = request_headers.split(/,\s*/) if request_headers.kind_of?(String)
|
425
|
-
request_headers.all? do |header|
|
426
|
-
header = header.downcase
|
427
|
-
CORS_SIMPLE_HEADERS.include?(header) || headers.include?(header)
|
428
|
-
end
|
429
|
-
end
|
204
|
+
def match_resource(path, env)
|
205
|
+
origin = env[HTTP_ORIGIN]
|
430
206
|
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
end
|
207
|
+
origin_matched = false
|
208
|
+
all_resources.each do |r|
|
209
|
+
next unless r.allow_origin?(origin, env)
|
435
210
|
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
pattern =
|
440
|
-
path.to_str.gsub(/((:\w+)|[\*#{special_chars.join}])/) do |match|
|
441
|
-
case match
|
442
|
-
when "*"
|
443
|
-
"(.*?)"
|
444
|
-
when *special_chars
|
445
|
-
Regexp.escape(match)
|
446
|
-
else
|
447
|
-
"([^/?&#]+)"
|
448
|
-
end
|
449
|
-
end
|
450
|
-
/^#{pattern}$/
|
451
|
-
elsif path.respond_to? :match
|
452
|
-
path
|
453
|
-
else
|
454
|
-
raise TypeError, path
|
455
|
-
end
|
456
|
-
end
|
211
|
+
origin_matched = true
|
212
|
+
found = r.match_resource(path, env)
|
213
|
+
return [found, nil] if found
|
457
214
|
end
|
458
215
|
|
216
|
+
[nil, origin_matched ? Result::MISS_NO_PATH : Result::MISS_NO_ORIGIN]
|
217
|
+
end
|
459
218
|
end
|
460
219
|
end
|
data/rack-cors.gemspec
CHANGED
@@ -1,27 +1,30 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require 'rack/cors/version'
|
5
6
|
|
6
7
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
8
|
+
spec.name = 'rack-cors'
|
8
9
|
spec.version = Rack::Cors::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
11
|
-
spec.description =
|
12
|
-
spec.summary =
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
10
|
+
spec.authors = ['Calvin Yu']
|
11
|
+
spec.email = ['me@sourcebender.com']
|
12
|
+
spec.description = 'Middleware that will make Rack-based apps CORS compatible. Fork the project here: https://github.com/cyu/rack-cors'
|
13
|
+
spec.summary = 'Middleware for enabling Cross-Origin Resource Sharing in Rack apps'
|
14
|
+
spec.homepage = 'https://github.com/cyu/rack-cors'
|
15
|
+
spec.license = 'MIT'
|
15
16
|
|
16
|
-
spec.files = `git ls-files`.split(
|
17
|
+
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR).reject { |f| (f == '.gitignore') || f =~ /^examples/ }
|
17
18
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
19
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
-
spec.require_paths = [
|
20
|
+
spec.require_paths = ['lib']
|
20
21
|
|
21
|
-
spec.add_dependency
|
22
|
-
spec.add_development_dependency
|
23
|
-
spec.add_development_dependency
|
24
|
-
spec.add_development_dependency
|
25
|
-
spec.add_development_dependency
|
26
|
-
spec.add_development_dependency
|
22
|
+
spec.add_dependency 'rack', '>= 2.0.0'
|
23
|
+
spec.add_development_dependency 'bundler', '>= 1.16.0', '< 3'
|
24
|
+
spec.add_development_dependency 'minitest', '~> 5.11.0'
|
25
|
+
spec.add_development_dependency 'mocha', '~> 1.6.0'
|
26
|
+
spec.add_development_dependency 'pry', '~> 0.12'
|
27
|
+
spec.add_development_dependency 'rack-test', '>= 1.1.0'
|
28
|
+
spec.add_development_dependency 'rake', '~> 12.3.0'
|
29
|
+
spec.add_development_dependency 'rubocop', '~> 0.80.1'
|
27
30
|
end
|
data/test/.rubocop.yml
ADDED
data/test/cors/test.cors.coffee
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
CORS_SERVER = '127.0.0.1.xip.io:
|
1
|
+
CORS_SERVER = '127.0.0.1.xip.io:3000'
|
2
|
+
|
3
|
+
mocha.setup({ignoreLeaks: true});
|
2
4
|
|
3
5
|
describe 'CORS', ->
|
4
6
|
|
@@ -34,7 +36,7 @@ describe 'CORS', ->
|
|
34
36
|
|
35
37
|
it 'should allow access to static resource', (done) ->
|
36
38
|
$.get "http://#{CORS_SERVER}/static.txt", (data, status, xhr) ->
|
37
|
-
expect($.trim(data)).to.eql("
|
39
|
+
expect($.trim(data)).to.eql("Hello world")
|
38
40
|
done()
|
39
41
|
|
40
42
|
it 'should allow post resource', (done) ->
|
data/test/cors/test.cors.js
CHANGED
@@ -2,7 +2,11 @@
|
|
2
2
|
(function() {
|
3
3
|
var CORS_SERVER;
|
4
4
|
|
5
|
-
CORS_SERVER = '127.0.0.1.xip.io:
|
5
|
+
CORS_SERVER = '127.0.0.1.xip.io:3000';
|
6
|
+
|
7
|
+
mocha.setup({
|
8
|
+
ignoreLeaks: true
|
9
|
+
});
|
6
10
|
|
7
11
|
describe('CORS', function() {
|
8
12
|
it('should allow access to dynamic resource', function(done) {
|
@@ -53,7 +57,7 @@
|
|
53
57
|
});
|
54
58
|
it('should allow access to static resource', function(done) {
|
55
59
|
return $.get(`http://${CORS_SERVER}/static.txt`, function(data, status, xhr) {
|
56
|
-
expect($.trim(data)).to.eql("
|
60
|
+
expect($.trim(data)).to.eql("Hello world");
|
57
61
|
return done();
|
58
62
|
});
|
59
63
|
});
|