rack-cors 0.2.9 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
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 [![Build Status](https://travis-ci.org/cyu/rack-cors.svg?branch=master)](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.
|