rack-cors 1.0.2 → 1.0.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 7a4d5e6683440676f486ce61b3c16ff2e7c8f65e
4
- data.tar.gz: be95c0c3dce56c965aff4b1cb398f2ad6fb4f6b3
2
+ SHA256:
3
+ metadata.gz: 4545ac1af54d2749c6f78b031efef78c2d8ec7cb7f5395d64bd79ee4dbd953fc
4
+ data.tar.gz: 9fac4069c1fdc45c1cbfae5a4cd8cafd83a27533f4f1557b9ff773158343aa57
5
5
  SHA512:
6
- metadata.gz: 8ae27dfd82bd822e700c476963118b15e68dee7850aaccb8b43a05670903f9f66217c8cd77dcf425f664581ecadf00eb43c1c1926648d97caf07c6d4a4dd0574
7
- data.tar.gz: df278b2f1b3e6f0b01305d601fb58f2d41aef0579232d5ae27564be76483afdfb58b9219708d5a944c7db293025d7bacec4924dc63c06aefed2a7df4ad00e9ec
6
+ metadata.gz: 8752bb4af30efe706487939b2daaa8a5189dafac69935d75d5359273f72bf2260a60570d769695675c69efda9b9ccd86e2cddfe01e6bfff504216cfdb42f856c
7
+ data.tar.gz: 3bb3628b7b1d7a4cc25651be3dac3848d60e433a7887911a263cae258a619cb30446aa46be2cde278a7ca5176feceeb2f3dbf7394764c1dc4a34737ae58ec6eb
@@ -1,6 +1,7 @@
1
1
  language: ruby
2
2
  sudo: false
3
3
  rvm:
4
- - 2.2.5
5
- - 2.3.0
6
- - 2.3.1
4
+ - 2.2
5
+ - 2.3
6
+ - 2.4
7
+ - 2.5
@@ -1,6 +1,15 @@
1
1
  # Change Log
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ ## 1.0.3 - 2019-03-24
5
+ ### Changed
6
+ - Don't send 'Content-Type' header with pre-flight requests
7
+ - Allow ruby array for vary header config
8
+
9
+ ## 1.0.2 - 2017-10-22
10
+ ### Fixed
11
+ - Automatically allow simple headers when headers are set
12
+
4
13
  ## 1.0.1 - 2017-07-18
5
14
  ### Fixed
6
15
  - Allow lambda origin configuration
data/Gemfile CHANGED
@@ -3,4 +3,4 @@ source 'https://rubygems.org'
3
3
  # Specify your gem's dependencies in rack-cors.gemspec
4
4
  gemspec
5
5
 
6
- gem 'pry-byebug'
6
+ gem 'pry-byebug', '~> 3.6.0'
data/README.md CHANGED
@@ -13,7 +13,7 @@ Install the gem:
13
13
  Or in your Gemfile:
14
14
 
15
15
  ```ruby
16
- gem 'rack-cors', :require => 'rack/cors'
16
+ gem 'rack-cors'
17
17
  ```
18
18
 
19
19
 
@@ -25,7 +25,6 @@ Put something like the code below in `config/application.rb` of your Rails appli
25
25
  ```ruby
26
26
  module YourApp
27
27
  class Application < Rails::Application
28
-
29
28
  # ...
30
29
 
31
30
  # Rails 5
@@ -33,7 +32,7 @@ module YourApp
33
32
  config.middleware.insert_before 0, Rack::Cors do
34
33
  allow do
35
34
  origins '*'
36
- resource '*', :headers => :any, :methods => [:get, :post, :options]
35
+ resource '*', headers: :any, methods: [:get, :post, :options]
37
36
  end
38
37
  end
39
38
 
@@ -42,15 +41,14 @@ module YourApp
42
41
  config.middleware.insert_before 0, "Rack::Cors" do
43
42
  allow do
44
43
  origins '*'
45
- resource '*', :headers => :any, :methods => [:get, :post, :options]
44
+ resource '*', headers: :any, methods: [:get, :post, :options]
46
45
  end
47
46
  end
48
-
49
47
  end
50
48
  end
51
49
  ```
52
50
 
53
- We use `insert_before` to make sure `Rack::Cors` runs at the beginning of the stack to make sure it isn't interfered with with other middleware (see `Rack::Cache` note in **Common Gotchas** section). Check out the [rails 4 example](https://github.com/cyu/rack-cors/tree/master/examples/rails4) and [rails 3 example](https://github.com/cyu/rack-cors/tree/master/examples/rails3).
51
+ We use `insert_before` to make sure `Rack::Cors` runs at the beginning of the stack to make sure it isn't interfered with by other middleware (see `Rack::Cache` note in **Common Gotchas** section). Check out the [rails 4 example](https://github.com/cyu/rack-cors/tree/master/examples/rails4) and [rails 3 example](https://github.com/cyu/rack-cors/tree/master/examples/rails3).
54
52
 
55
53
  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).
56
54
 
@@ -69,16 +67,22 @@ use Rack::Cors do
69
67
 
70
68
  resource '/file/list_all/', :headers => 'x-domain-token'
71
69
  resource '/file/at/*',
72
- :methods => [:get, :post, :delete, :put, :patch, :options, :head],
73
- :headers => 'x-domain-token',
74
- :expose => ['Some-Custom-Response-Header'],
75
- :max_age => 600
70
+ methods: [:get, :post, :delete, :put, :patch, :options, :head],
71
+ headers: 'x-domain-token',
72
+ expose: ['Some-Custom-Response-Header'],
73
+ max_age: 600
76
74
  # headers to expose
77
75
  end
78
76
 
79
77
  allow do
80
78
  origins '*'
81
- resource '/public/*', :headers => :any, :methods => :get
79
+ resource '/public/*', headers: :any, methods: :get
80
+
81
+ # Only allow a request for a specific host
82
+ resource '/api/v1/*',
83
+ headers: :any,
84
+ methods: :get,
85
+ if: proc { |env| env['HTTP_HOST'] == 'api.example.com' }
82
86
  end
83
87
  end
84
88
  ```
@@ -16,10 +16,8 @@ module Rack
16
16
  # retaining the old key for backwards compatibility
17
17
  ENV_KEY = 'rack.cors'.freeze
18
18
 
19
- OPTIONS = 'OPTIONS'.freeze
20
- VARY = 'Vary'.freeze
21
- CONTENT_TYPE = 'Content-Type'.freeze
22
- TEXT_PLAIN = 'text/plain'.freeze
19
+ OPTIONS = 'OPTIONS'.freeze
20
+ VARY = 'Vary'.freeze
23
21
 
24
22
  DEFAULT_VARY_HEADERS = ['Origin'].freeze
25
23
 
@@ -117,7 +115,7 @@ module Rack
117
115
  else
118
116
  DEFAULT_VARY_HEADERS
119
117
  end
120
- headers[VARY] = ((vary ? vary.split(/,\s*/) : []) + cors_vary_headers).uniq.join(', ')
118
+ headers[VARY] = ((vary ? ([vary].flatten.map { |v| v.split(/,\s*/) }.flatten) : []) + cors_vary_headers).uniq.join(', ')
121
119
  end
122
120
 
123
121
  if debug? && result = env[RACK_CORS]
@@ -363,7 +361,7 @@ module Rack
363
361
  end
364
362
 
365
363
  def process_preflight(env, result)
366
- headers = {CONTENT_TYPE => TEXT_PLAIN}
364
+ headers = {}
367
365
 
368
366
  request_method = env[HTTP_ACCESS_CONTROL_REQUEST_METHOD]
369
367
  if request_method.nil?
@@ -1,5 +1,5 @@
1
1
  module Rack
2
2
  class Cors
3
- VERSION = "1.0.2"
3
+ VERSION = "1.0.3"
4
4
  end
5
5
  end
@@ -8,7 +8,7 @@ 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: https://github.com/cyu/rack-cors}
11
+ spec.description = %q{Middleware that will make Rack-based apps CORS compatible. 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
13
  spec.homepage = "https://github.com/cyu/rack-cors"
14
14
  spec.license = "MIT"
@@ -18,9 +18,9 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_development_dependency "bundler", "~> 1.3"
22
- spec.add_development_dependency "rake"
23
- spec.add_development_dependency "minitest", ">= 5.3.0"
24
- spec.add_development_dependency "mocha", ">= 0.14.0"
25
- spec.add_development_dependency "rack-test", ">= 0"
21
+ spec.add_development_dependency "bundler", ">= 1.16.0", '< 3'
22
+ spec.add_development_dependency "rake", "~> 12.3.0"
23
+ spec.add_development_dependency "minitest", "~> 5.11.0"
24
+ spec.add_development_dependency "mocha", "~> 1.6.0"
25
+ spec.add_development_dependency "rack-test", "~> 1.1.0"
26
26
  end
@@ -12,6 +12,11 @@ describe 'CORS', ->
12
12
  expect(data).to.eql('Hello world')
13
13
  done()
14
14
 
15
+ it 'should allow PATCH access to dynamic resource', (done) ->
16
+ $.ajax("http://#{CORS_SERVER}/", type: 'PATCH').done (data, textStatus, jqXHR) ->
17
+ expect(data).to.eql('Hello world')
18
+ done()
19
+
15
20
  it 'should allow HEAD access to dynamic resource', (done) ->
16
21
  $.ajax("http://#{CORS_SERVER}/", type: 'HEAD').done (data, textStatus, jqXHR) ->
17
22
  expect(jqXHR.status).to.eql(200)
@@ -1,4 +1,4 @@
1
- // Generated by CoffeeScript 1.12.6
1
+ // Generated by CoffeeScript 2.3.1
2
2
  (function() {
3
3
  var CORS_SERVER;
4
4
 
@@ -6,21 +6,29 @@
6
6
 
7
7
  describe('CORS', function() {
8
8
  it('should allow access to dynamic resource', function(done) {
9
- return $.get("http://" + CORS_SERVER + "/", function(data, status, xhr) {
9
+ return $.get(`http://${CORS_SERVER}/`, function(data, status, xhr) {
10
10
  expect(data).to.eql('Hello world');
11
11
  return done();
12
12
  });
13
13
  });
14
14
  it('should allow PUT access to dynamic resource', function(done) {
15
- return $.ajax("http://" + CORS_SERVER + "/", {
15
+ return $.ajax(`http://${CORS_SERVER}/`, {
16
16
  type: 'PUT'
17
17
  }).done(function(data, textStatus, jqXHR) {
18
18
  expect(data).to.eql('Hello world');
19
19
  return done();
20
20
  });
21
21
  });
22
+ it('should allow PATCH access to dynamic resource', function(done) {
23
+ return $.ajax(`http://${CORS_SERVER}/`, {
24
+ type: 'PATCH'
25
+ }).done(function(data, textStatus, jqXHR) {
26
+ expect(data).to.eql('Hello world');
27
+ return done();
28
+ });
29
+ });
22
30
  it('should allow HEAD access to dynamic resource', function(done) {
23
- return $.ajax("http://" + CORS_SERVER + "/", {
31
+ return $.ajax(`http://${CORS_SERVER}/`, {
24
32
  type: 'HEAD'
25
33
  }).done(function(data, textStatus, jqXHR) {
26
34
  expect(jqXHR.status).to.eql(200);
@@ -28,7 +36,7 @@
28
36
  });
29
37
  });
30
38
  it('should allow DELETE access to dynamic resource', function(done) {
31
- return $.ajax("http://" + CORS_SERVER + "/", {
39
+ return $.ajax(`http://${CORS_SERVER}/`, {
32
40
  type: 'DELETE'
33
41
  }).done(function(data, textStatus, jqXHR) {
34
42
  expect(data).to.eql('Hello world');
@@ -36,7 +44,7 @@
36
44
  });
37
45
  });
38
46
  it('should allow OPTIONS access to dynamic resource', function(done) {
39
- return $.ajax("http://" + CORS_SERVER + "/", {
47
+ return $.ajax(`http://${CORS_SERVER}/`, {
40
48
  type: 'OPTIONS'
41
49
  }).done(function(data, textStatus, jqXHR) {
42
50
  expect(jqXHR.status).to.eql(200);
@@ -44,7 +52,7 @@
44
52
  });
45
53
  });
46
54
  it('should allow access to static resource', function(done) {
47
- return $.get("http://" + CORS_SERVER + "/static.txt", function(data, status, xhr) {
55
+ return $.get(`http://${CORS_SERVER}/static.txt`, function(data, status, xhr) {
48
56
  expect($.trim(data)).to.eql("hello world");
49
57
  return done();
50
58
  });
@@ -52,7 +60,7 @@
52
60
  return it('should allow post resource', function(done) {
53
61
  return $.ajax({
54
62
  type: 'POST',
55
- url: "http://" + CORS_SERVER + "/cors",
63
+ url: `http://${CORS_SERVER}/cors`,
56
64
  beforeSend: function(xhr) {
57
65
  return xhr.setRequestHeader('X-Requested-With', 'XMLHTTPRequest');
58
66
  },
@@ -19,11 +19,11 @@ end
19
19
 
20
20
  module MiniTest::Assertions
21
21
  def assert_cors_success(response)
22
- assert !response.headers['Access-Control-Allow-Origin'].nil?, "Expected a successful CORS response"
22
+ assert !response.headers['Access-Control-Allow-Origin'].nil?, "Expected a successful CORS response"
23
23
  end
24
24
 
25
25
  def assert_not_cors_success(response)
26
- assert response.headers['Access-Control-Allow-Origin'].nil?, "Expected a failed CORS response"
26
+ assert response.headers['Access-Control-Allow-Origin'].nil?, "Expected a failed CORS response"
27
27
  end
28
28
  end
29
29
 
@@ -40,6 +40,18 @@ class CaptureResult
40
40
  end
41
41
  end
42
42
 
43
+ class FakeProxy
44
+ def initialize(app, options = {})
45
+ @app = app
46
+ end
47
+
48
+ def call(env)
49
+ status, headers, body = @app.call(env)
50
+ headers['Vary'] = %w(Origin User-Agent)
51
+ [status, headers, body]
52
+ end
53
+ end
54
+
43
55
  Rack::MockResponse.infect_an_assertion :assert_cors_success, :must_render_cors_success, :only_one_argument
44
56
  Rack::MockResponse.infect_an_assertion :assert_not_cors_success, :wont_render_cors_success, :only_one_argument
45
57
 
@@ -48,11 +60,12 @@ describe Rack::Cors do
48
60
 
49
61
  attr_accessor :cors_result
50
62
 
51
- def load_app(name)
63
+ def load_app(name, options = {})
52
64
  test = self
53
65
  Rack::Builder.new do
54
66
  use CaptureResult, :holder => test
55
67
  eval File.read(File.dirname(__FILE__) + "/#{name}.ru")
68
+ use FakeProxy if options[:proxy]
56
69
  map('/') do
57
70
  run proc { |env|
58
71
  [200, {'Content-Type' => 'text/html'}, ['success']]
@@ -133,6 +146,15 @@ describe Rack::Cors do
133
146
  last_response.headers['Vary'].must_equal 'Origin, Host'
134
147
  end
135
148
 
149
+ describe 'with array of upstream Vary headers' do
150
+ let(:app) { load_app('test', { proxy: true }) }
151
+
152
+ it 'should add to them' do
153
+ successful_cors_request '/vary_test'
154
+ last_response.headers['Vary'].must_equal 'Origin, User-Agent, Host'
155
+ end
156
+ end
157
+
136
158
  it 'should add Vary header if Access-Control-Allow-Origin header was added and if it is specific' do
137
159
  successful_cors_request '/', :origin => "http://192.168.0.3:8080"
138
160
  last_response.headers['Access-Control-Allow-Origin'].must_equal 'http://192.168.0.3:8080'
@@ -244,6 +266,19 @@ describe Rack::Cors do
244
266
  cors.call({'HTTP_ORIGIN' => 'test.com'})
245
267
  end
246
268
  end
269
+
270
+ it 'should use Logger if none is set' do
271
+ app = mock
272
+ app.stubs(:call).returns([200, {}, ['']])
273
+
274
+ logger = mock
275
+ Logger.expects(:new).returns(logger)
276
+ logger.expects(:tap).returns(logger)
277
+ logger.expects(:debug)
278
+
279
+ cors = Rack::Cors.new(app, :debug => true) {}
280
+ cors.call({'HTTP_ORIGIN' => 'test.com'})
281
+ end
247
282
  end
248
283
 
249
284
  describe 'preflight requests' do
@@ -280,6 +315,11 @@ describe Rack::Cors do
280
315
  last_response.must_render_cors_success
281
316
  end
282
317
 
318
+ it 'allows PATCH method' do
319
+ preflight_request('http://localhost:3000', '/', :methods => [ :patch ])
320
+ last_response.must_render_cors_success
321
+ end
322
+
283
323
  it 'should allow header case insensitive match' do
284
324
  preflight_request('http://localhost:3000', '/single_header', :headers => 'X-Domain-Token')
285
325
  last_response.must_render_cors_success
@@ -313,12 +353,6 @@ describe Rack::Cors do
313
353
  last_response.headers['Access-Control-Allow-Origin'].must_equal 'file://'
314
354
  end
315
355
 
316
- it 'should return a Content-Type' do
317
- preflight_request('http://localhost:3000', '/')
318
- last_response.must_render_cors_success
319
- last_response.headers['Content-Type'].wont_be_nil
320
- end
321
-
322
356
  describe '' do
323
357
 
324
358
  let(:app) do
@@ -332,7 +366,7 @@ describe Rack::Cors do
332
366
  end
333
367
  end
334
368
  map('/') do
335
- run ->(env) { [500, {'Content-Type' => 'text/plain'}, ['FAIL!']] }
369
+ run ->(env) { [500, {}, ['FAIL!']] }
336
370
  end
337
371
  end
338
372
  end
@@ -389,7 +423,7 @@ describe Rack::Cors do
389
423
  end
390
424
  end
391
425
  map('/') do
392
- run ->(env) { [200, {'Content-Type' => 'text/plain', 'Access-Control-Allow-Origin' => 'http://foo.net'}, ['success']] }
426
+ run ->(env) { [200, {'Access-Control-Allow-Origin' => 'http://foo.net'}, ['success']] }
393
427
  end
394
428
  end
395
429
  end
@@ -19,6 +19,7 @@ use Rack::Cors do
19
19
  resource '/expose_multiple_headers', :expose => %w{expose-test-1 expose-test-2}
20
20
  resource '/conditional', :methods => :get, :if => proc { |env| !!env['HTTP_X_OK'] }
21
21
  resource '/vary_test', :methods => :get, :vary => %w{ Origin Host }
22
+ resource '/patch_test', :methods => :patch
22
23
  # resource '/file/at/*',
23
24
  # :methods => [:get, :post, :put, :delete],
24
25
  # :headers => :any,
metadata CHANGED
@@ -1,87 +1,92 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-cors
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Calvin Yu
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-22 00:00:00.000000000 Z
11
+ date: 2019-03-25 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
+ - !ruby/object:Gem::Version
19
+ version: 1.16.0
20
+ - - "<"
18
21
  - !ruby/object:Gem::Version
19
- version: '1.3'
22
+ version: '3'
20
23
  type: :development
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
- - - "~>"
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 1.16.0
30
+ - - "<"
25
31
  - !ruby/object:Gem::Version
26
- version: '1.3'
32
+ version: '3'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: rake
29
35
  requirement: !ruby/object:Gem::Requirement
30
36
  requirements:
31
- - - ">="
37
+ - - "~>"
32
38
  - !ruby/object:Gem::Version
33
- version: '0'
39
+ version: 12.3.0
34
40
  type: :development
35
41
  prerelease: false
36
42
  version_requirements: !ruby/object:Gem::Requirement
37
43
  requirements:
38
- - - ">="
44
+ - - "~>"
39
45
  - !ruby/object:Gem::Version
40
- version: '0'
46
+ version: 12.3.0
41
47
  - !ruby/object:Gem::Dependency
42
48
  name: minitest
43
49
  requirement: !ruby/object:Gem::Requirement
44
50
  requirements:
45
- - - ">="
51
+ - - "~>"
46
52
  - !ruby/object:Gem::Version
47
- version: 5.3.0
53
+ version: 5.11.0
48
54
  type: :development
49
55
  prerelease: false
50
56
  version_requirements: !ruby/object:Gem::Requirement
51
57
  requirements:
52
- - - ">="
58
+ - - "~>"
53
59
  - !ruby/object:Gem::Version
54
- version: 5.3.0
60
+ version: 5.11.0
55
61
  - !ruby/object:Gem::Dependency
56
62
  name: mocha
57
63
  requirement: !ruby/object:Gem::Requirement
58
64
  requirements:
59
- - - ">="
65
+ - - "~>"
60
66
  - !ruby/object:Gem::Version
61
- version: 0.14.0
67
+ version: 1.6.0
62
68
  type: :development
63
69
  prerelease: false
64
70
  version_requirements: !ruby/object:Gem::Requirement
65
71
  requirements:
66
- - - ">="
72
+ - - "~>"
67
73
  - !ruby/object:Gem::Version
68
- version: 0.14.0
74
+ version: 1.6.0
69
75
  - !ruby/object:Gem::Dependency
70
76
  name: rack-test
71
77
  requirement: !ruby/object:Gem::Requirement
72
78
  requirements:
73
- - - ">="
79
+ - - "~>"
74
80
  - !ruby/object:Gem::Version
75
- version: '0'
81
+ version: 1.1.0
76
82
  type: :development
77
83
  prerelease: false
78
84
  version_requirements: !ruby/object:Gem::Requirement
79
85
  requirements:
80
- - - ">="
86
+ - - "~>"
81
87
  - !ruby/object:Gem::Version
82
- version: '0'
83
- description: 'Middleware that will make Rack-based apps CORS compatible. Read more
84
- here: http://blog.sourcebender.com/2010/06/09/introducin-rack-cors.html. Fork the
88
+ version: 1.1.0
89
+ description: 'Middleware that will make Rack-based apps CORS compatible. Fork the
85
90
  project here: https://github.com/cyu/rack-cors'
86
91
  email:
87
92
  - me@sourcebender.com
@@ -90,7 +95,7 @@ extensions: []
90
95
  extra_rdoc_files: []
91
96
  files:
92
97
  - ".travis.yml"
93
- - CHANGELOG
98
+ - CHANGELOG.md
94
99
  - Gemfile
95
100
  - LICENSE.txt
96
101
  - README.md
@@ -129,7 +134,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
129
134
  version: '0'
130
135
  requirements: []
131
136
  rubyforge_project:
132
- rubygems_version: 2.5.2
137
+ rubygems_version: 2.7.6
133
138
  signing_key:
134
139
  specification_version: 4
135
140
  summary: Middleware for enabling Cross-Origin Resource Sharing in Rack apps