rack-cors 0.2.7 → 0.2.8

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.
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