rack-cors 0.2.9 → 0.3.0
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 -13
- data/CHANGELOG +15 -0
- data/README.md +113 -0
- data/lib/rack/cors.rb +158 -31
- data/lib/rack/cors/version.rb +1 -1
- data/rack-cors.gemspec +3 -3
- data/test/cors/test.cors.coffee +20 -1
- data/test/cors/test.cors.js +33 -0
- data/test/unit/cors_test.rb +159 -77
- data/test/unit/dsl_test.rb +17 -17
- data/test/unit/non_http.ru +8 -0
- data/test/unit/test.ru +0 -4
- metadata +25 -22
- data/README.rdoc +0 -66
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
ZDQyMTJlMTg3MDczMmE0ZjFkMmZjOGExMGU3NDE0NmQ2MGY1YzBlZQ==
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7fa6e09583a5f2886f25edeea60c8684dd4570e2
|
4
|
+
data.tar.gz: d6527b5970f02a3a43dfc305cf8c3edde91ae00b
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
NDc3ODlkMTIwNjFmNGZhOWUwZmNjMmEyN2YxZWQ1NTA3NDU3NjEzMGYyNDdi
|
11
|
-
NTM4ZTI3NmQ4ZTE1MmNjOGY5ZTBlNDk2YTQyZDQ0NzA5ZTc2NTE=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
NGIwN2QwMjQ1OTQwNzY3M2MzYWFiNWI0Y2RjMjVmMTEzMTk3YjE1ZGJhNjQw
|
14
|
-
YzRjNzhkZTRmZGExYjU2YzU5Y2Q4OTkyNzAyYTFhODRmNGViOGI0MTQyNmNh
|
15
|
-
MjAwYjUxZjRkMGZjMjRmMDJhYjRiOWU2ZmNjNTFjNmEzZTY2YWQ=
|
6
|
+
metadata.gz: 6b4048b21713e5b87d4fca48995253fb500e28e82e38a57a6af489bfa0989706e6cb008f9894d2d87c7b5c7dc215aa32fdfcb3d65748cf5152a79e8c59e1813f
|
7
|
+
data.tar.gz: dd9967c547e09f5eebecc4dfcaf1fab6f16395786af08f8c0dbb09d92e3c6c5400c5d828536b5e66588086c9d9fd1e5af7cfcdebe438c92689b7c2bf066421fd
|
data/CHANGELOG
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# Change Log
|
2
|
+
All notable changes to this project will be documented in this file.
|
3
|
+
|
4
|
+
## 0.3.0 - 2014-10-19
|
5
|
+
### Added
|
6
|
+
- Added support for defining a logger with a Proc
|
7
|
+
- Return a X-Rack-CORS header when in debug mode detailing how
|
8
|
+
Rack::Cors processed a request
|
9
|
+
- Added support for non HTTP/HTTPS origins when just a domain is
|
10
|
+
is specified
|
11
|
+
|
12
|
+
### Changed
|
13
|
+
- Changed the log level of the fallback logger to DEBUG
|
14
|
+
- Print warning when attempting to use :any as an allowed method
|
15
|
+
- Treat incoming `Origin: null` headers as file://
|
data/README.md
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
# Rack CORS Middleware [](https://travis-ci.org/cyu/rack-cors)
|
2
|
+
|
3
|
+
`Rack::Cors` provides support for Cross-Origin Resource Sharing (CORS) for Rack compatible web applications.
|
4
|
+
|
5
|
+
The [CORS spec](http://www.w3.org/TR/cors/) allows web applications to make cross domain AJAX calls without using workarounds such as JSONP. See [Cross-domain Ajax with Cross-Origin Resource Sharing](http://www.nczonline.net/blog/2010/05/25/cross-domain-ajax-with-cross-origin-resource-sharing/)
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Install the gem:
|
10
|
+
|
11
|
+
`gem install rack-cors`
|
12
|
+
|
13
|
+
Or in your Gemfile:
|
14
|
+
|
15
|
+
```ruby
|
16
|
+
gem 'rack-cors', :require => 'rack/cors'
|
17
|
+
```
|
18
|
+
|
19
|
+
|
20
|
+
## Configuration
|
21
|
+
|
22
|
+
### Rack
|
23
|
+
|
24
|
+
In `config.ru`, configure `Rack::Cors` by passing a block to the `use` command:
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
use Rack::Cors do
|
28
|
+
allow do
|
29
|
+
origins 'localhost:3000', '127.0.0.1:3000',
|
30
|
+
/http:\/\/192\.168\.0\.\d{1,3}(:\d+)?/
|
31
|
+
# regular expressions can be used here
|
32
|
+
|
33
|
+
resource '/file/list_all/', :headers => 'x-domain-token'
|
34
|
+
resource '/file/at/*',
|
35
|
+
:methods => [:get, :post, :put, :delete, :options],
|
36
|
+
:headers => 'x-domain-token',
|
37
|
+
:expose => ['Some-Custom-Response-Header'],
|
38
|
+
:max_age => 600
|
39
|
+
# headers to expose
|
40
|
+
end
|
41
|
+
|
42
|
+
allow do
|
43
|
+
origins '*'
|
44
|
+
resource '/public/*', :headers => :any, :methods => :get
|
45
|
+
end
|
46
|
+
end
|
47
|
+
```
|
48
|
+
|
49
|
+
### Rails
|
50
|
+
Put something like the code below in `config/application.rb` of your Rails application. For example, this will allow GET, POST or OPTIONS requests from any origin on any resource.
|
51
|
+
|
52
|
+
```ruby
|
53
|
+
module YourApp
|
54
|
+
class Application < Rails::Application
|
55
|
+
|
56
|
+
# ...
|
57
|
+
|
58
|
+
config.middleware.insert_before 0, "Rack::Cors" do
|
59
|
+
allow do
|
60
|
+
origins '*'
|
61
|
+
resource '*', :headers => :any, :methods => [:get, :post, :options]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
67
|
+
```
|
68
|
+
Refer to [rails 3 example](https://github.com/cyu/rack-cors/tree/master/examples/rails3) and [rails 4 example](https://github.com/cyu/rack-cors/tree/master/examples/rails4) for more details.
|
69
|
+
|
70
|
+
See The [Rails Guide to Rack](http://guides.rubyonrails.org/rails_on_rack.html) for more details on rack middlewares or watch the [railscast](http://railscasts.com/episodes/151-rack-middleware.)
|
71
|
+
|
72
|
+
### Configuration Reference
|
73
|
+
|
74
|
+
#### Middleware Options
|
75
|
+
* **debug** (boolean): Enables debug logging and `X-Rack-CORS` HTTP headers for debugging.
|
76
|
+
* **logger** (Object or Proc): Specify the logger to log to. If a proc is provided, it will be called when a logger is needed (this is helpful in cases where the logger is initialized after `Rack::Cors` is used, like `Rails.logger`.
|
77
|
+
|
78
|
+
#### Origin
|
79
|
+
Origins can be specified as a string, a regular expression, or as '*' to allow all origins.
|
80
|
+
|
81
|
+
#### Resource
|
82
|
+
A Resource path can be specified as exact string match (`/path/to/file.txt`) or with a '*' wildcard (`/all/files/in/*`). A resource that take the following options:
|
83
|
+
|
84
|
+
* **methods** (string or array): The HTTP methods allowed for the resource.
|
85
|
+
* **headers** (string or array or `:any`): The HTTP headers that will be allowed in the CORS resource request. Use `:any` to allow for any headers in the actual request.
|
86
|
+
* **expose** (string or an array): The HTTP headers in the resource response can can be exposed to the client.
|
87
|
+
* **credentials** (boolean): Sets the `Access-Control-Allow-Credentials` response header.
|
88
|
+
* **max_age** (number): Sets the `Access-Control-Max-Age` response header.
|
89
|
+
|
90
|
+
|
91
|
+
## Common Gotchas
|
92
|
+
|
93
|
+
Incorrect positioning of `Rack::Cors` in the middleware stack can produce unexpected results. The Rails example above will put it above all middleware which should cover most issues.
|
94
|
+
|
95
|
+
Here are some common cases:
|
96
|
+
|
97
|
+
* **Serving static files.** Insert this middleware before `ActionDispatch::Static` so that static files are served with the proper CORS headers (see note below for a caveat). **NOTE:** that this might not work in production environments as static files are usually served from the web server (Nginx, Apache) and not the Rails container.
|
98
|
+
|
99
|
+
* **Caching in the middleware.** Insert this middleware before `Rack::Cache` so that the proper CORS headers are written and not cached ones.
|
100
|
+
|
101
|
+
* **Authentication via Warden** Warden will return immediately if a resource that requires authentication is accessed without authentication. If `Warden::Manager`is in the stack before `Rack::Cors`, it will return without the correct CORS headers being applied, resulting in a failed CORS request. Be sure to insert this middleware before 'Warden::Manager`.
|
102
|
+
|
103
|
+
To determine where to put the CORS middleware in the Rack stack, run the following command:
|
104
|
+
|
105
|
+
```bash
|
106
|
+
bundle exec rake middleware
|
107
|
+
```
|
108
|
+
|
109
|
+
In many cases, the Rack stack will be different running in production environments. For example, the `ActionDispatch::Static` middleware will not be part of the stack if `config.serve_static_assets = false`. You can run the following command to see what your middleware stack looks like in production:
|
110
|
+
|
111
|
+
```bash
|
112
|
+
bundle exec RAILS_ENV=production rake middleware
|
113
|
+
```
|
data/lib/rack/cors.rb
CHANGED
@@ -2,11 +2,23 @@ require 'logger'
|
|
2
2
|
|
3
3
|
module Rack
|
4
4
|
class Cors
|
5
|
+
ENV_KEY = 'X_RACK_CORS'.freeze
|
6
|
+
|
7
|
+
ORIGIN_HEADER_KEY = 'HTTP_ORIGIN'.freeze
|
8
|
+
PATH_INFO_HEADER_KEY = 'PATH_INFO'.freeze
|
9
|
+
|
5
10
|
def initialize(app, opts={}, &block)
|
6
11
|
@app = app
|
7
|
-
@logger = opts[:logger]
|
8
12
|
@debug_mode = !!opts[:debug]
|
9
13
|
|
14
|
+
if logger = opts[:logger]
|
15
|
+
if logger.respond_to? :call
|
16
|
+
@logger_proc = opts[:logger]
|
17
|
+
else
|
18
|
+
@logger = logger
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
10
22
|
if block_given?
|
11
23
|
if block.arity == 1
|
12
24
|
block.call(self)
|
@@ -16,6 +28,10 @@ module Rack
|
|
16
28
|
end
|
17
29
|
end
|
18
30
|
|
31
|
+
def debug?
|
32
|
+
@debug_mode
|
33
|
+
end
|
34
|
+
|
19
35
|
def allow(&block)
|
20
36
|
all_resources << (resources = Resources.new)
|
21
37
|
|
@@ -27,14 +43,13 @@ module Rack
|
|
27
43
|
end
|
28
44
|
|
29
45
|
def call(env)
|
30
|
-
env[
|
31
|
-
env['HTTP_ORIGIN'] ||= env['HTTP_X_ORIGIN']
|
46
|
+
env[ORIGIN_HEADER_KEY] ||= env['HTTP_X_ORIGIN']
|
32
47
|
|
33
|
-
|
34
|
-
if env[
|
48
|
+
add_headers = nil
|
49
|
+
if env[ORIGIN_HEADER_KEY]
|
35
50
|
debug(env) do
|
36
51
|
[ 'Incoming Headers:',
|
37
|
-
" Origin: #{env[
|
52
|
+
" Origin: #{env[ORIGIN_HEADER_KEY]}",
|
38
53
|
" Access-Control-Request-Method: #{env['HTTP_ACCESS_CONTROL_REQUEST_METHOD']}",
|
39
54
|
" Access-Control-Request-Headers: #{env['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}"
|
40
55
|
].join("\n")
|
@@ -48,12 +63,16 @@ module Rack
|
|
48
63
|
return [200, headers, []]
|
49
64
|
end
|
50
65
|
else
|
51
|
-
|
66
|
+
add_headers = process_cors(env)
|
52
67
|
end
|
68
|
+
else
|
69
|
+
Result.miss(env, Result::MISS_NO_ORIGIN)
|
53
70
|
end
|
71
|
+
|
54
72
|
status, headers, body = @app.call env
|
55
|
-
|
56
|
-
|
73
|
+
|
74
|
+
if add_headers
|
75
|
+
headers = headers.merge(add_headers)
|
57
76
|
|
58
77
|
# http://www.w3.org/TR/cors/#resource-implementation
|
59
78
|
unless headers['Access-Control-Allow-Origin'] == '*'
|
@@ -61,16 +80,33 @@ module Rack
|
|
61
80
|
headers['Vary'] = ((vary ? vary.split(/,\s*/) : []) + ['Origin']).uniq.join(', ')
|
62
81
|
end
|
63
82
|
end
|
83
|
+
|
84
|
+
if debug? && result = env[ENV_KEY]
|
85
|
+
result.append_header(headers)
|
86
|
+
end
|
87
|
+
|
64
88
|
[status, headers, body]
|
65
89
|
end
|
66
90
|
|
67
91
|
protected
|
68
92
|
def debug(env, message = nil, &block)
|
69
|
-
if
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
93
|
+
(@logger || select_logger(env)).debug(message, &block) if debug?
|
94
|
+
end
|
95
|
+
|
96
|
+
def select_logger(env)
|
97
|
+
@logger = if @logger_proc
|
98
|
+
logger_proc = @logger_proc
|
99
|
+
@logger_proc = nil
|
100
|
+
logger_proc.call
|
101
|
+
|
102
|
+
elsif defined?(Rails) && Rails.logger
|
103
|
+
Rails.logger
|
104
|
+
|
105
|
+
elsif env['rack.logger']
|
106
|
+
env['rack.logger']
|
107
|
+
|
108
|
+
else
|
109
|
+
::Logger.new(STDOUT).tap { |logger| logger.level = ::Logger::Severity::DEBUG }
|
74
110
|
end
|
75
111
|
end
|
76
112
|
|
@@ -79,22 +115,104 @@ module Rack
|
|
79
115
|
end
|
80
116
|
|
81
117
|
def process_preflight(env)
|
82
|
-
resource = find_resource(env
|
83
|
-
|
118
|
+
resource, error = find_resource(env)
|
119
|
+
if resource
|
120
|
+
Result.preflight_hit(env)
|
121
|
+
preflight = resource.process_preflight(env)
|
122
|
+
preflight
|
123
|
+
|
124
|
+
else
|
125
|
+
Result.preflight_miss(env, error)
|
126
|
+
nil
|
127
|
+
end
|
84
128
|
end
|
85
129
|
|
86
130
|
def process_cors(env)
|
87
|
-
resource = find_resource(env
|
88
|
-
|
131
|
+
resource, error = find_resource(env)
|
132
|
+
if resource
|
133
|
+
Result.hit(env)
|
134
|
+
cors = resource.to_headers(env)
|
135
|
+
cors
|
136
|
+
|
137
|
+
else
|
138
|
+
Result.miss(env, error)
|
139
|
+
nil
|
140
|
+
end
|
89
141
|
end
|
90
142
|
|
91
|
-
def find_resource(
|
143
|
+
def find_resource(env)
|
144
|
+
path = env[PATH_INFO_HEADER_KEY]
|
145
|
+
origin = env[ORIGIN_HEADER_KEY]
|
146
|
+
|
147
|
+
origin_matched = false
|
92
148
|
all_resources.each do |r|
|
93
|
-
if r.allow_origin?(origin, env)
|
94
|
-
|
149
|
+
if r.allow_origin?(origin, env)
|
150
|
+
origin_matched = true
|
151
|
+
if found = r.find_resource(path)
|
152
|
+
return [found, nil]
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
[nil, origin_matched ? Result::MISS_NO_PATH : Result::MISS_NO_ORIGIN]
|
158
|
+
end
|
159
|
+
|
160
|
+
class Result
|
161
|
+
HEADER_KEY = 'X-Rack-CORS'.freeze
|
162
|
+
|
163
|
+
MISS_NO_ORIGIN = 'no-origin'.freeze
|
164
|
+
MISS_NO_PATH = 'no-path'.freeze
|
165
|
+
|
166
|
+
attr_accessor :preflight, :hit, :miss_reason
|
167
|
+
|
168
|
+
def hit?
|
169
|
+
!!hit
|
170
|
+
end
|
171
|
+
|
172
|
+
def preflight?
|
173
|
+
!!preflight
|
174
|
+
end
|
175
|
+
|
176
|
+
def self.hit(env)
|
177
|
+
r = Result.new
|
178
|
+
r.preflight = false
|
179
|
+
r.hit = true
|
180
|
+
env[ENV_KEY] = r
|
181
|
+
end
|
182
|
+
|
183
|
+
def self.miss(env, reason)
|
184
|
+
r = Result.new
|
185
|
+
r.preflight = false
|
186
|
+
r.hit = false
|
187
|
+
r.miss_reason = reason
|
188
|
+
env[ENV_KEY] = r
|
189
|
+
end
|
190
|
+
|
191
|
+
def self.preflight_hit(env)
|
192
|
+
r = Result.new
|
193
|
+
r.preflight = true
|
194
|
+
r.hit = true
|
195
|
+
env[ENV_KEY] = r
|
196
|
+
end
|
197
|
+
|
198
|
+
def self.preflight_miss(env, reason)
|
199
|
+
r = Result.new
|
200
|
+
r.preflight = true
|
201
|
+
r.hit = false
|
202
|
+
r.miss_reason = reason
|
203
|
+
env[ENV_KEY] = r
|
204
|
+
end
|
205
|
+
|
206
|
+
def append_header(headers)
|
207
|
+
headers[HEADER_KEY] = if hit?
|
208
|
+
preflight? ? 'preflight-hit' : 'hit'
|
209
|
+
else
|
210
|
+
[
|
211
|
+
(preflight? ? 'preflight-miss' : 'preflight-hit'),
|
212
|
+
miss_reason
|
213
|
+
].join('; ')
|
95
214
|
end
|
96
215
|
end
|
97
|
-
nil
|
98
216
|
end
|
99
217
|
|
100
218
|
class Resources
|
@@ -104,13 +222,14 @@ module Rack
|
|
104
222
|
@public_resources = false
|
105
223
|
end
|
106
224
|
|
107
|
-
def origins(*args
|
225
|
+
def origins(*args, &blk)
|
108
226
|
@origins = args.flatten.collect do |n|
|
109
227
|
case n
|
110
|
-
when Regexp,
|
111
|
-
|
112
|
-
|
113
|
-
|
228
|
+
when Regexp,
|
229
|
+
/^https?:\/\//,
|
230
|
+
'file://' then n
|
231
|
+
when '*' then @public_resources = true; n
|
232
|
+
else Regexp.compile("^[a-z][a-z0-9.+-]*:\\\/\\\/#{Regexp.quote(n)}")
|
114
233
|
end
|
115
234
|
end.flatten
|
116
235
|
@origins.push(blk) if blk
|
@@ -126,11 +245,14 @@ module Rack
|
|
126
245
|
|
127
246
|
def allow_origin?(source,env = {})
|
128
247
|
return true if public_resources?
|
248
|
+
|
249
|
+
effective_source = (source == 'null' ? 'file://' : source)
|
250
|
+
|
129
251
|
return !! @origins.detect do |origin|
|
130
252
|
if origin.is_a?(Proc)
|
131
253
|
origin.call(source,env)
|
132
254
|
else
|
133
|
-
origin ===
|
255
|
+
origin === effective_source
|
134
256
|
end
|
135
257
|
end
|
136
258
|
end
|
@@ -145,7 +267,7 @@ module Rack
|
|
145
267
|
|
146
268
|
def initialize(public_resource, path, opts={})
|
147
269
|
self.path = path
|
148
|
-
self.methods =
|
270
|
+
self.methods = prepare_and_validate_methods_option(opts[:methods]) || [:get]
|
149
271
|
self.credentials = opts[:credentials].nil? ? true : opts[:credentials]
|
150
272
|
self.max_age = opts[:max_age] || 1728000
|
151
273
|
self.pattern = compile(path)
|
@@ -173,7 +295,7 @@ module Rack
|
|
173
295
|
def to_headers(env)
|
174
296
|
x_origin = env['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']
|
175
297
|
h = {
|
176
|
-
'Access-Control-Allow-Origin' => origin_for_response_header(env[
|
298
|
+
'Access-Control-Allow-Origin' => origin_for_response_header(env[ORIGIN_HEADER_KEY]),
|
177
299
|
'Access-Control-Allow-Methods' => methods.collect{|m| m.to_s.upcase}.join(', '),
|
178
300
|
'Access-Control-Expose-Headers' => expose.nil? ? '' : expose.join(', '),
|
179
301
|
'Access-Control-Max-Age' => max_age.to_s }
|
@@ -188,7 +310,7 @@ module Rack
|
|
188
310
|
|
189
311
|
def origin_for_response_header(origin)
|
190
312
|
return '*' if public_resource? && !credentials
|
191
|
-
origin
|
313
|
+
origin
|
192
314
|
end
|
193
315
|
|
194
316
|
def to_preflight_headers(env)
|
@@ -217,6 +339,11 @@ module Rack
|
|
217
339
|
end
|
218
340
|
end
|
219
341
|
|
342
|
+
def prepare_and_validate_methods_option setting
|
343
|
+
raise ArgumentError.new("rack-cors methods must be an single HTTP verb, or an array of verbs") if setting && setting == :any
|
344
|
+
ensure_enum setting
|
345
|
+
end
|
346
|
+
|
220
347
|
def ensure_enum(v)
|
221
348
|
return nil if v.nil?
|
222
349
|
[v].flatten
|
data/lib/rack/cors/version.rb
CHANGED
data/rack-cors.gemspec
CHANGED
@@ -8,9 +8,9 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = Rack::Cors::VERSION
|
9
9
|
spec.authors = ["Calvin Yu"]
|
10
10
|
spec.email = ["me@sourcebender.com"]
|
11
|
-
spec.description = %q{Middleware that will make Rack-based apps CORS compatible. Read more here: http://blog.sourcebender.com/2010/06/09/introducin-rack-cors.html. Fork the project here:
|
11
|
+
spec.description = %q{Middleware that will make Rack-based apps CORS compatible. Read more here: http://blog.sourcebender.com/2010/06/09/introducin-rack-cors.html. Fork the project here: https://github.com/cyu/rack-cors}
|
12
12
|
spec.summary = %q{Middleware for enabling Cross-Origin Resource Sharing in Rack apps}
|
13
|
-
spec.homepage = "
|
13
|
+
spec.homepage = "https://github.com/cyu/rack-cors"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
16
|
spec.files = `git ls-files`.split($/).reject { |f| f == '.gitignore' or f =~ /^examples/ }
|
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.add_development_dependency "bundler", "~> 1.3"
|
22
22
|
spec.add_development_dependency "rake"
|
23
|
-
spec.add_development_dependency "
|
23
|
+
spec.add_development_dependency "minitest", ">= 5.3.0"
|
24
24
|
spec.add_development_dependency "mocha", ">= 0.14.0"
|
25
25
|
spec.add_development_dependency "rack-test", ">= 0"
|
26
26
|
end
|
data/test/cors/test.cors.coffee
CHANGED
@@ -7,6 +7,26 @@ describe 'CORS', ->
|
|
7
7
|
expect(data).to.eql('Hello world')
|
8
8
|
done()
|
9
9
|
|
10
|
+
it 'should allow PUT access to dynamic resource', (done) ->
|
11
|
+
$.ajax("http://#{CORS_SERVER}/", type: 'PUT').done (data, textStatus, jqXHR) ->
|
12
|
+
expect(data).to.eql('Hello world')
|
13
|
+
done()
|
14
|
+
|
15
|
+
it 'should allow HEAD access to dynamic resource', (done) ->
|
16
|
+
$.ajax("http://#{CORS_SERVER}/", type: 'HEAD').done (data, textStatus, jqXHR) ->
|
17
|
+
expect(jqXHR.status).to.eql(200)
|
18
|
+
done()
|
19
|
+
|
20
|
+
it 'should allow DELETE access to dynamic resource', (done) ->
|
21
|
+
$.ajax("http://#{CORS_SERVER}/", type: 'DELETE').done (data, textStatus, jqXHR) ->
|
22
|
+
expect(data).to.eql('Hello world')
|
23
|
+
done()
|
24
|
+
|
25
|
+
it 'should allow OPTIONS access to dynamic resource', (done) ->
|
26
|
+
$.ajax("http://#{CORS_SERVER}/", type: 'OPTIONS').done (data, textStatus, jqXHR) ->
|
27
|
+
expect(jqXHR.status).to.eql(200)
|
28
|
+
done()
|
29
|
+
|
10
30
|
it 'should allow access to static resource', (done) ->
|
11
31
|
$.get "http://#{CORS_SERVER}/static.txt", (data, status, xhr) ->
|
12
32
|
expect($.trim(data)).to.eql("hello world")
|
@@ -20,4 +40,3 @@ describe 'CORS', ->
|
|
20
40
|
success:(data, status, xhr) ->
|
21
41
|
expect($.trim(data)).to.eql("OK!")
|
22
42
|
done()
|
23
|
-
|
data/test/cors/test.cors.js
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
// Generated by CoffeeScript 1.7.1
|
1
2
|
(function() {
|
2
3
|
var CORS_SERVER;
|
3
4
|
|
@@ -10,6 +11,38 @@
|
|
10
11
|
return done();
|
11
12
|
});
|
12
13
|
});
|
14
|
+
it('should allow PUT access to dynamic resource', function(done) {
|
15
|
+
return $.ajax("http://" + CORS_SERVER + "/", {
|
16
|
+
type: 'PUT'
|
17
|
+
}).done(function(data, textStatus, jqXHR) {
|
18
|
+
expect(data).to.eql('Hello world');
|
19
|
+
return done();
|
20
|
+
});
|
21
|
+
});
|
22
|
+
it('should allow HEAD access to dynamic resource', function(done) {
|
23
|
+
return $.ajax("http://" + CORS_SERVER + "/", {
|
24
|
+
type: 'HEAD'
|
25
|
+
}).done(function(data, textStatus, jqXHR) {
|
26
|
+
expect(jqXHR.status).to.eql(200);
|
27
|
+
return done();
|
28
|
+
});
|
29
|
+
});
|
30
|
+
it('should allow DELETE access to dynamic resource', function(done) {
|
31
|
+
return $.ajax("http://" + CORS_SERVER + "/", {
|
32
|
+
type: 'DELETE'
|
33
|
+
}).done(function(data, textStatus, jqXHR) {
|
34
|
+
expect(data).to.eql('Hello world');
|
35
|
+
return done();
|
36
|
+
});
|
37
|
+
});
|
38
|
+
it('should allow OPTIONS access to dynamic resource', function(done) {
|
39
|
+
return $.ajax("http://" + CORS_SERVER + "/", {
|
40
|
+
type: 'OPTIONS'
|
41
|
+
}).done(function(data, textStatus, jqXHR) {
|
42
|
+
expect(jqXHR.status).to.eql(200);
|
43
|
+
return done();
|
44
|
+
});
|
45
|
+
});
|
13
46
|
it('should allow access to static resource', function(done) {
|
14
47
|
return $.get("http://" + CORS_SERVER + "/static.txt", function(data, status, xhr) {
|
15
48
|
expect($.trim(data)).to.eql("hello world");
|
data/test/unit/cors_test.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
require '
|
2
|
+
require 'minitest/autorun'
|
3
3
|
require 'rack/test'
|
4
|
-
require 'shoulda'
|
5
4
|
require 'mocha/setup'
|
6
5
|
require 'rack/cors'
|
6
|
+
require 'ostruct'
|
7
7
|
|
8
8
|
Rack::Test::Session.class_eval do
|
9
9
|
def options(uri, params = {}, env = {}, &block)
|
@@ -16,149 +16,231 @@ Rack::Test::Methods.class_eval do
|
|
16
16
|
def_delegator :current_session, :options
|
17
17
|
end
|
18
18
|
|
19
|
-
|
19
|
+
describe Rack::Cors do
|
20
20
|
include Rack::Test::Methods
|
21
21
|
|
22
|
-
|
23
|
-
|
22
|
+
attr_accessor :cors_result
|
23
|
+
|
24
|
+
def load_app(name)
|
25
|
+
test = self
|
26
|
+
Rack::Builder.new do
|
27
|
+
eval File.read(File.dirname(__FILE__) + "/#{name}.ru")
|
28
|
+
map('/') do
|
29
|
+
run proc { |env|
|
30
|
+
test.cors_result = env[Rack::Cors::ENV_KEY]
|
31
|
+
[200, {'Content-Type' => 'text/html'}, ['success']]
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
24
35
|
end
|
25
36
|
|
26
|
-
|
37
|
+
let(:app) { load_app('test') }
|
27
38
|
|
28
|
-
should
|
39
|
+
it 'should support simple CORS request' do
|
40
|
+
cors_request
|
41
|
+
cors_result.must_be :hit
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should not return CORS headers if Origin header isn't present" do
|
45
|
+
get '/'
|
46
|
+
should_render_cors_failure
|
47
|
+
cors_result.wont_be :hit
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should support OPTIONS CORS request' do
|
29
51
|
cors_request '/options', :method => :options
|
30
52
|
end
|
31
53
|
|
32
|
-
should
|
54
|
+
it 'should support regex origins configuration' do
|
33
55
|
cors_request :origin => 'http://192.168.0.1:1234'
|
34
56
|
end
|
35
57
|
|
36
|
-
should
|
58
|
+
it 'should support proc origins configuration' do
|
37
59
|
cors_request '/proc-origin', :origin => 'http://10.10.10.10:3000'
|
38
60
|
end
|
39
61
|
|
40
|
-
should
|
62
|
+
it 'should support alternative X-Origin header' do
|
41
63
|
header 'X-Origin', 'http://localhost:3000'
|
42
64
|
get '/'
|
43
|
-
|
65
|
+
should_render_cors_success
|
44
66
|
end
|
45
67
|
|
46
|
-
should
|
68
|
+
it 'should support expose header configuration' do
|
47
69
|
cors_request '/expose_single_header'
|
48
|
-
|
70
|
+
last_response.headers['Access-Control-Expose-Headers'].must_equal 'expose-test'
|
49
71
|
end
|
50
72
|
|
51
|
-
should
|
73
|
+
it 'should support expose multiple header configuration' do
|
52
74
|
cors_request '/expose_multiple_headers'
|
53
|
-
|
75
|
+
last_response.headers['Access-Control-Expose-Headers'].must_equal 'expose-test-1, expose-test-2'
|
54
76
|
end
|
55
77
|
|
56
|
-
should
|
78
|
+
it 'should add Vary header if Access-Control-Allow-Origin header was added and if it is specific' do
|
57
79
|
cors_request '/', :origin => "http://192.168.0.3:8080"
|
58
|
-
|
59
|
-
|
60
|
-
assert_not_nil last_response.headers['Vary'], 'missing Vary header'
|
80
|
+
last_response.headers['Access-Control-Allow-Origin'].must_equal 'http://192.168.0.3:8080'
|
81
|
+
last_response.headers['Vary'].wont_be_nil
|
61
82
|
end
|
62
83
|
|
63
|
-
should
|
84
|
+
it 'should not add Vary header if Access-Control-Allow-Origin header was added and if it is generic (*)' do
|
64
85
|
cors_request '/public_without_credentials', :origin => "http://192.168.1.3:8080"
|
65
|
-
|
66
|
-
|
67
|
-
assert_nil last_response.headers['Vary'], 'no expecting Vary header'
|
86
|
+
last_response.headers['Access-Control-Allow-Origin'].must_equal '*'
|
87
|
+
last_response.headers['Vary'].must_be_nil
|
68
88
|
end
|
69
89
|
|
70
|
-
should
|
90
|
+
it 'should support multi allow configurations for the same resource' do
|
71
91
|
cors_request '/multi-allow-config', :origin => "http://mucho-grande.com"
|
72
|
-
|
73
|
-
|
74
|
-
assert_equal 'Origin', last_response.headers['Vary'], 'expecting Vary header'
|
92
|
+
last_response.headers['Access-Control-Allow-Origin'].must_equal 'http://mucho-grande.com'
|
93
|
+
last_response.headers['Vary'].must_equal 'Origin'
|
75
94
|
|
76
95
|
cors_request '/multi-allow-config', :origin => "http://192.168.1.3:8080"
|
77
|
-
|
78
|
-
|
79
|
-
assert_nil last_response.headers['Vary'], 'no expecting Vary header'
|
96
|
+
last_response.headers['Access-Control-Allow-Origin'].must_equal '*'
|
97
|
+
last_response.headers['Vary'].must_be_nil
|
80
98
|
end
|
81
99
|
|
82
|
-
should
|
83
|
-
|
84
|
-
|
100
|
+
it "should not return CORS headers on OPTIONS request if Access-Control-Allow-Origin is not present" do
|
101
|
+
options '/get-only'
|
102
|
+
last_response.headers['Access-Control-Allow-Origin'].must_be_nil
|
103
|
+
end
|
85
104
|
|
86
|
-
|
87
|
-
|
105
|
+
describe 'logging' do
|
106
|
+
it 'should not log debug messages if debug option is false' do
|
107
|
+
app = mock
|
108
|
+
app.stubs(:call).returns(200, {}, [''])
|
88
109
|
|
89
|
-
|
90
|
-
|
91
|
-
|
110
|
+
logger = mock
|
111
|
+
logger.expects(:debug).never
|
112
|
+
|
113
|
+
cors = Rack::Cors.new(app, :debug => false, :logger => logger) {}
|
114
|
+
cors.send(:debug, {}, 'testing')
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'should log debug messages if debug option is true' do
|
118
|
+
app = mock
|
119
|
+
app.stubs(:call).returns(200, {}, [''])
|
120
|
+
|
121
|
+
logger = mock
|
122
|
+
logger.expects(:debug)
|
123
|
+
|
124
|
+
cors = Rack::Cors.new(app, :debug => true, :logger => logger) {}
|
125
|
+
cors.send(:debug, {}, 'testing')
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'should use rack.logger if available' do
|
129
|
+
app = mock
|
130
|
+
app.stubs(:call).returns([200, {}, ['']])
|
131
|
+
|
132
|
+
logger = mock
|
133
|
+
logger.expects(:debug).at_least_once
|
92
134
|
|
93
|
-
|
94
|
-
|
95
|
-
|
135
|
+
cors = Rack::Cors.new(app, :debug => true) {}
|
136
|
+
cors.call({'rack.logger' => logger, 'HTTP_ORIGIN' => 'test.com'})
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'should use logger proc' do
|
140
|
+
app = mock
|
141
|
+
app.stubs(:call).returns([200, {}, ['']])
|
142
|
+
|
143
|
+
logger = mock
|
144
|
+
logger.expects(:debug)
|
145
|
+
|
146
|
+
cors = Rack::Cors.new(app, :debug => true, :logger => proc { logger }) {}
|
147
|
+
cors.call({'HTTP_ORIGIN' => 'test.com'})
|
148
|
+
end
|
149
|
+
|
150
|
+
describe 'with Rails setup' do
|
151
|
+
after do
|
152
|
+
::Rails.logger = nil if defined?(::Rails)
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'should use Rails.logger if available' do
|
156
|
+
app = mock
|
157
|
+
app.stubs(:call).returns([200, {}, ['']])
|
158
|
+
|
159
|
+
logger = mock
|
160
|
+
logger.expects(:debug)
|
96
161
|
|
97
|
-
|
98
|
-
logger.expects(:debug)
|
162
|
+
::Rails = OpenStruct.new(:logger => logger)
|
99
163
|
|
100
|
-
|
101
|
-
|
164
|
+
cors = Rack::Cors.new(app, :debug => true) {}
|
165
|
+
cors.call({'HTTP_ORIGIN' => 'test.com'})
|
166
|
+
end
|
167
|
+
end
|
102
168
|
end
|
103
169
|
|
104
|
-
|
105
|
-
should
|
170
|
+
describe 'preflight requests' do
|
171
|
+
it 'should fail if origin is invalid' do
|
106
172
|
preflight_request('http://allyourdataarebelongtous.com', '/')
|
107
|
-
|
173
|
+
should_render_cors_failure
|
174
|
+
cors_result.wont_be :hit
|
175
|
+
cors_result.must_be :preflight
|
108
176
|
end
|
109
177
|
|
110
|
-
should
|
178
|
+
it 'should fail if Access-Control-Request-Method is not allowed' do
|
111
179
|
preflight_request('http://localhost:3000', '/get-only', :method => :post)
|
112
|
-
|
180
|
+
should_render_cors_failure
|
113
181
|
end
|
114
182
|
|
115
|
-
should
|
183
|
+
it 'should fail if header is not allowed' do
|
116
184
|
preflight_request('http://localhost:3000', '/single_header', :headers => 'Fooey')
|
117
|
-
|
185
|
+
should_render_cors_failure
|
118
186
|
end
|
119
187
|
|
120
|
-
should
|
188
|
+
it 'should allow any header if headers = :any' do
|
121
189
|
preflight_request('http://localhost:3000', '/', :headers => 'Fooey')
|
122
|
-
|
190
|
+
should_render_cors_success
|
123
191
|
end
|
124
192
|
|
125
|
-
should
|
193
|
+
it 'should allow header case insensitive match' do
|
126
194
|
preflight_request('http://localhost:3000', '/single_header', :headers => 'X-Domain-Token')
|
127
|
-
|
195
|
+
should_render_cors_success
|
128
196
|
end
|
129
197
|
|
130
|
-
should
|
198
|
+
it 'should allow multiple headers match' do
|
131
199
|
# Webkit style
|
132
200
|
preflight_request('http://localhost:3000', '/two_headers', :headers => 'X-Requested-With, X-Domain-Token')
|
133
|
-
|
201
|
+
should_render_cors_success
|
134
202
|
|
135
203
|
# Gecko style
|
136
204
|
preflight_request('http://localhost:3000', '/two_headers', :headers => 'x-requested-with,x-domain-token')
|
137
|
-
|
205
|
+
should_render_cors_success
|
138
206
|
end
|
139
207
|
|
140
|
-
should
|
208
|
+
it 'should * origin should allow any origin' do
|
141
209
|
preflight_request('http://locohost:3000', '/public')
|
142
|
-
|
143
|
-
|
210
|
+
should_render_cors_success
|
211
|
+
last_response.headers['Access-Control-Allow-Origin'].must_equal 'http://locohost:3000'
|
144
212
|
end
|
145
213
|
|
146
|
-
should
|
214
|
+
it 'should * origin should allow any origin, and set * if no credentials required' do
|
147
215
|
preflight_request('http://locohost:3000', '/public_without_credentials')
|
148
|
-
|
149
|
-
|
216
|
+
should_render_cors_success
|
217
|
+
last_response.headers['Access-Control-Allow-Origin'].must_equal '*'
|
150
218
|
end
|
151
219
|
|
152
|
-
should
|
220
|
+
it 'should "null" origin, allowed as "file://", returned as "null" in header' do
|
153
221
|
preflight_request('null', '/')
|
154
|
-
|
155
|
-
|
222
|
+
should_render_cors_success
|
223
|
+
last_response.headers['Access-Control-Allow-Origin'].must_equal 'null'
|
224
|
+
end
|
225
|
+
|
226
|
+
it 'should return "file://" as header with "file://" as origin' do
|
227
|
+
preflight_request('file://', '/')
|
228
|
+
should_render_cors_success
|
229
|
+
last_response.headers['Access-Control-Allow-Origin'].must_equal 'file://'
|
156
230
|
end
|
157
231
|
|
158
|
-
should
|
232
|
+
it 'should return a Content-Type' do
|
159
233
|
preflight_request('http://localhost:3000', '/')
|
160
|
-
|
161
|
-
|
234
|
+
should_render_cors_success
|
235
|
+
last_response.headers['Content-Type'].wont_be_nil
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
describe "with non HTTP config" do
|
240
|
+
let(:app) { load_app("non_http") }
|
241
|
+
|
242
|
+
it 'should support non http/https origins' do
|
243
|
+
cors_request '/public', origin: 'content://com.company.app'
|
162
244
|
end
|
163
245
|
end
|
164
246
|
|
@@ -170,8 +252,8 @@ class CorsTest < Test::Unit::TestCase
|
|
170
252
|
opts.merge! args.last if args.last.is_a?(Hash)
|
171
253
|
|
172
254
|
header 'Origin', opts[:origin]
|
173
|
-
current_session.__send__ opts[:method], path
|
174
|
-
|
255
|
+
current_session.__send__ opts[:method], path, {}, test: self
|
256
|
+
should_render_cors_success
|
175
257
|
end
|
176
258
|
|
177
259
|
def preflight_request(origin, path, opts = {})
|
@@ -185,11 +267,11 @@ class CorsTest < Test::Unit::TestCase
|
|
185
267
|
options path
|
186
268
|
end
|
187
269
|
|
188
|
-
def
|
189
|
-
|
270
|
+
def should_render_cors_success
|
271
|
+
last_response.headers['Access-Control-Allow-Origin'].wont_be_nil
|
190
272
|
end
|
191
273
|
|
192
|
-
def
|
193
|
-
|
274
|
+
def should_render_cors_failure
|
275
|
+
last_response.headers['Access-Control-Allow-Origin'].must_be_nil
|
194
276
|
end
|
195
277
|
end
|
data/test/unit/dsl_test.rb
CHANGED
@@ -1,11 +1,10 @@
|
|
1
1
|
require 'rubygems'
|
2
|
-
require '
|
2
|
+
require 'minitest/autorun'
|
3
3
|
require 'rack/cors'
|
4
|
-
require 'shoulda'
|
5
4
|
|
6
5
|
|
7
|
-
|
8
|
-
should
|
6
|
+
describe Rack::Cors, 'DSL' do
|
7
|
+
it 'should support explicit config object dsl mode' do
|
9
8
|
cors = Rack::Cors.new(Proc.new {}) do |cfg|
|
10
9
|
cfg.allow do |allow|
|
11
10
|
allow.origins 'localhost:3000', '127.0.0.1:3000' do |source,env|
|
@@ -17,15 +16,15 @@ class DSLTest < Test::Unit::TestCase
|
|
17
16
|
end
|
18
17
|
end
|
19
18
|
resources = cors.send :all_resources
|
20
|
-
assert_equal 1, resources.length
|
21
|
-
assert resources.first.allow_origin?('http://localhost:3000')
|
22
19
|
|
23
|
-
|
24
|
-
|
25
|
-
|
20
|
+
resources.length.must_equal 1
|
21
|
+
resources.first.allow_origin?('http://localhost:3000').must_equal true
|
22
|
+
resources.first.allow_origin?('http://10.10.10.10:3000',{"USER_AGENT" => "test-agent" }).must_equal true
|
23
|
+
resources.first.allow_origin?('http://10.10.10.10:3001',{"USER_AGENT" => "test-agent" }).wont_equal true
|
24
|
+
resources.first.allow_origin?('http://10.10.10.10:3000',{"USER_AGENT" => "other-agent"}).wont_equal true
|
26
25
|
end
|
27
26
|
|
28
|
-
should
|
27
|
+
it 'should support implicit config object dsl mode' do
|
29
28
|
cors = Rack::Cors.new(Proc.new {}) do
|
30
29
|
allow do
|
31
30
|
origins 'localhost:3000', '127.0.0.1:3000' do |source,env|
|
@@ -37,15 +36,15 @@ class DSLTest < Test::Unit::TestCase
|
|
37
36
|
end
|
38
37
|
end
|
39
38
|
resources = cors.send :all_resources
|
40
|
-
assert_equal 1, resources.length
|
41
|
-
assert resources.first.allow_origin?('http://localhost:3000')
|
42
39
|
|
43
|
-
|
44
|
-
|
45
|
-
|
40
|
+
resources.length.must_equal 1
|
41
|
+
resources.first.allow_origin?('http://localhost:3000').must_equal true
|
42
|
+
resources.first.allow_origin?('http://10.10.10.10:3000',{"USER_AGENT" => "test-agent" }).must_equal true
|
43
|
+
resources.first.allow_origin?('http://10.10.10.10:3001',{"USER_AGENT" => "test-agent" }).wont_equal true
|
44
|
+
resources.first.allow_origin?('http://10.10.10.10:3000',{"USER_AGENT" => "other-agent"}).wont_equal true
|
46
45
|
end
|
47
46
|
|
48
|
-
should
|
47
|
+
it 'should support "file://" origin' do
|
49
48
|
cors = Rack::Cors.new(Proc.new {}) do
|
50
49
|
allow do
|
51
50
|
origins 'file://'
|
@@ -53,6 +52,7 @@ class DSLTest < Test::Unit::TestCase
|
|
53
52
|
end
|
54
53
|
end
|
55
54
|
resources = cors.send :all_resources
|
56
|
-
|
55
|
+
|
56
|
+
resources.first.allow_origin?('file://').must_equal true
|
57
57
|
end
|
58
58
|
end
|
data/test/unit/test.ru
CHANGED
metadata
CHANGED
@@ -1,97 +1,98 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rack-cors
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Calvin Yu
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-12-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - ~>
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.3'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - ~>
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.3'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: minitest
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: 5.3.0
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: 5.3.0
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: mocha
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: 0.14.0
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: 0.14.0
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rack-test
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
-
description:
|
83
|
+
description: 'Middleware that will make Rack-based apps CORS compatible. Read more
|
84
84
|
here: http://blog.sourcebender.com/2010/06/09/introducin-rack-cors.html. Fork the
|
85
|
-
project here:
|
85
|
+
project here: https://github.com/cyu/rack-cors'
|
86
86
|
email:
|
87
87
|
- me@sourcebender.com
|
88
88
|
executables: []
|
89
89
|
extensions: []
|
90
90
|
extra_rdoc_files: []
|
91
91
|
files:
|
92
|
+
- CHANGELOG
|
92
93
|
- Gemfile
|
93
94
|
- LICENSE.txt
|
94
|
-
- README.
|
95
|
+
- README.md
|
95
96
|
- Rakefile
|
96
97
|
- lib/rack/cors.rb
|
97
98
|
- lib/rack/cors/version.rb
|
@@ -104,8 +105,9 @@ files:
|
|
104
105
|
- test/cors/test.cors.js
|
105
106
|
- test/unit/cors_test.rb
|
106
107
|
- test/unit/dsl_test.rb
|
108
|
+
- test/unit/non_http.ru
|
107
109
|
- test/unit/test.ru
|
108
|
-
homepage:
|
110
|
+
homepage: https://github.com/cyu/rack-cors
|
109
111
|
licenses:
|
110
112
|
- MIT
|
111
113
|
metadata: {}
|
@@ -115,17 +117,17 @@ require_paths:
|
|
115
117
|
- lib
|
116
118
|
required_ruby_version: !ruby/object:Gem::Requirement
|
117
119
|
requirements:
|
118
|
-
- -
|
120
|
+
- - ">="
|
119
121
|
- !ruby/object:Gem::Version
|
120
122
|
version: '0'
|
121
123
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
122
124
|
requirements:
|
123
|
-
- -
|
125
|
+
- - ">="
|
124
126
|
- !ruby/object:Gem::Version
|
125
127
|
version: '0'
|
126
128
|
requirements: []
|
127
129
|
rubyforge_project:
|
128
|
-
rubygems_version: 2.
|
130
|
+
rubygems_version: 2.2.2
|
129
131
|
signing_key:
|
130
132
|
specification_version: 4
|
131
133
|
summary: Middleware for enabling Cross-Origin Resource Sharing in Rack apps
|
@@ -138,4 +140,5 @@ test_files:
|
|
138
140
|
- test/cors/test.cors.js
|
139
141
|
- test/unit/cors_test.rb
|
140
142
|
- test/unit/dsl_test.rb
|
143
|
+
- test/unit/non_http.ru
|
141
144
|
- test/unit/test.ru
|
data/README.rdoc
DELETED
@@ -1,66 +0,0 @@
|
|
1
|
-
= Rack CORS Middleware
|
2
|
-
|
3
|
-
Rack::Cors provides support for Cross-Origin Resource Sharing (CORS) for Rack compatible web applications. The CORS spec allows web applications to make cross domain AJAX calls without
|
4
|
-
using workarounds such as JSONP. For a thorough write up on CORS, see this blog post:
|
5
|
-
|
6
|
-
http://www.nczonline.net/blog/2010/05/25/cross-domain-ajax-with-cross-origin-resource-sharing/
|
7
|
-
|
8
|
-
Or for all the gory details, you can read the spec here:
|
9
|
-
|
10
|
-
http://www.w3.org/TR/access-control/#simple-cross-origin-request-and-actual-r
|
11
|
-
|
12
|
-
|
13
|
-
Install the gem:
|
14
|
-
|
15
|
-
gem install rack-cors
|
16
|
-
|
17
|
-
In your Gemfile:
|
18
|
-
|
19
|
-
gem 'rack-cors', :require => 'rack/cors'
|
20
|
-
|
21
|
-
|
22
|
-
== Configuration
|
23
|
-
|
24
|
-
You configure Rack::Cors by passing a block to the <tt>use</tt> command:
|
25
|
-
|
26
|
-
use Rack::Cors do
|
27
|
-
allow do
|
28
|
-
origins 'localhost:3000', '127.0.0.1:3000',
|
29
|
-
/http:\/\/192\.168\.0\.\d{1,3}(:\d+)?/
|
30
|
-
# regular expressions can be used here
|
31
|
-
|
32
|
-
resource '/file/list_all/', :headers => 'x-domain-token'
|
33
|
-
resource '/file/at/*',
|
34
|
-
:methods => [:get, :post, :put, :delete, :options],
|
35
|
-
:headers => 'x-domain-token',
|
36
|
-
:expose => ['Some-Custom-Response-Header'],
|
37
|
-
:max_age => 600
|
38
|
-
# headers to expose
|
39
|
-
end
|
40
|
-
|
41
|
-
allow do
|
42
|
-
origins '*'
|
43
|
-
resource '/public/*', :headers => :any, :methods => :get
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
Put your code in "config/application.rb" on your rails application. For example, this will allow
|
48
|
-
from any origins on any resource of your application, methods :get, :post and :options.
|
49
|
-
|
50
|
-
module YourApp
|
51
|
-
class Application < Rails::Application
|
52
|
-
|
53
|
-
# ...
|
54
|
-
|
55
|
-
config.middleware.use Rack::Cors do
|
56
|
-
allow do
|
57
|
-
origins '*'
|
58
|
-
resource '*', :headers => :any, :methods => [:get, :post, :options]
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
See http://guides.rubyonrails.org/rails_on_rack.html for more details on rack middlewares or
|
66
|
-
http://railscasts.com/episodes/151-rack-middleware.
|