rack-cors 0.2.7 → 0.2.8

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.

data/Gemfile CHANGED
@@ -5,7 +5,8 @@ gem "rack"
5
5
  group :development do
6
6
  gem "rake"
7
7
  gem "shoulda"
8
+ gem "mocha"
8
9
  gem "rack-test"
9
- gem "bundler", "~> 1.1.0"
10
+ gem "bundler", ">= 1.1.0"
10
11
  gem "jeweler", "~> 1.8.3"
11
12
  end
@@ -13,7 +13,7 @@ http://www.w3.org/TR/access-control/#simple-cross-origin-request-and-actual-r
13
13
  Install the gem:
14
14
 
15
15
  gem install rack-cors
16
-
16
+
17
17
  In your Gemfile:
18
18
 
19
19
  gem 'rack-cors', :require => 'rack/cors'
@@ -31,7 +31,7 @@ You configure Rack::Cors by passing a block to the <tt>use</tt> command:
31
31
 
32
32
  resource '/file/list_all/', :headers => 'x-domain-token'
33
33
  resource '/file/at/*',
34
- :methods => [:get, :post, :put, :delete],
34
+ :methods => [:get, :post, :put, :delete, :options],
35
35
  :headers => 'x-domain-token',
36
36
  :expose => ['Some-Custom-Response-Header']
37
37
  # headers to expose
@@ -42,3 +42,22 @@ You configure Rack::Cors by passing a block to the <tt>use</tt> command:
42
42
  resource '/public/*', :headers => :any, :methods => :get
43
43
  end
44
44
  end
45
+
46
+ Put your code in "config/application.rb" on your rails application. For example, this will allow
47
+ from any origins on any resource of your application, methods :get, :post and :options.
48
+
49
+ module YourApp
50
+ class Application < Rails::Application
51
+
52
+ # ...
53
+
54
+ config.middleware.use Rack::Cors do
55
+ allow do
56
+ origins '*'
57
+ resource '*', :headers => :any, :methods => [:get, :post, :options]
58
+ end
59
+ end
60
+ end
61
+
62
+ See http://guides.rubyonrails.org/rails_on_rack.html for more details on rack middlewares or
63
+ http://railscasts.com/episodes/151-rack-middleware.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.7
1
+ 0.2.8
@@ -5,11 +5,14 @@ module Rack
5
5
  def initialize(app, opts={}, &block)
6
6
  @app = app
7
7
  @logger = opts[:logger]
8
+ @debug_mode = !!opts[:debug]
8
9
 
9
- if block.arity == 1
10
- block.call(self)
11
- else
12
- instance_eval(&block)
10
+ if block_given?
11
+ if block.arity == 1
12
+ block.call(self)
13
+ else
14
+ instance_eval(&block)
15
+ end
13
16
  end
14
17
  end
15
18
 
@@ -61,10 +64,12 @@ module Rack
61
64
 
62
65
  protected
63
66
  def debug(env, message = nil, &block)
64
- logger = @logger || env['rack.logger'] || begin
65
- @logger = ::Logger.new(STDOUT).tap {|logger| logger.level = ::Logger::Severity::INFO}
67
+ if @debug_mode
68
+ logger = @logger || env['rack.logger'] || begin
69
+ @logger = ::Logger.new(STDOUT).tap {|logger| logger.level = ::Logger::Severity::INFO}
70
+ end
71
+ logger.debug(message, &block)
66
72
  end
67
- logger.debug(message, &block)
68
73
  end
69
74
 
70
75
  def all_resources
@@ -72,17 +77,17 @@ module Rack
72
77
  end
73
78
 
74
79
  def process_preflight(env)
75
- resource = find_resource(env['HTTP_ORIGIN'], env['PATH_INFO'])
80
+ resource = find_resource(env['HTTP_ORIGIN'], env['PATH_INFO'],env)
76
81
  resource && resource.process_preflight(env)
77
82
  end
78
83
 
79
84
  def process_cors(env)
80
- resource = find_resource(env['HTTP_ORIGIN'], env['PATH_INFO'])
85
+ resource = find_resource(env['HTTP_ORIGIN'], env['PATH_INFO'],env)
81
86
  resource.to_headers(env) if resource
82
87
  end
83
88
 
84
- def find_resource(origin, path)
85
- allowed = all_resources.detect {|r| r.allow_origin?(origin)}
89
+ def find_resource(origin, path, env)
90
+ allowed = all_resources.detect {|r| r.allow_origin?(origin,env)}
86
91
  allowed ? allowed.find_resource(path) : nil
87
92
  end
88
93
 
@@ -93,14 +98,16 @@ module Rack
93
98
  @public_resources = false
94
99
  end
95
100
 
96
- def origins(*args)
101
+ def origins(*args,&blk)
97
102
  @origins = args.flatten.collect do |n|
98
103
  case n
99
104
  when Regexp, /^https?:\/\// then n
105
+ when 'file://' then n
100
106
  when '*' then @public_resources = true; n
101
107
  else "http://#{n}"
102
108
  end
103
109
  end
110
+ @origins.push(blk) if blk
104
111
  end
105
112
 
106
113
  def resource(path, opts={})
@@ -111,8 +118,15 @@ module Rack
111
118
  @public_resources
112
119
  end
113
120
 
114
- def allow_origin?(source)
115
- public_resources? || !!@origins.detect {|origin| origin === source}
121
+ def allow_origin?(source,env = {})
122
+ return true if public_resources?
123
+ return !! @origins.detect do |origin|
124
+ if origin.is_a?(Proc)
125
+ origin.call(source,env)
126
+ else
127
+ origin === source
128
+ end
129
+ end
116
130
  end
117
131
 
118
132
  def find_resource(path)
@@ -152,7 +166,8 @@ module Rack
152
166
 
153
167
  def to_headers(env)
154
168
  x_origin = env['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']
155
- h = { 'Access-Control-Allow-Origin' => credentials ? env['HTTP_ORIGIN'] : public_resource? ? '*' : env['HTTP_ORIGIN'],
169
+ h = {
170
+ 'Access-Control-Allow-Origin' => origin_for_response_header(env['HTTP_ORIGIN']),
156
171
  'Access-Control-Allow-Methods' => methods.collect{|m| m.to_s.upcase}.join(', '),
157
172
  'Access-Control-Expose-Headers' => expose.nil? ? '' : expose.join(', '),
158
173
  'Access-Control-Max-Age' => max_age.to_s }
@@ -165,6 +180,11 @@ module Rack
165
180
  @public_resource
166
181
  end
167
182
 
183
+ def origin_for_response_header(origin)
184
+ return '*' if public_resource? && !credentials
185
+ origin == 'file://' ? 'null' : origin
186
+ end
187
+
168
188
  def to_preflight_headers(env)
169
189
  h = to_headers(env)
170
190
  if env['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "rack-cors"
8
- s.version = "0.2.7"
8
+ s.version = "0.2.8"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Calvin Yu"]
12
- s.date = "2012-06-07"
12
+ s.date = "2013-05-31"
13
13
  s.description = "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: http://github.com/cyu/rack-cors"
14
14
  s.email = "me@sourcebender.com"
15
15
  s.extra_rdoc_files = [
@@ -31,7 +31,7 @@ Gem::Specification.new do |s|
31
31
  s.homepage = "http://github.com/cyu/rack-cors"
32
32
  s.licenses = ["MIT"]
33
33
  s.require_paths = ["lib"]
34
- s.rubygems_version = "1.8.24"
34
+ s.rubygems_version = "1.8.23"
35
35
  s.summary = "Middleware for enabling Cross-Origin Resource Sharing in Rack apps"
36
36
 
37
37
  if s.respond_to? :specification_version then
@@ -41,23 +41,26 @@ Gem::Specification.new do |s|
41
41
  s.add_runtime_dependency(%q<rack>, [">= 0"])
42
42
  s.add_development_dependency(%q<rake>, [">= 0"])
43
43
  s.add_development_dependency(%q<shoulda>, [">= 0"])
44
+ s.add_development_dependency(%q<mocha>, [">= 0"])
44
45
  s.add_development_dependency(%q<rack-test>, [">= 0"])
45
- s.add_development_dependency(%q<bundler>, ["~> 1.1.0"])
46
+ s.add_development_dependency(%q<bundler>, [">= 1.1.0"])
46
47
  s.add_development_dependency(%q<jeweler>, ["~> 1.8.3"])
47
48
  else
48
49
  s.add_dependency(%q<rack>, [">= 0"])
49
50
  s.add_dependency(%q<rake>, [">= 0"])
50
51
  s.add_dependency(%q<shoulda>, [">= 0"])
52
+ s.add_dependency(%q<mocha>, [">= 0"])
51
53
  s.add_dependency(%q<rack-test>, [">= 0"])
52
- s.add_dependency(%q<bundler>, ["~> 1.1.0"])
54
+ s.add_dependency(%q<bundler>, [">= 1.1.0"])
53
55
  s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
54
56
  end
55
57
  else
56
58
  s.add_dependency(%q<rack>, [">= 0"])
57
59
  s.add_dependency(%q<rake>, [">= 0"])
58
60
  s.add_dependency(%q<shoulda>, [">= 0"])
61
+ s.add_dependency(%q<mocha>, [">= 0"])
59
62
  s.add_dependency(%q<rack-test>, [">= 0"])
60
- s.add_dependency(%q<bundler>, ["~> 1.1.0"])
63
+ s.add_dependency(%q<bundler>, [">= 1.1.0"])
61
64
  s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
62
65
  end
63
66
  end
@@ -1,6 +1,8 @@
1
1
  require 'rubygems'
2
2
  require 'rack/test'
3
3
  require 'shoulda'
4
+ require 'mocha'
5
+ require 'rack/cors'
4
6
 
5
7
  Rack::Test::Session.class_eval do
6
8
  def options(uri, params = {}, env = {}, &block)
@@ -26,6 +28,10 @@ class CorsTest < Test::Unit::TestCase
26
28
  cors_request :origin => 'http://192.168.0.1:1234'
27
29
  end
28
30
 
31
+ should 'support proc origins configuration' do
32
+ cors_request '/proc-origin', :origin => 'http://10.10.10.10:3000'
33
+ end
34
+
29
35
  should 'support alternative X-Origin header' do
30
36
  header 'X-Origin', 'http://localhost:3000'
31
37
  get '/'
@@ -35,7 +41,6 @@ class CorsTest < Test::Unit::TestCase
35
41
  should 'support expose header configuration' do
36
42
  cors_request '/expose_single_header'
37
43
  assert_equal 'expose-test', last_response.headers['Access-Control-Expose-Headers']
38
-
39
44
  end
40
45
 
41
46
  should 'support expose multiple header configuration' do
@@ -57,6 +62,28 @@ class CorsTest < Test::Unit::TestCase
57
62
  assert_nil last_response.headers['Vary'], 'no expecting Vary header'
58
63
  end
59
64
 
65
+ should 'not log debug messages if debug option is false' do
66
+ app = mock
67
+ app.stubs(:call).returns(200, {}, [''])
68
+
69
+ logger = mock
70
+ logger.expects(:debug).never
71
+
72
+ cors = Rack::Cors.new(app, :debug => false, :logger => logger) {}
73
+ cors.send(:debug, {}, 'testing')
74
+ end
75
+
76
+ should 'log debug messages if debug option is true' do
77
+ app = mock
78
+ app.stubs(:call).returns(200, {}, [''])
79
+
80
+ logger = mock
81
+ logger.expects(:debug)
82
+
83
+ cors = Rack::Cors.new(app, :debug => true, :logger => logger) {}
84
+ cors.send(:debug, {}, 'testing')
85
+ end
86
+
60
87
  context 'preflight requests' do
61
88
  should 'fail if origin is invalid' do
62
89
  preflight_request('http://allyourdataarebelongtous.com', '/')
@@ -110,6 +137,12 @@ class CorsTest < Test::Unit::TestCase
110
137
  assert_equal '*', last_response.headers['Access-Control-Allow-Origin']
111
138
  end
112
139
 
140
+ should '"null" origin, allowed as "file://", returned as "null" in header' do
141
+ preflight_request('null', '/')
142
+ assert_cors_success
143
+ assert_equal 'null', last_response.headers['Access-Control-Allow-Origin']
144
+ end
145
+
113
146
  should 'return a Content-Type' do
114
147
  preflight_request('http://localhost:3000', '/')
115
148
  assert_cors_success
@@ -7,7 +7,10 @@ class DSLTest < Test::Unit::TestCase
7
7
  should 'support explicit config object dsl mode' do
8
8
  cors = Rack::Cors.new(Proc.new {}) do |cfg|
9
9
  cfg.allow do |allow|
10
- allow.origins 'localhost:3000', '127.0.0.1:3000'
10
+ allow.origins 'localhost:3000', '127.0.0.1:3000' do |source,env|
11
+ source == "http://10.10.10.10:3000" &&
12
+ env["USER_AGENT"] == "test-agent"
13
+ end
11
14
  allow.resource '/get-only', :methods => :get
12
15
  allow.resource '/', :headers => :any
13
16
  end
@@ -15,12 +18,19 @@ class DSLTest < Test::Unit::TestCase
15
18
  resources = cors.send :all_resources
16
19
  assert_equal 1, resources.length
17
20
  assert resources.first.allow_origin?('http://localhost:3000')
21
+
22
+ assert resources.first.allow_origin?('http://10.10.10.10:3000',{"USER_AGENT" => "test-agent" })
23
+ assert !resources.first.allow_origin?('http://10.10.10.10:3001',{"USER_AGENT" => "test-agent" })
24
+ assert !resources.first.allow_origin?('http://10.10.10.10:3000',{"USER_AGENT" => "other-agent"})
18
25
  end
19
26
 
20
27
  should 'support implicit config object dsl mode' do
21
28
  cors = Rack::Cors.new(Proc.new {}) do
22
29
  allow do
23
- origins 'localhost:3000', '127.0.0.1:3000'
30
+ origins 'localhost:3000', '127.0.0.1:3000' do |source,env|
31
+ source == "http://10.10.10.10:3000" &&
32
+ env["USER_AGENT"] == "test-agent"
33
+ end
24
34
  resource '/get-only', :methods => :get
25
35
  resource '/', :headers => :any
26
36
  end
@@ -28,5 +38,20 @@ class DSLTest < Test::Unit::TestCase
28
38
  resources = cors.send :all_resources
29
39
  assert_equal 1, resources.length
30
40
  assert resources.first.allow_origin?('http://localhost:3000')
41
+
42
+ assert resources.first.allow_origin?('http://10.10.10.10:3000',{"USER_AGENT" => "test-agent" })
43
+ assert !resources.first.allow_origin?('http://10.10.10.10:3001',{"USER_AGENT" => "test-agent" })
44
+ assert !resources.first.allow_origin?('http://10.10.10.10:3000',{"USER_AGENT" => "other-agent"})
45
+ end
46
+
47
+ should 'support "file://" origin' do
48
+ cors = Rack::Cors.new(Proc.new {}) do
49
+ allow do
50
+ origins 'file://'
51
+ resource '/', :headers => :any
52
+ end
53
+ end
54
+ resources = cors.send :all_resources
55
+ assert resources.first.allow_origin?('file://')
31
56
  end
32
- end
57
+ end
@@ -2,7 +2,7 @@ require 'rack/cors'
2
2
 
3
3
  use Rack::Cors do
4
4
  allow do
5
- origins 'localhost:3000', '127.0.0.1:3000', /http:\/\/192\.168\.0\.\d{1,3}(:\d+)?/
5
+ origins 'localhost:3000', '127.0.0.1:3000', /http:\/\/192\.168\.0\.\d{1,3}(:\d+)?/, 'file://'
6
6
 
7
7
  resource '/get-only', :methods => :get
8
8
  resource '/', :headers => :any
@@ -16,6 +16,13 @@ use Rack::Cors do
16
16
  # :max_age => 0
17
17
  end
18
18
 
19
+ allow do
20
+ origins do |source,env|
21
+ source.end_with?("10.10.10.10:3000")
22
+ end
23
+ resource '/proc-origin'
24
+ end
25
+
19
26
  allow do
20
27
  origins '*'
21
28
  resource '/public'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-cors
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.7
4
+ version: 0.2.8
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-07 00:00:00.000000000 Z
12
+ date: 2013-05-31 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rack
@@ -59,6 +59,22 @@ dependencies:
59
59
  - - ! '>='
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: mocha
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
62
78
  - !ruby/object:Gem::Dependency
63
79
  name: rack-test
64
80
  requirement: !ruby/object:Gem::Requirement
@@ -80,7 +96,7 @@ dependencies:
80
96
  requirement: !ruby/object:Gem::Requirement
81
97
  none: false
82
98
  requirements:
83
- - - ~>
99
+ - - ! '>='
84
100
  - !ruby/object:Gem::Version
85
101
  version: 1.1.0
86
102
  type: :development
@@ -88,7 +104,7 @@ dependencies:
88
104
  version_requirements: !ruby/object:Gem::Requirement
89
105
  none: false
90
106
  requirements:
91
- - - ~>
107
+ - - ! '>='
92
108
  - !ruby/object:Gem::Version
93
109
  version: 1.1.0
94
110
  - !ruby/object:Gem::Dependency
@@ -142,7 +158,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
142
158
  version: '0'
143
159
  segments:
144
160
  - 0
145
- hash: -4990705370164666
161
+ hash: -1437619420423070521
146
162
  required_rubygems_version: !ruby/object:Gem::Requirement
147
163
  none: false
148
164
  requirements:
@@ -151,7 +167,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
151
167
  version: '0'
152
168
  requirements: []
153
169
  rubyforge_project:
154
- rubygems_version: 1.8.24
170
+ rubygems_version: 1.8.23
155
171
  signing_key:
156
172
  specification_version: 3
157
173
  summary: Middleware for enabling Cross-Origin Resource Sharing in Rack apps