rack-cors 1.1.1 → 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 +11 -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 +101 -354
- 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 +164 -158
- 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 -21
- metadata +50 -15
- 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,20 +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
|
|
80
81
|
if env[REQUEST_METHOD] == OPTIONS && env[HTTP_ACCESS_CONTROL_REQUEST_METHOD]
|
81
82
|
return [400, {}, []] unless Rack::Utils.valid_path?(path)
|
83
|
+
|
82
84
|
headers = process_preflight(env, path)
|
83
85
|
debug(env) do
|
84
86
|
"Preflight Headers:\n" +
|
85
|
-
|
87
|
+
headers.collect { |kv| " #{kv.join(': ')}" }.join("\n")
|
86
88
|
end
|
87
89
|
return [200, headers, []]
|
88
90
|
else
|
@@ -103,9 +105,7 @@ module Rack
|
|
103
105
|
headers = add_headers.merge(headers)
|
104
106
|
debug(env) do
|
105
107
|
add_headers.each_pair do |key, value|
|
106
|
-
if headers.
|
107
|
-
headers["X-Rack-CORS-Original-#{key}"] = value
|
108
|
-
end
|
108
|
+
headers["x-rack-cors-original-#{key}"] = value if headers.key?(key)
|
109
109
|
end
|
110
110
|
end
|
111
111
|
end
|
@@ -114,359 +114,106 @@ module Rack
|
|
114
114
|
# response to be different depending on the Origin header value.
|
115
115
|
# Better explained here: http://www.fastly.com/blog/best-practices-for-using-the-vary-header/
|
116
116
|
if vary_resource
|
117
|
-
vary = headers[
|
118
|
-
cors_vary_headers = if vary_resource.vary_headers
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
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(', ')
|
124
124
|
end
|
125
125
|
|
126
|
-
|
127
|
-
|
128
|
-
end
|
126
|
+
result = env[ENV_KEY]
|
127
|
+
result.append_header(headers) if debug? && result
|
129
128
|
|
130
129
|
[status, headers, body]
|
131
130
|
end
|
132
131
|
|
133
132
|
protected
|
134
|
-
def debug(env, message = nil, &block)
|
135
|
-
(@logger || select_logger(env)).debug(message, &block) if debug?
|
136
|
-
end
|
137
133
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
@logger_proc = nil
|
142
|
-
logger_proc.call
|
134
|
+
def debug(env, message = nil, &block)
|
135
|
+
(@logger || select_logger(env)).debug(message, &block) if debug?
|
136
|
+
end
|
143
137
|
|
144
|
-
|
145
|
-
|
138
|
+
def select_logger(env)
|
139
|
+
@logger = if @logger_proc
|
140
|
+
logger_proc = @logger_proc
|
141
|
+
@logger_proc = nil
|
142
|
+
logger_proc.call
|
146
143
|
|
147
|
-
|
148
|
-
|
144
|
+
elsif defined?(Rails) && Rails.respond_to?(:logger) && Rails.logger
|
145
|
+
Rails.logger
|
149
146
|
|
150
|
-
|
151
|
-
|
152
|
-
end
|
153
|
-
end
|
147
|
+
elsif env[RACK_LOGGER]
|
148
|
+
env[RACK_LOGGER]
|
154
149
|
|
155
|
-
|
156
|
-
|
150
|
+
else
|
151
|
+
::Logger.new(STDOUT).tap { |logger| logger.level = ::Logger::Severity::DEBUG }
|
152
|
+
end
|
153
|
+
end
|
157
154
|
|
158
|
-
|
159
|
-
|
155
|
+
def evaluate_path(env)
|
156
|
+
path = env[PATH_INFO]
|
160
157
|
|
161
|
-
|
162
|
-
|
163
|
-
end
|
164
|
-
end
|
158
|
+
if path
|
159
|
+
path = Rack::Utils.unescape_path(path)
|
165
160
|
|
166
|
-
path
|
161
|
+
path = Rack::Utils.clean_path_info(path) if Rack::Utils.valid_path?(path)
|
167
162
|
end
|
168
163
|
|
169
|
-
|
170
|
-
|
171
|
-
end
|
164
|
+
path
|
165
|
+
end
|
172
166
|
|
173
|
-
|
174
|
-
|
167
|
+
def all_resources
|
168
|
+
@all_resources ||= []
|
169
|
+
end
|
175
170
|
|
176
|
-
|
177
|
-
|
178
|
-
result.miss(error)
|
179
|
-
return {}
|
180
|
-
end
|
171
|
+
def process_preflight(env, path)
|
172
|
+
result = Result.preflight(env)
|
181
173
|
|
182
|
-
|
174
|
+
resource, error = match_resource(path, env)
|
175
|
+
unless resource
|
176
|
+
result.miss(error)
|
177
|
+
return {}
|
183
178
|
end
|
184
179
|
|
185
|
-
|
186
|
-
|
187
|
-
if resource
|
188
|
-
Result.hit(env)
|
189
|
-
cors = resource.to_headers(env)
|
190
|
-
cors
|
180
|
+
resource.process_preflight(env, result)
|
181
|
+
end
|
191
182
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
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
|
197
189
|
|
198
|
-
|
199
|
-
|
200
|
-
if found = r.resource_for_path(path_info)
|
201
|
-
return found
|
202
|
-
end
|
203
|
-
end
|
190
|
+
else
|
191
|
+
Result.miss(env, error)
|
204
192
|
nil
|
205
193
|
end
|
194
|
+
end
|
206
195
|
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
all_resources.each do |r|
|
212
|
-
if r.allow_origin?(origin, env)
|
213
|
-
origin_matched = true
|
214
|
-
if found = r.match_resource(path, env)
|
215
|
-
return [found, nil]
|
216
|
-
end
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
[nil, origin_matched ? Result::MISS_NO_PATH : Result::MISS_NO_ORIGIN]
|
221
|
-
end
|
222
|
-
|
223
|
-
class Result
|
224
|
-
HEADER_KEY = 'X-Rack-CORS'.freeze
|
225
|
-
|
226
|
-
MISS_NO_ORIGIN = 'no-origin'.freeze
|
227
|
-
MISS_NO_PATH = 'no-path'.freeze
|
228
|
-
|
229
|
-
MISS_NO_METHOD = 'no-method'.freeze
|
230
|
-
MISS_DENY_METHOD = 'deny-method'.freeze
|
231
|
-
MISS_DENY_HEADER = 'deny-header'.freeze
|
232
|
-
|
233
|
-
attr_accessor :preflight, :hit, :miss_reason
|
234
|
-
|
235
|
-
def hit?
|
236
|
-
!!hit
|
237
|
-
end
|
238
|
-
|
239
|
-
def preflight?
|
240
|
-
!!preflight
|
241
|
-
end
|
242
|
-
|
243
|
-
def miss(reason)
|
244
|
-
self.hit = false
|
245
|
-
self.miss_reason = reason
|
246
|
-
end
|
247
|
-
|
248
|
-
def self.hit(env)
|
249
|
-
r = Result.new
|
250
|
-
r.preflight = false
|
251
|
-
r.hit = true
|
252
|
-
env[RACK_CORS] = r
|
253
|
-
end
|
254
|
-
|
255
|
-
def self.miss(env, reason)
|
256
|
-
r = Result.new
|
257
|
-
r.preflight = false
|
258
|
-
r.hit = false
|
259
|
-
r.miss_reason = reason
|
260
|
-
env[RACK_CORS] = r
|
261
|
-
end
|
262
|
-
|
263
|
-
def self.preflight(env)
|
264
|
-
r = Result.new
|
265
|
-
r.preflight = true
|
266
|
-
env[RACK_CORS] = r
|
267
|
-
end
|
268
|
-
|
269
|
-
|
270
|
-
def append_header(headers)
|
271
|
-
headers[HEADER_KEY] = if hit?
|
272
|
-
preflight? ? 'preflight-hit' : 'hit'
|
273
|
-
else
|
274
|
-
[
|
275
|
-
(preflight? ? 'preflight-miss' : 'miss'),
|
276
|
-
miss_reason
|
277
|
-
].join('; ')
|
278
|
-
end
|
279
|
-
end
|
280
|
-
end
|
281
|
-
|
282
|
-
class Resources
|
283
|
-
|
284
|
-
attr_reader :resources
|
285
|
-
|
286
|
-
def initialize
|
287
|
-
@origins = []
|
288
|
-
@resources = []
|
289
|
-
@public_resources = false
|
290
|
-
end
|
291
|
-
|
292
|
-
def origins(*args, &blk)
|
293
|
-
@origins = args.flatten.reject{ |s| s == '' }.map do |n|
|
294
|
-
case n
|
295
|
-
when Proc,
|
296
|
-
Regexp,
|
297
|
-
/^https?:\/\//,
|
298
|
-
'file://' then n
|
299
|
-
when '*' then @public_resources = true; n
|
300
|
-
else Regexp.compile("^[a-z][a-z0-9.+-]*:\\\/\\\/#{Regexp.quote(n)}$")
|
301
|
-
end
|
302
|
-
end.flatten
|
303
|
-
@origins.push(blk) if blk
|
304
|
-
end
|
305
|
-
|
306
|
-
def resource(path, opts={})
|
307
|
-
@resources << Resource.new(public_resources?, path, opts)
|
308
|
-
end
|
309
|
-
|
310
|
-
def public_resources?
|
311
|
-
@public_resources
|
312
|
-
end
|
313
|
-
|
314
|
-
def allow_origin?(source,env = {})
|
315
|
-
return true if public_resources?
|
316
|
-
|
317
|
-
return !! @origins.detect do |origin|
|
318
|
-
if origin.is_a?(Proc)
|
319
|
-
origin.call(source,env)
|
320
|
-
else
|
321
|
-
origin === source
|
322
|
-
end
|
323
|
-
end
|
324
|
-
end
|
325
|
-
|
326
|
-
def match_resource(path, env)
|
327
|
-
@resources.detect { |r| r.match?(path, env) }
|
328
|
-
end
|
329
|
-
|
330
|
-
def resource_for_path(path)
|
331
|
-
@resources.detect { |r| r.matches_path?(path) }
|
332
|
-
end
|
333
|
-
|
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
|
334
200
|
end
|
201
|
+
nil
|
202
|
+
end
|
335
203
|
|
336
|
-
|
337
|
-
|
338
|
-
def message
|
339
|
-
"Allowing credentials for wildcard origins is insecure."\
|
340
|
-
" Please specify more restrictive origins or set 'credentials' to false in your CORS configuration."
|
341
|
-
end
|
342
|
-
end
|
343
|
-
|
344
|
-
attr_accessor :path, :methods, :headers, :expose, :max_age, :credentials, :pattern, :if_proc, :vary_headers
|
345
|
-
|
346
|
-
def initialize(public_resource, path, opts={})
|
347
|
-
raise CorsMisconfigurationError if public_resource && opts[:credentials] == true
|
348
|
-
|
349
|
-
self.path = path
|
350
|
-
self.credentials = public_resource ? false : (opts[:credentials] == true)
|
351
|
-
self.max_age = opts[:max_age] || 7200
|
352
|
-
self.pattern = compile(path)
|
353
|
-
self.if_proc = opts[:if]
|
354
|
-
self.vary_headers = opts[:vary] && [opts[:vary]].flatten
|
355
|
-
@public_resource = public_resource
|
356
|
-
|
357
|
-
self.headers = case opts[:headers]
|
358
|
-
when :any then :any
|
359
|
-
when nil then nil
|
360
|
-
else
|
361
|
-
[opts[:headers]].flatten.collect{|h| h.downcase}
|
362
|
-
end
|
363
|
-
|
364
|
-
self.methods = case opts[:methods]
|
365
|
-
when :any then [:get, :head, :post, :put, :patch, :delete, :options]
|
366
|
-
else
|
367
|
-
ensure_enum(opts[:methods]) || [:get]
|
368
|
-
end.map{|e| e.to_s }
|
369
|
-
|
370
|
-
self.expose = opts[:expose] ? [opts[:expose]].flatten : nil
|
371
|
-
end
|
372
|
-
|
373
|
-
def matches_path?(path)
|
374
|
-
pattern =~ path
|
375
|
-
end
|
376
|
-
|
377
|
-
def match?(path, env)
|
378
|
-
matches_path?(path) && (if_proc.nil? || if_proc.call(env))
|
379
|
-
end
|
380
|
-
|
381
|
-
def process_preflight(env, result)
|
382
|
-
headers = {}
|
383
|
-
|
384
|
-
request_method = env[HTTP_ACCESS_CONTROL_REQUEST_METHOD]
|
385
|
-
if request_method.nil?
|
386
|
-
result.miss(Result::MISS_NO_METHOD) and return headers
|
387
|
-
end
|
388
|
-
if !methods.include?(request_method.downcase)
|
389
|
-
result.miss(Result::MISS_DENY_METHOD) and return headers
|
390
|
-
end
|
391
|
-
|
392
|
-
request_headers = env[HTTP_ACCESS_CONTROL_REQUEST_HEADERS]
|
393
|
-
if request_headers && !allow_headers?(request_headers)
|
394
|
-
result.miss(Result::MISS_DENY_HEADER) and return headers
|
395
|
-
end
|
396
|
-
|
397
|
-
result.hit = true
|
398
|
-
headers.merge(to_preflight_headers(env))
|
399
|
-
end
|
400
|
-
|
401
|
-
def to_headers(env)
|
402
|
-
h = {
|
403
|
-
'Access-Control-Allow-Origin' => origin_for_response_header(env[HTTP_ORIGIN]),
|
404
|
-
'Access-Control-Allow-Methods' => methods.collect{|m| m.to_s.upcase}.join(', '),
|
405
|
-
'Access-Control-Expose-Headers' => expose.nil? ? '' : expose.join(', '),
|
406
|
-
'Access-Control-Max-Age' => max_age.to_s }
|
407
|
-
h['Access-Control-Allow-Credentials'] = 'true' if credentials
|
408
|
-
h
|
409
|
-
end
|
410
|
-
|
411
|
-
protected
|
412
|
-
def public_resource?
|
413
|
-
@public_resource
|
414
|
-
end
|
415
|
-
|
416
|
-
def origin_for_response_header(origin)
|
417
|
-
return '*' if public_resource?
|
418
|
-
origin
|
419
|
-
end
|
420
|
-
|
421
|
-
def to_preflight_headers(env)
|
422
|
-
h = to_headers(env)
|
423
|
-
if env[HTTP_ACCESS_CONTROL_REQUEST_HEADERS]
|
424
|
-
h.merge!('Access-Control-Allow-Headers' => env[HTTP_ACCESS_CONTROL_REQUEST_HEADERS])
|
425
|
-
end
|
426
|
-
h
|
427
|
-
end
|
428
|
-
|
429
|
-
def allow_headers?(request_headers)
|
430
|
-
headers = self.headers || []
|
431
|
-
if headers == :any
|
432
|
-
return true
|
433
|
-
end
|
434
|
-
request_headers = request_headers.split(/,\s*/) if request_headers.kind_of?(String)
|
435
|
-
request_headers.all? do |header|
|
436
|
-
header = header.downcase
|
437
|
-
CORS_SIMPLE_HEADERS.include?(header) || headers.include?(header)
|
438
|
-
end
|
439
|
-
end
|
204
|
+
def match_resource(path, env)
|
205
|
+
origin = env[HTTP_ORIGIN]
|
440
206
|
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
end
|
207
|
+
origin_matched = false
|
208
|
+
all_resources.each do |r|
|
209
|
+
next unless r.allow_origin?(origin, env)
|
445
210
|
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
pattern =
|
450
|
-
path.to_str.gsub(/((:\w+)|\/\*|[\*#{special_chars.join}])/) do |match|
|
451
|
-
case match
|
452
|
-
when "/*"
|
453
|
-
"\\/?(.*?)"
|
454
|
-
when "*"
|
455
|
-
"(.*?)"
|
456
|
-
when *special_chars
|
457
|
-
Regexp.escape(match)
|
458
|
-
else
|
459
|
-
"([^/?&#]+)"
|
460
|
-
end
|
461
|
-
end
|
462
|
-
/^#{pattern}$/
|
463
|
-
elsif path.respond_to? :match
|
464
|
-
path
|
465
|
-
else
|
466
|
-
raise TypeError, path
|
467
|
-
end
|
468
|
-
end
|
211
|
+
origin_matched = true
|
212
|
+
found = r.match_resource(path, env)
|
213
|
+
return [found, nil] if found
|
469
214
|
end
|
470
215
|
|
216
|
+
[nil, origin_matched ? Result::MISS_NO_PATH : Result::MISS_NO_ORIGIN]
|
217
|
+
end
|
471
218
|
end
|
472
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
|
});
|