rack-cors 1.1.1 → 2.0.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8f879bc8ea95eac0ca9360c3a553084961d02944255f6ad380b64e855653b8b6
4
- data.tar.gz: bd9478603340a1785324ab4f1db9517a8943fdcc1be13193e4d6b83b184fa032
3
+ metadata.gz: f47b5b2ba34721795ddb1c65e70e989134655e7f47116dd977edee702a79f41f
4
+ data.tar.gz: 7c03dc701b00b7418ab4d733872fccc3522392f0f85014b8ca25045767d866a9
5
5
  SHA512:
6
- metadata.gz: 12d13e99acef13b159595487b3c0198bc1a355371bdb149241d11e1d0715148e0749085d0f0c362d4defdec2e325b416b1e93aeb28be2d421516d4db8185fdac
7
- data.tar.gz: a1f373194a95094f337c545e7751eac2c4d8500dfd607088a88e55774b755fa0ec659710319a2f7997e579231b7de806e63f2ce4a1639cdb732eed5bcbb743b9
6
+ metadata.gz: d5a94b8f282fd5367e125f4b49e18ce5fb1c07581d89b2d50dc8cf4eb70e8404d97c78a6ccaf90f1e41f0f220bb09ff9dd07a4677559935cc35256674e6c512d
7
+ data.tar.gz: bee187e2dc53281d8b454df32b6a8fd50e05b66de4f25649d74f176abf29d52eb4cee5a2b2e602e087c5f5805b6dd55ab86a9e0692d3d82c5538e0c30e3c020b
@@ -0,0 +1,39 @@
1
+ name: ci
2
+
3
+ on:
4
+ - push
5
+ - pull_request
6
+
7
+ jobs:
8
+ test:
9
+ strategy:
10
+ fail-fast: false
11
+ matrix:
12
+ ruby:
13
+ - "2.3"
14
+ - "2.4"
15
+ - "2.5"
16
+ - "2.6"
17
+ - "2.7"
18
+ - "3.0"
19
+ - "3.1"
20
+ - "3.2"
21
+ - truffleruby-head
22
+ runs-on: ubuntu-latest
23
+ steps:
24
+ - uses: actions/checkout@v3
25
+ - uses: ruby/setup-ruby@v1
26
+ with:
27
+ ruby-version: ${{ matrix.ruby }}
28
+ bundler-cache: true
29
+ - run: bundle exec rake test
30
+
31
+ rubocop:
32
+ runs-on: ubuntu-latest
33
+ steps:
34
+ - uses: actions/checkout@v3
35
+ - uses: ruby/setup-ruby@v1
36
+ with:
37
+ ruby-version: 3.2.1
38
+ bundler-cache: true
39
+ - run: bundle exec rubocop
data/.rubocop.yml ADDED
@@ -0,0 +1,31 @@
1
+ ---
2
+ AllCops:
3
+ Exclude:
4
+ - "examples/**/*"
5
+ - "vendor/**/*"
6
+
7
+ # Disables
8
+ Layout/LineLength:
9
+ Enabled: false
10
+ Style/Documentation:
11
+ Enabled: false
12
+ Metrics/ClassLength:
13
+ Enabled: false
14
+ Metrics/MethodLength:
15
+ Enabled: false
16
+ Metrics/BlockLength:
17
+ Enabled: false
18
+ Style/HashEachMethods:
19
+ Enabled: false
20
+ Style/HashTransformKeys:
21
+ Enabled: false
22
+ Style/HashTransformValues:
23
+ Enabled: false
24
+ Style/DoubleNegation:
25
+ Enabled: false
26
+ Metrics/CyclomaticComplexity:
27
+ Enabled: false
28
+ Metrics/PerceivedComplexity:
29
+ Enabled: false
30
+ Metrics/AbcSize:
31
+ Enabled: false
data/CHANGELOG.md CHANGED
@@ -1,6 +1,17 @@
1
1
  # Change Log
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ ## 2.0.1 - 2023-02-17
5
+ ### Changed
6
+ - Use Rack::Utils::HeaderHash when Rack 2.x is detected
7
+
8
+ ## 2.0.0 - 2023-02-14
9
+ ### Changed
10
+ - Refactored codebase
11
+ - Support declaring custom protocols in origin
12
+ - Lowercased header names as defined by Rack spec
13
+ - Fix issue with duplicate headers because of header name case
14
+
4
15
  ## 1.1.1 - 2019-12-29
5
16
  ### Changed
6
17
  - Allow /<resource>/* to match /<resource>/ and /<resource> paths
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in rack-cors.gemspec
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
- # Rack CORS Middleware [![Build Status](https://travis-ci.org/cyu/rack-cors.svg?branch=master)](https://travis-ci.org/cyu/rack-cors)
1
+ # Rack CORS Middleware [![Build Status](https://github.com/cyu/rack-cors/actions/workflows/ci.yaml/badge.svg)](https://github.com/cyu/rack-cors/actions)
2
2
 
3
3
  `Rack::Cors` provides support for Cross-Origin Resource Sharing (CORS) for Rack compatible web applications.
4
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/)
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 [further explanations on MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS)
6
6
 
7
7
  ## Installation
8
8
 
@@ -20,41 +20,36 @@ gem 'rack-cors'
20
20
  ## Configuration
21
21
 
22
22
  ### Rails Configuration
23
- 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.
23
+ For Rails, you'll need to add this middleware on application startup. A practical way to do this is with an initializer file. For example, the following will allow GET, POST, PATCH, or PUT requests from any origin on any resource:
24
24
 
25
25
  ```ruby
26
- module YourApp
27
- class Application < Rails::Application
28
- # ...
29
-
30
- # Rails 5
31
-
32
- config.middleware.insert_before 0, Rack::Cors do
33
- allow do
34
- origins '*'
35
- resource '*', headers: :any, methods: [:get, :post, :options]
36
- end
37
- end
38
-
39
- # Rails 3/4
40
-
41
- config.middleware.insert_before 0, "Rack::Cors" do
42
- allow do
43
- origins '*'
44
- resource '*', headers: :any, methods: [:get, :post, :options]
45
- end
46
- end
26
+ # config/initializers/cors.rb
27
+
28
+ Rails.application.config.middleware.insert_before 0, Rack::Cors do
29
+ allow do
30
+ origins '*'
31
+ resource '*', headers: :any, methods: [:get, :post, :patch, :put]
47
32
  end
48
33
  end
49
34
  ```
50
35
 
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).
36
+ NOTE: If you create application with `--api` option, configuration automatically generate in `config/initializers/cors.rb`.
37
+
38
+ 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). Basic setup examples for Rails 5 & Rails 6 can be found in the examples/ directory.
52
39
 
53
40
  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).
54
41
 
42
+ *Note about Rails 6*: Rails 6 has support for blocking requests from unknown hosts, so origin domains will need to be added there as well.
43
+
44
+ ```ruby
45
+ Rails.application.config.hosts << "product.com"
46
+ ```
47
+
48
+ Read more about it here in the [Rails Guides](https://guides.rubyonrails.org/configuring.html#configuring-middleware)
49
+
55
50
  ### Rack Configuration
56
51
 
57
- NOTE: If you're running Rails, updating in `config/application.rb` should be enough. There is no need to update `config.ru` as well.
52
+ NOTE: If you're running Rails, adding `config/initializers/cors.rb` should be enough. There is no need to update `config.ru` as well.
58
53
 
59
54
  In `config.ru`, configure `Rack::Cors` by passing a block to the `use` command:
60
55
 
@@ -96,14 +91,14 @@ end
96
91
  #### Origin
97
92
  Origins can be specified as a string, a regular expression, or as '\*' to allow all origins.
98
93
 
99
- **\*SECURITY NOTE:** Be careful when using regular expressions to not accidentally be too inclusive. For example, the expression `/https:\/\/example\.com/` will match the domain *example.com.randomdomainname.co.uk*. It is recommended that any regular expression be enclosed with start & end string anchors (`\A\z`).
94
+ **\*SECURITY NOTE:** Be careful when using regular expressions to not accidentally be too inclusive. For example, the expression `/https:\/\/example\.com/` will match the domain *example.com.randomdomainname.co.uk*. It is recommended that any regular expression be enclosed with start & end string anchors, like `\Ahttps:\/\/example\.com\z`.
100
95
 
101
96
  Additionally, origins can be specified dynamically via a block of the following form:
102
97
  ```ruby
103
98
  origins { |source, env| true || false }
104
99
  ```
105
100
 
106
- A Resource path can be specified as exact string match (`/path/to/file.txt`) or with a '\*' wildcard (`/all/files/in/*`). To include all of a directory's files and the files in its subdirectories, use this form: `/assets/**/*`. A resource can take the following options:
101
+ A Resource path can be specified as exact string match (`/path/to/file.txt`) or with a '\*' wildcard (`/all/files/in/*`). A resource can take the following options:
107
102
 
108
103
  * **methods** (string or array or `:any`): The HTTP methods allowed for the resource.
109
104
  * **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.
@@ -116,24 +111,50 @@ A Resource path can be specified as exact string match (`/path/to/file.txt`) or
116
111
 
117
112
  ## Common Gotchas
118
113
 
119
- 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.
114
+ ### Origin Matching
115
+
116
+ When specifying an origin, make sure that it does not have a trailing slash.
117
+
118
+ ### Testing Postman and/or cURL
120
119
 
121
- Here are some common cases:
120
+ * Make sure you're passing in an `Origin:` header. That header is required to trigger a CORS response. Here's [a good SO post](https://stackoverflow.com/questions/12173990/how-can-you-debug-a-cors-request-with-curl) about using cURL for testing CORS.
121
+ * Make sure your origin does not have a trailing slash.
122
122
 
123
- * **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.
123
+ ### Positioning in the Middleware Stack
124
124
 
125
- * **Caching in the middleware.** Insert this middleware before `Rack::Cache` so that the proper CORS headers are written and not cached ones.
125
+ Positioning of `Rack::Cors` in the middleware stack is very important. In the Rails example above we put it above all other middleware which, in our experience, provides the most consistent results.
126
126
 
127
- * **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`.
127
+ Here are some scenarios where incorrect positioning have created issues:
128
128
 
129
- To determine where to put the CORS middleware in the Rack stack, run the following command:
129
+ * **Serving static files.** Insert before `ActionDispatch::Static` so that static files are served with the proper CORS headers. **NOTE:** this might not work in production as static files are usually served from the web server (Nginx, Apache) and not the Rails container.
130
+
131
+ * **Caching in the middleware.** Insert before `Rack::Cache` so that the proper CORS headers are written and not cached ones.
132
+
133
+ * **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.
134
+
135
+ You can run the following command to see what the middleware stack looks like:
130
136
 
131
137
  ```bash
132
138
  bundle exec rake middleware
133
139
  ```
134
140
 
135
- 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:
141
+ Note that the middleware stack is different in production. For example, the `ActionDispatch::Static` middleware will not be part of the stack if `config.serve_static_assets = false`. You can run this to see what your middleware stack looks like in production:
136
142
 
137
143
  ```bash
138
144
  RAILS_ENV=production bundle exec rake middleware
139
145
  ```
146
+
147
+ ### Serving static files
148
+
149
+ If you trying to serve CORS headers on static assets (like CSS, JS, Font files), keep in mind that static files are usually served directly from web servers and never runs through the Rails container (including the middleware stack where `Rack::Cors` resides).
150
+
151
+ In Heroku, you can serve static assets through the Rails container by setting `config.serve_static_assets = true` in `production.rb`.
152
+
153
+ ### Custom Protocols (chrome-extension://, ionic://, etc.)
154
+
155
+ Prior to 2.0.0, `http://`, `https://`, and `file://` are the only protocols supported in the `origins` list. If you wish to specify an origin that
156
+ has a custom protocol (`chrome-extension://`, `ionic://`, etc.) simply exclude the protocol. [See issue.](https://github.com/cyu/rack-cors/issues/100)
157
+
158
+ For example, instead of specifying `chrome-extension://aomjjhallfgjeglblehebfpbcfeobpga` specify `aomjjhallfgjeglblehebfpbcfeobpga` in `origins`.
159
+
160
+ As of 2.0.0 (currently in RC1), you can specify origins with a custom protocol.
data/Rakefile CHANGED
@@ -1,4 +1,6 @@
1
- require "bundler/gem_tasks"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
2
4
 
3
5
  require 'rake/testtask'
4
6
  Rake::TestTask.new(:test) do |test|
@@ -7,15 +9,14 @@ Rake::TestTask.new(:test) do |test|
7
9
  test.verbose = true
8
10
  end
9
11
 
10
- task :default => :test
12
+ task default: :test
11
13
 
12
14
  require 'rdoc/task'
13
15
  Rake::RDocTask.new do |rdoc|
14
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
16
+ version = File.exist?('VERSION') ? File.read('VERSION') : ''
15
17
 
16
18
  rdoc.rdoc_dir = 'rdoc'
17
19
  rdoc.title = "rack-cors #{version}"
18
20
  rdoc.rdoc_files.include('README*')
19
21
  rdoc.rdoc_files.include('lib/**/*.rb')
20
22
  end
21
-
@@ -0,0 +1,142 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rack
4
+ class Cors
5
+ class Resource
6
+ # All CORS routes need to accept CORS simple headers at all times
7
+ # {https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers}
8
+ CORS_SIMPLE_HEADERS = %w[accept accept-language content-language content-type].freeze
9
+
10
+ attr_accessor :path, :methods, :headers, :expose, :max_age, :credentials, :pattern, :if_proc, :vary_headers
11
+
12
+ def initialize(public_resource, path, opts = {})
13
+ raise CorsMisconfigurationError if public_resource && opts[:credentials] == true
14
+
15
+ self.path = path
16
+ self.credentials = public_resource ? false : (opts[:credentials] == true)
17
+ self.max_age = opts[:max_age] || 7200
18
+ self.pattern = compile(path)
19
+ self.if_proc = opts[:if]
20
+ self.vary_headers = opts[:vary] && [opts[:vary]].flatten
21
+ @public_resource = public_resource
22
+
23
+ self.headers = case opts[:headers]
24
+ when :any then :any
25
+ when nil then nil
26
+ else
27
+ [opts[:headers]].flatten.collect(&:downcase)
28
+ end
29
+
30
+ self.methods = case opts[:methods]
31
+ when :any then %i[get head post put patch delete options]
32
+ else
33
+ ensure_enum(opts[:methods]) || [:get]
34
+ end.map(&:to_s)
35
+
36
+ self.expose = opts[:expose] ? [opts[:expose]].flatten : nil
37
+ end
38
+
39
+ def matches_path?(path)
40
+ pattern =~ path
41
+ end
42
+
43
+ def match?(path, env)
44
+ matches_path?(path) && (if_proc.nil? || if_proc.call(env))
45
+ end
46
+
47
+ def process_preflight(env, result)
48
+ headers = {}
49
+
50
+ request_method = env[Rack::Cors::HTTP_ACCESS_CONTROL_REQUEST_METHOD]
51
+ result.miss(Result::MISS_NO_METHOD) && (return headers) if request_method.nil?
52
+ result.miss(Result::MISS_DENY_METHOD) && (return headers) unless methods.include?(request_method.downcase)
53
+
54
+ request_headers = env[Rack::Cors::HTTP_ACCESS_CONTROL_REQUEST_HEADERS]
55
+ result.miss(Result::MISS_DENY_HEADER) && (return headers) if request_headers && !allow_headers?(request_headers)
56
+
57
+ result.hit = true
58
+ headers.merge(to_preflight_headers(env))
59
+ end
60
+
61
+ def to_headers(env)
62
+ h = {
63
+ 'access-control-allow-origin' => origin_for_response_header(env[Rack::Cors::HTTP_ORIGIN]),
64
+ 'access-control-allow-methods' => methods.collect { |m| m.to_s.upcase }.join(', '),
65
+ 'access-control-expose-headers' => expose.nil? ? '' : expose.join(', '),
66
+ 'access-control-max-age' => max_age.to_s
67
+ }
68
+ h['access-control-allow-credentials'] = 'true' if credentials
69
+ header_proc.call(h)
70
+ end
71
+
72
+ protected
73
+
74
+ def public_resource?
75
+ @public_resource
76
+ end
77
+
78
+ def origin_for_response_header(origin)
79
+ return '*' if public_resource?
80
+
81
+ origin
82
+ end
83
+
84
+ def to_preflight_headers(env)
85
+ h = to_headers(env)
86
+ h.merge!('access-control-allow-headers' => env[Rack::Cors::HTTP_ACCESS_CONTROL_REQUEST_HEADERS]) if env[Rack::Cors::HTTP_ACCESS_CONTROL_REQUEST_HEADERS]
87
+ h
88
+ end
89
+
90
+ def allow_headers?(request_headers)
91
+ headers = self.headers || []
92
+ return true if headers == :any
93
+
94
+ request_headers = request_headers.split(/,\s*/) if request_headers.is_a?(String)
95
+ request_headers.all? do |header|
96
+ header = header.downcase
97
+ CORS_SIMPLE_HEADERS.include?(header) || headers.include?(header)
98
+ end
99
+ end
100
+
101
+ def ensure_enum(var)
102
+ return nil if var.nil?
103
+
104
+ [var].flatten
105
+ end
106
+
107
+ def compile(path)
108
+ if path.respond_to? :to_str
109
+ special_chars = %w[. + ( )]
110
+ pattern =
111
+ path.to_str.gsub(%r{((:\w+)|/\*|[\*#{special_chars.join}])}) do |match|
112
+ case match
113
+ when '/*'
114
+ '\\/?(.*?)'
115
+ when '*'
116
+ '(.*?)'
117
+ when *special_chars
118
+ Regexp.escape(match)
119
+ else
120
+ '([^/?&#]+)'
121
+ end
122
+ end
123
+ /^#{pattern}$/
124
+ elsif path.respond_to? :match
125
+ path
126
+ else
127
+ raise TypeError, path
128
+ end
129
+ end
130
+
131
+ def header_proc
132
+ @header_proc ||= begin
133
+ if defined?(Rack::Headers)
134
+ ->(h) { h }
135
+ else
136
+ ->(h) { Rack::Utils::HeaderHash.new(h) }
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rack
4
+ class Cors
5
+ class Resource
6
+ class CorsMisconfigurationError < StandardError
7
+ def message
8
+ 'Allowing credentials for wildcard origins is insecure.' \
9
+ " Please specify more restrictive origins or set 'credentials' to false in your CORS configuration."
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'resources/cors_misconfiguration_error'
4
+
5
+ module Rack
6
+ class Cors
7
+ class Resources
8
+ attr_reader :resources
9
+
10
+ def initialize
11
+ @origins = []
12
+ @resources = []
13
+ @public_resources = false
14
+ end
15
+
16
+ def origins(*args, &blk)
17
+ @origins = args.flatten.reject { |s| s == '' }.map do |n|
18
+ case n
19
+ when Proc, Regexp, %r{^[a-z][a-z0-9.+-]*://}
20
+ n
21
+ when '*'
22
+ @public_resources = true
23
+ n
24
+ else
25
+ Regexp.compile("^[a-z][a-z0-9.+-]*:\\\/\\\/#{Regexp.quote(n)}$")
26
+ end
27
+ end.flatten
28
+ @origins.push(blk) if blk
29
+ end
30
+
31
+ def resource(path, opts = {})
32
+ @resources << Resource.new(public_resources?, path, opts)
33
+ end
34
+
35
+ def public_resources?
36
+ @public_resources
37
+ end
38
+
39
+ def allow_origin?(source, env = {})
40
+ return true if public_resources?
41
+
42
+ !!@origins.detect do |origin|
43
+ if origin.is_a?(Proc)
44
+ origin.call(source, env)
45
+ elsif origin.is_a?(Regexp)
46
+ source =~ origin
47
+ else
48
+ source == origin
49
+ end
50
+ end
51
+ end
52
+
53
+ def match_resource(path, env)
54
+ @resources.detect { |r| r.match?(path, env) }
55
+ end
56
+
57
+ def resource_for_path(path)
58
+ @resources.detect { |r| r.matches_path?(path) }
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rack
4
+ class Cors
5
+ class Result
6
+ HEADER_KEY = 'x-rack-cors'
7
+
8
+ MISS_NO_ORIGIN = 'no-origin'
9
+ MISS_NO_PATH = 'no-path'
10
+
11
+ MISS_NO_METHOD = 'no-method'
12
+ MISS_DENY_METHOD = 'deny-method'
13
+ MISS_DENY_HEADER = 'deny-header'
14
+
15
+ attr_accessor :preflight, :hit, :miss_reason
16
+
17
+ def hit?
18
+ !!hit
19
+ end
20
+
21
+ def preflight?
22
+ !!preflight
23
+ end
24
+
25
+ def miss(reason)
26
+ self.hit = false
27
+ self.miss_reason = reason
28
+ end
29
+
30
+ def self.hit(env)
31
+ r = Result.new
32
+ r.preflight = false
33
+ r.hit = true
34
+ env[Rack::Cors::ENV_KEY] = r
35
+ end
36
+
37
+ def self.miss(env, reason)
38
+ r = Result.new
39
+ r.preflight = false
40
+ r.hit = false
41
+ r.miss_reason = reason
42
+ env[Rack::Cors::ENV_KEY] = r
43
+ end
44
+
45
+ def self.preflight(env)
46
+ r = Result.new
47
+ r.preflight = true
48
+ env[Rack::Cors::ENV_KEY] = r
49
+ end
50
+
51
+ def append_header(headers)
52
+ headers[HEADER_KEY] = if hit?
53
+ preflight? ? 'preflight-hit' : 'hit'
54
+ else
55
+ [
56
+ (preflight? ? 'preflight-miss' : 'miss'),
57
+ miss_reason
58
+ ].join('; ')
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rack
2
4
  class Cors
3
- VERSION = "1.1.1"
5
+ VERSION = '2.0.1'
4
6
  end
5
7
  end