rack-cors 0.4.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 +5 -5
- data/.github/workflows/ci.yaml +39 -0
- data/.rubocop.yml +31 -0
- data/CHANGELOG.md +99 -0
- data/Gemfile +3 -1
- data/README.md +68 -43
- 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 +124 -323
- data/rack-cors.gemspec +20 -16
- data/test/.rubocop.yml +8 -0
- data/test/cors/test.cors.coffee +9 -2
- data/test/cors/test.cors.js +22 -10
- data/test/unit/cors_test.rb +303 -120
- data/test/unit/dsl_test.rb +38 -26
- data/test/unit/insecure.ru +10 -0
- data/test/unit/non_http.ru +2 -0
- data/test/unit/test.ru +34 -18
- metadata +82 -27
- data/.travis.yml +0 -6
- data/CHANGELOG +0 -34
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rack
|
4
|
+
class Cors
|
5
|
+
class Result
|
6
|
+
HEADER_KEY = 'x-rack-cors'
|
7
|
+
|
8
|
+
MISS_NO_ORIGIN = 'no-origin'
|
9
|
+
MISS_NO_PATH = 'no-path'
|
10
|
+
|
11
|
+
MISS_NO_METHOD = 'no-method'
|
12
|
+
MISS_DENY_METHOD = 'deny-method'
|
13
|
+
MISS_DENY_HEADER = 'deny-header'
|
14
|
+
|
15
|
+
attr_accessor :preflight, :hit, :miss_reason
|
16
|
+
|
17
|
+
def hit?
|
18
|
+
!!hit
|
19
|
+
end
|
20
|
+
|
21
|
+
def preflight?
|
22
|
+
!!preflight
|
23
|
+
end
|
24
|
+
|
25
|
+
def miss(reason)
|
26
|
+
self.hit = false
|
27
|
+
self.miss_reason = reason
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.hit(env)
|
31
|
+
r = Result.new
|
32
|
+
r.preflight = false
|
33
|
+
r.hit = true
|
34
|
+
env[Rack::Cors::ENV_KEY] = r
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.miss(env, reason)
|
38
|
+
r = Result.new
|
39
|
+
r.preflight = false
|
40
|
+
r.hit = false
|
41
|
+
r.miss_reason = reason
|
42
|
+
env[Rack::Cors::ENV_KEY] = r
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.preflight(env)
|
46
|
+
r = Result.new
|
47
|
+
r.preflight = true
|
48
|
+
env[Rack::Cors::ENV_KEY] = r
|
49
|
+
end
|
50
|
+
|
51
|
+
def append_header(headers)
|
52
|
+
headers[HEADER_KEY] = if hit?
|
53
|
+
preflight? ? 'preflight-hit' : 'hit'
|
54
|
+
else
|
55
|
+
[
|
56
|
+
(preflight? ? 'preflight-miss' : 'miss'),
|
57
|
+
miss_reason
|
58
|
+
].join('; ')
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/rack/cors/version.rb
CHANGED
data/lib/rack/cors.rb
CHANGED
@@ -1,21 +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
|
-
|
11
|
+
HTTP_ORIGIN = 'HTTP_ORIGIN'
|
12
|
+
HTTP_X_ORIGIN = 'HTTP_X_ORIGIN'
|
13
|
+
|
14
|
+
HTTP_ACCESS_CONTROL_REQUEST_METHOD = 'HTTP_ACCESS_CONTROL_REQUEST_METHOD'
|
15
|
+
HTTP_ACCESS_CONTROL_REQUEST_HEADERS = 'HTTP_ACCESS_CONTROL_REQUEST_HEADERS'
|
16
|
+
|
17
|
+
PATH_INFO = 'PATH_INFO'
|
18
|
+
REQUEST_METHOD = 'REQUEST_METHOD'
|
19
|
+
|
20
|
+
RACK_LOGGER = 'rack.logger'
|
21
|
+
RACK_CORS =
|
22
|
+
# retaining the old key for backwards compatibility
|
23
|
+
ENV_KEY = 'rack.cors'
|
6
24
|
|
7
|
-
|
8
|
-
ORIGIN_X_HEADER_KEY = 'HTTP_X_ORIGIN'.freeze
|
9
|
-
PATH_INFO_HEADER_KEY = 'PATH_INFO'.freeze
|
10
|
-
VARY_HEADER_KEY = 'Vary'.freeze
|
11
|
-
DEFAULT_VARY_HEADERS = ['Origin'].freeze
|
25
|
+
OPTIONS = 'OPTIONS'
|
12
26
|
|
13
|
-
|
27
|
+
DEFAULT_VARY_HEADERS = ['Origin'].freeze
|
28
|
+
|
29
|
+
def initialize(app, opts = {}, &block)
|
14
30
|
@app = app
|
15
31
|
@debug_mode = !!opts[:debug]
|
16
32
|
@logger = @logger_proc = nil
|
17
33
|
|
18
|
-
|
34
|
+
logger = opts[:logger]
|
35
|
+
if logger
|
19
36
|
if logger.respond_to? :call
|
20
37
|
@logger_proc = opts[:logger]
|
21
38
|
else
|
@@ -23,12 +40,12 @@ module Rack
|
|
23
40
|
end
|
24
41
|
end
|
25
42
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
43
|
+
return unless block_given?
|
44
|
+
|
45
|
+
if block.arity == 1
|
46
|
+
block.call(self)
|
47
|
+
else
|
48
|
+
instance_eval(&block)
|
32
49
|
end
|
33
50
|
end
|
34
51
|
|
@@ -47,36 +64,40 @@ module Rack
|
|
47
64
|
end
|
48
65
|
|
49
66
|
def call(env)
|
50
|
-
env[
|
67
|
+
env[HTTP_ORIGIN] ||= env[HTTP_X_ORIGIN] if env[HTTP_X_ORIGIN]
|
68
|
+
|
69
|
+
path = evaluate_path(env)
|
51
70
|
|
52
71
|
add_headers = nil
|
53
|
-
if env[
|
72
|
+
if env[HTTP_ORIGIN]
|
54
73
|
debug(env) do
|
55
|
-
[
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
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")
|
60
79
|
end
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
80
|
+
|
81
|
+
if env[REQUEST_METHOD] == OPTIONS && env[HTTP_ACCESS_CONTROL_REQUEST_METHOD]
|
82
|
+
return [400, {}, []] unless Rack::Utils.valid_path?(path)
|
83
|
+
|
84
|
+
headers = process_preflight(env, path)
|
85
|
+
debug(env) do
|
86
|
+
"Preflight Headers:\n" +
|
87
|
+
headers.collect { |kv| " #{kv.join(': ')}" }.join("\n")
|
68
88
|
end
|
89
|
+
return [200, headers, []]
|
69
90
|
else
|
70
|
-
add_headers = process_cors(env)
|
91
|
+
add_headers = process_cors(env, path)
|
71
92
|
end
|
72
93
|
else
|
73
94
|
Result.miss(env, Result::MISS_NO_ORIGIN)
|
74
95
|
end
|
75
96
|
|
76
97
|
# This call must be done BEFORE calling the app because for some reason
|
77
|
-
# env[
|
78
|
-
#
|
79
|
-
vary_resource = resource_for_path(
|
98
|
+
# env[PATH_INFO] gets changed after that and it won't match. (At least
|
99
|
+
# in rails 4.1.6)
|
100
|
+
vary_resource = resource_for_path(path)
|
80
101
|
|
81
102
|
status, headers, body = @app.call env
|
82
103
|
|
@@ -84,9 +105,7 @@ module Rack
|
|
84
105
|
headers = add_headers.merge(headers)
|
85
106
|
debug(env) do
|
86
107
|
add_headers.each_pair do |key, value|
|
87
|
-
if headers.
|
88
|
-
headers["X-Rack-CORS-Original-#{key}"] = value
|
89
|
-
end
|
108
|
+
headers["x-rack-cors-original-#{key}"] = value if headers.key?(key)
|
90
109
|
end
|
91
110
|
end
|
92
111
|
end
|
@@ -95,324 +114,106 @@ module Rack
|
|
95
114
|
# response to be different depending on the Origin header value.
|
96
115
|
# Better explained here: http://www.fastly.com/blog/best-practices-for-using-the-vary-header/
|
97
116
|
if vary_resource
|
98
|
-
vary = headers[
|
99
|
-
cors_vary_headers = if vary_resource.vary_headers
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
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(', ')
|
105
124
|
end
|
106
125
|
|
107
|
-
|
108
|
-
|
109
|
-
end
|
126
|
+
result = env[ENV_KEY]
|
127
|
+
result.append_header(headers) if debug? && result
|
110
128
|
|
111
129
|
[status, headers, body]
|
112
130
|
end
|
113
131
|
|
114
132
|
protected
|
115
|
-
def debug(env, message = nil, &block)
|
116
|
-
(@logger || select_logger(env)).debug(message, &block) if debug?
|
117
|
-
end
|
118
|
-
|
119
|
-
def select_logger(env)
|
120
|
-
@logger = if @logger_proc
|
121
|
-
logger_proc = @logger_proc
|
122
|
-
@logger_proc = nil
|
123
|
-
logger_proc.call
|
124
|
-
|
125
|
-
elsif defined?(Rails) && Rails.logger
|
126
|
-
Rails.logger
|
127
|
-
|
128
|
-
elsif env['rack.logger']
|
129
|
-
env['rack.logger']
|
130
133
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
end
|
135
|
-
|
136
|
-
def all_resources
|
137
|
-
@all_resources ||= []
|
138
|
-
end
|
134
|
+
def debug(env, message = nil, &block)
|
135
|
+
(@logger || select_logger(env)).debug(message, &block) if debug?
|
136
|
+
end
|
139
137
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
preflight
|
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
|
-
|
149
|
-
nil
|
150
|
-
end
|
151
|
-
end
|
144
|
+
elsif defined?(Rails) && Rails.respond_to?(:logger) && Rails.logger
|
145
|
+
Rails.logger
|
152
146
|
|
153
|
-
|
154
|
-
|
155
|
-
if resource
|
156
|
-
Result.hit(env)
|
157
|
-
cors = resource.to_headers(env)
|
158
|
-
cors
|
147
|
+
elsif env[RACK_LOGGER]
|
148
|
+
env[RACK_LOGGER]
|
159
149
|
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
end
|
150
|
+
else
|
151
|
+
::Logger.new(STDOUT).tap { |logger| logger.level = ::Logger::Severity::DEBUG }
|
152
|
+
end
|
153
|
+
end
|
165
154
|
|
166
|
-
|
167
|
-
|
168
|
-
if found = r.resource_for_path(path_info)
|
169
|
-
return found
|
170
|
-
end
|
171
|
-
end
|
172
|
-
nil
|
173
|
-
end
|
155
|
+
def evaluate_path(env)
|
156
|
+
path = env[PATH_INFO]
|
174
157
|
|
175
|
-
|
176
|
-
path
|
177
|
-
origin = env[ORIGIN_HEADER_KEY]
|
178
|
-
|
179
|
-
origin_matched = false
|
180
|
-
all_resources.each do |r|
|
181
|
-
if r.allow_origin?(origin, env)
|
182
|
-
origin_matched = true
|
183
|
-
if found = r.match_resource(path, env)
|
184
|
-
return [found, nil]
|
185
|
-
end
|
186
|
-
end
|
187
|
-
end
|
158
|
+
if path
|
159
|
+
path = Rack::Utils.unescape_path(path)
|
188
160
|
|
189
|
-
|
161
|
+
path = Rack::Utils.clean_path_info(path) if Rack::Utils.valid_path?(path)
|
190
162
|
end
|
191
163
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
MISS_NO_ORIGIN = 'no-origin'.freeze
|
196
|
-
MISS_NO_PATH = 'no-path'.freeze
|
197
|
-
|
198
|
-
attr_accessor :preflight, :hit, :miss_reason
|
199
|
-
|
200
|
-
def hit?
|
201
|
-
!!hit
|
202
|
-
end
|
203
|
-
|
204
|
-
def preflight?
|
205
|
-
!!preflight
|
206
|
-
end
|
207
|
-
|
208
|
-
def self.hit(env)
|
209
|
-
r = Result.new
|
210
|
-
r.preflight = false
|
211
|
-
r.hit = true
|
212
|
-
env[ENV_KEY] = r
|
213
|
-
end
|
214
|
-
|
215
|
-
def self.miss(env, reason)
|
216
|
-
r = Result.new
|
217
|
-
r.preflight = false
|
218
|
-
r.hit = false
|
219
|
-
r.miss_reason = reason
|
220
|
-
env[ENV_KEY] = r
|
221
|
-
end
|
164
|
+
path
|
165
|
+
end
|
222
166
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
r.hit = true
|
227
|
-
env[ENV_KEY] = r
|
228
|
-
end
|
167
|
+
def all_resources
|
168
|
+
@all_resources ||= []
|
169
|
+
end
|
229
170
|
|
230
|
-
|
231
|
-
|
232
|
-
r.preflight = true
|
233
|
-
r.hit = false
|
234
|
-
r.miss_reason = reason
|
235
|
-
env[ENV_KEY] = r
|
236
|
-
end
|
171
|
+
def process_preflight(env, path)
|
172
|
+
result = Result.preflight(env)
|
237
173
|
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
[
|
243
|
-
(preflight? ? 'preflight-miss' : 'miss'),
|
244
|
-
miss_reason
|
245
|
-
].join('; ')
|
246
|
-
end
|
247
|
-
end
|
174
|
+
resource, error = match_resource(path, env)
|
175
|
+
unless resource
|
176
|
+
result.miss(error)
|
177
|
+
return {}
|
248
178
|
end
|
249
179
|
|
250
|
-
|
251
|
-
|
252
|
-
@origins = []
|
253
|
-
@resources = []
|
254
|
-
@public_resources = false
|
255
|
-
end
|
256
|
-
|
257
|
-
def origins(*args, &blk)
|
258
|
-
@origins = args.flatten.collect do |n|
|
259
|
-
case n
|
260
|
-
when Regexp,
|
261
|
-
/^https?:\/\//,
|
262
|
-
'file://' then n
|
263
|
-
when '*' then @public_resources = true; n
|
264
|
-
else Regexp.compile("^[a-z][a-z0-9.+-]*:\\\/\\\/#{Regexp.quote(n)}$")
|
265
|
-
end
|
266
|
-
end.flatten
|
267
|
-
@origins.push(blk) if blk
|
268
|
-
end
|
269
|
-
|
270
|
-
def resource(path, opts={})
|
271
|
-
@resources << Resource.new(public_resources?, path, opts)
|
272
|
-
end
|
273
|
-
|
274
|
-
def public_resources?
|
275
|
-
@public_resources
|
276
|
-
end
|
277
|
-
|
278
|
-
def allow_origin?(source,env = {})
|
279
|
-
return true if public_resources?
|
280
|
-
|
281
|
-
effective_source = (source == 'null' ? 'file://' : source)
|
282
|
-
|
283
|
-
return !! @origins.detect do |origin|
|
284
|
-
if origin.is_a?(Proc)
|
285
|
-
origin.call(source,env)
|
286
|
-
else
|
287
|
-
origin === effective_source
|
288
|
-
end
|
289
|
-
end
|
290
|
-
end
|
291
|
-
|
292
|
-
def match_resource(path, env)
|
293
|
-
@resources.detect { |r| r.match?(path, env) }
|
294
|
-
end
|
180
|
+
resource.process_preflight(env, result)
|
181
|
+
end
|
295
182
|
|
296
|
-
|
297
|
-
|
298
|
-
|
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
|
299
189
|
|
190
|
+
else
|
191
|
+
Result.miss(env, error)
|
192
|
+
nil
|
300
193
|
end
|
194
|
+
end
|
301
195
|
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
self.pattern = compile(path)
|
310
|
-
self.if_proc = opts[:if]
|
311
|
-
self.vary_headers = opts[:vary] && [opts[:vary]].flatten
|
312
|
-
@public_resource = public_resource
|
313
|
-
|
314
|
-
self.headers = case opts[:headers]
|
315
|
-
when :any then :any
|
316
|
-
when nil then nil
|
317
|
-
else
|
318
|
-
[opts[:headers]].flatten.collect{|h| h.downcase}
|
319
|
-
end
|
320
|
-
|
321
|
-
self.methods = case opts[:methods]
|
322
|
-
when :any then [:get, :head, :post, :put, :patch, :delete, :options]
|
323
|
-
else
|
324
|
-
ensure_enum(opts[:methods]) || [:get]
|
325
|
-
end.map{|e| e.to_s }
|
326
|
-
|
327
|
-
self.expose = opts[:expose] ? [opts[:expose]].flatten : nil
|
328
|
-
end
|
329
|
-
|
330
|
-
def matches_path?(path)
|
331
|
-
pattern =~ path
|
332
|
-
end
|
333
|
-
|
334
|
-
def match?(path, env)
|
335
|
-
matches_path?(path) && (if_proc.nil? || if_proc.call(env))
|
336
|
-
end
|
337
|
-
|
338
|
-
def process_preflight(env)
|
339
|
-
return nil if invalid_method_request?(env) || invalid_headers_request?(env)
|
340
|
-
{'Content-Type' => 'text/plain'}.merge(to_preflight_headers(env))
|
341
|
-
end
|
342
|
-
|
343
|
-
def to_headers(env)
|
344
|
-
h = {
|
345
|
-
'Access-Control-Allow-Origin' => origin_for_response_header(env[ORIGIN_HEADER_KEY]),
|
346
|
-
'Access-Control-Allow-Methods' => methods.collect{|m| m.to_s.upcase}.join(', '),
|
347
|
-
'Access-Control-Expose-Headers' => expose.nil? ? '' : expose.join(', '),
|
348
|
-
'Access-Control-Max-Age' => max_age.to_s }
|
349
|
-
h['Access-Control-Allow-Credentials'] = 'true' if credentials
|
350
|
-
h
|
351
|
-
end
|
352
|
-
|
353
|
-
protected
|
354
|
-
def public_resource?
|
355
|
-
@public_resource
|
356
|
-
end
|
357
|
-
|
358
|
-
def origin_for_response_header(origin)
|
359
|
-
return '*' if public_resource? && !credentials
|
360
|
-
origin
|
361
|
-
end
|
362
|
-
|
363
|
-
def to_preflight_headers(env)
|
364
|
-
h = to_headers(env)
|
365
|
-
if env['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']
|
366
|
-
h.merge!('Access-Control-Allow-Headers' => env['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])
|
367
|
-
end
|
368
|
-
h
|
369
|
-
end
|
370
|
-
|
371
|
-
def invalid_method_request?(env)
|
372
|
-
request_method = env['HTTP_ACCESS_CONTROL_REQUEST_METHOD']
|
373
|
-
request_method.nil? || !methods.include?(request_method.downcase)
|
374
|
-
end
|
375
|
-
|
376
|
-
def invalid_headers_request?(env)
|
377
|
-
request_headers = env['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']
|
378
|
-
request_headers && !allow_headers?(request_headers)
|
379
|
-
end
|
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
|
200
|
+
end
|
201
|
+
nil
|
202
|
+
end
|
380
203
|
|
381
|
-
|
382
|
-
|
383
|
-
headers == :any || begin
|
384
|
-
request_headers = request_headers.split(/,\s*/) if request_headers.kind_of?(String)
|
385
|
-
request_headers.all?{|h| headers.include?(h.downcase)}
|
386
|
-
end
|
387
|
-
end
|
204
|
+
def match_resource(path, env)
|
205
|
+
origin = env[HTTP_ORIGIN]
|
388
206
|
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
end
|
207
|
+
origin_matched = false
|
208
|
+
all_resources.each do |r|
|
209
|
+
next unless r.allow_origin?(origin, env)
|
393
210
|
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
pattern =
|
398
|
-
path.to_str.gsub(/((:\w+)|[\*#{special_chars.join}])/) do |match|
|
399
|
-
case match
|
400
|
-
when "*"
|
401
|
-
"(.*?)"
|
402
|
-
when *special_chars
|
403
|
-
Regexp.escape(match)
|
404
|
-
else
|
405
|
-
"([^/?&#]+)"
|
406
|
-
end
|
407
|
-
end
|
408
|
-
/^#{pattern}$/
|
409
|
-
elsif path.respond_to? :match
|
410
|
-
path
|
411
|
-
else
|
412
|
-
raise TypeError, path
|
413
|
-
end
|
414
|
-
end
|
211
|
+
origin_matched = true
|
212
|
+
found = r.match_resource(path, env)
|
213
|
+
return [found, nil] if found
|
415
214
|
end
|
416
215
|
|
216
|
+
[nil, origin_matched ? Result::MISS_NO_PATH : Result::MISS_NO_ORIGIN]
|
217
|
+
end
|
417
218
|
end
|
418
219
|
end
|
data/rack-cors.gemspec
CHANGED
@@ -1,26 +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.
|
22
|
-
spec.add_development_dependency
|
23
|
-
spec.add_development_dependency
|
24
|
-
spec.add_development_dependency
|
25
|
-
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'
|
26
30
|
end
|