rack-cors-2.0.2/0000755000004100000410000000000014577710550013442 5ustar www-datawww-datarack-cors-2.0.2/rack-cors.gemspec0000644000004100000410000000447314577710550016703 0ustar www-datawww-data######################################################### # This file has been automatically generated by gem2tgz # ######################################################### # -*- encoding: utf-8 -*- # stub: rack-cors 2.0.2 ruby lib Gem::Specification.new do |s| s.name = "rack-cors".freeze s.version = "2.0.2" s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.require_paths = ["lib".freeze] s.authors = ["Calvin Yu".freeze] s.date = "2024-03-04" s.description = "Middleware that will make Rack-based apps CORS compatible. Fork the project here: https://github.com/cyu/rack-cors".freeze s.email = ["me@sourcebender.com".freeze] s.files = ["CHANGELOG.md".freeze, "LICENSE.txt".freeze, "README.md".freeze, "lib/rack/cors.rb".freeze, "lib/rack/cors/resource.rb".freeze, "lib/rack/cors/resources.rb".freeze, "lib/rack/cors/resources/cors_misconfiguration_error.rb".freeze, "lib/rack/cors/result.rb".freeze, "lib/rack/cors/version.rb".freeze] s.homepage = "https://github.com/cyu/rack-cors".freeze s.licenses = ["MIT".freeze] s.rubygems_version = "3.3.15".freeze s.summary = "Middleware for enabling Cross-Origin Resource Sharing in Rack apps".freeze if s.respond_to? :specification_version then s.specification_version = 4 end if s.respond_to? :add_runtime_dependency then s.add_development_dependency(%q.freeze, [">= 1.16.0", "< 3"]) s.add_development_dependency(%q.freeze, ["~> 5.11.0"]) s.add_development_dependency(%q.freeze, ["~> 1.6.0"]) s.add_development_dependency(%q.freeze, ["~> 0.12"]) s.add_runtime_dependency(%q.freeze, [">= 2.0.0"]) s.add_development_dependency(%q.freeze, [">= 1.1.0"]) s.add_development_dependency(%q.freeze, ["~> 12.3.0"]) s.add_development_dependency(%q.freeze, ["~> 0.80.1"]) else s.add_dependency(%q.freeze, [">= 1.16.0", "< 3"]) s.add_dependency(%q.freeze, ["~> 5.11.0"]) s.add_dependency(%q.freeze, ["~> 1.6.0"]) s.add_dependency(%q.freeze, ["~> 0.12"]) s.add_dependency(%q.freeze, [">= 2.0.0"]) s.add_dependency(%q.freeze, [">= 1.1.0"]) s.add_dependency(%q.freeze, ["~> 12.3.0"]) s.add_dependency(%q.freeze, ["~> 0.80.1"]) end end rack-cors-2.0.2/lib/0000755000004100000410000000000014577710550014210 5ustar www-datawww-datarack-cors-2.0.2/lib/rack/0000755000004100000410000000000014577710550015130 5ustar www-datawww-datarack-cors-2.0.2/lib/rack/cors/0000755000004100000410000000000014577710550016076 5ustar www-datawww-datarack-cors-2.0.2/lib/rack/cors/resource.rb0000644000004100000410000001077414577710550020263 0ustar www-datawww-data# frozen_string_literal: true module Rack class Cors class Resource # All CORS routes need to accept CORS simple headers at all times # {https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers} CORS_SIMPLE_HEADERS = %w[accept accept-language content-language content-type].freeze attr_accessor :path, :methods, :headers, :expose, :max_age, :credentials, :pattern, :if_proc, :vary_headers def initialize(public_resource, path, opts = {}) raise CorsMisconfigurationError if public_resource && opts[:credentials] == true self.path = path self.credentials = public_resource ? false : (opts[:credentials] == true) self.max_age = opts[:max_age] || 7200 self.pattern = compile(path) self.if_proc = opts[:if] self.vary_headers = opts[:vary] && [opts[:vary]].flatten @public_resource = public_resource self.headers = case opts[:headers] when :any then :any when nil then nil else [opts[:headers]].flatten.collect(&:downcase) end self.methods = case opts[:methods] when :any then %i[get head post put patch delete options] else ensure_enum(opts[:methods]) || [:get] end.map(&:to_s) self.expose = opts[:expose] ? [opts[:expose]].flatten : nil end def matches_path?(path) pattern =~ path end def match?(path, env) matches_path?(path) && (if_proc.nil? || if_proc.call(env)) end def process_preflight(env, result) headers = {} request_method = env[Rack::Cors::HTTP_ACCESS_CONTROL_REQUEST_METHOD] result.miss(Result::MISS_NO_METHOD) && (return headers) if request_method.nil? result.miss(Result::MISS_DENY_METHOD) && (return headers) unless methods.include?(request_method.downcase) request_headers = env[Rack::Cors::HTTP_ACCESS_CONTROL_REQUEST_HEADERS] result.miss(Result::MISS_DENY_HEADER) && (return headers) if request_headers && !allow_headers?(request_headers) result.hit = true headers.merge(to_preflight_headers(env)) end def to_headers(env) h = { 'access-control-allow-origin' => origin_for_response_header(env[Rack::Cors::HTTP_ORIGIN]), 'access-control-allow-methods' => methods.collect { |m| m.to_s.upcase }.join(', '), 'access-control-expose-headers' => expose.nil? ? '' : expose.join(', '), 'access-control-max-age' => max_age.to_s } h['access-control-allow-credentials'] = 'true' if credentials header_proc.call(h) end protected def public_resource? @public_resource end def origin_for_response_header(origin) return '*' if public_resource? origin end def to_preflight_headers(env) h = to_headers(env) h.merge!('access-control-allow-headers' => env[Rack::Cors::HTTP_ACCESS_CONTROL_REQUEST_HEADERS]) if env[Rack::Cors::HTTP_ACCESS_CONTROL_REQUEST_HEADERS] h end def allow_headers?(request_headers) headers = self.headers || [] return true if headers == :any request_headers = request_headers.split(/,\s*/) if request_headers.is_a?(String) request_headers.all? do |header| header = header.downcase CORS_SIMPLE_HEADERS.include?(header) || headers.include?(header) end end def ensure_enum(var) return nil if var.nil? [var].flatten end def compile(path) if path.respond_to? :to_str special_chars = %w[. + ( ) $] pattern = path.to_str.gsub(%r{((:\w+)|/\*|[\*#{special_chars.join}])}) do |match| case match when '/*' '\\/?(.*?)' when '*' '(.*?)' when *special_chars Regexp.escape(match) else '([^/?&#]+)' end end /^#{pattern}$/ elsif path.respond_to? :match path else raise TypeError, path end end def header_proc @header_proc ||= begin if defined?(Rack::Headers) ->(h) { h } else ->(h) { Rack::Utils::HeaderHash.new(h) } end end end end end end rack-cors-2.0.2/lib/rack/cors/resources.rb0000644000004100000410000000263314577710550020441 0ustar www-datawww-data# frozen_string_literal: true require_relative 'resources/cors_misconfiguration_error' module Rack class Cors class Resources attr_reader :resources def initialize @origins = [] @resources = [] @public_resources = false end def origins(*args, &blk) @origins = args.flatten.reject { |s| s == '' }.map do |n| case n when Proc, Regexp, %r{^[a-z][a-z0-9.+-]*://} n when '*' @public_resources = true n else Regexp.compile("^[a-z][a-z0-9.+-]*:\\\/\\\/#{Regexp.quote(n)}$") end end.flatten @origins.push(blk) if blk end def resource(path, opts = {}) @resources << Resource.new(public_resources?, path, opts) end def public_resources? @public_resources end def allow_origin?(source, env = {}) return true if public_resources? !!@origins.detect do |origin| if origin.is_a?(Proc) origin.call(source, env) elsif origin.is_a?(Regexp) source =~ origin else source == origin end end end def match_resource(path, env) @resources.detect { |r| r.match?(path, env) } end def resource_for_path(path) @resources.detect { |r| r.matches_path?(path) } end end end end rack-cors-2.0.2/lib/rack/cors/resources/0000755000004100000410000000000014577710550020110 5ustar www-datawww-datarack-cors-2.0.2/lib/rack/cors/resources/cors_misconfiguration_error.rb0000644000004100000410000000056114577710550026256 0ustar www-datawww-data# frozen_string_literal: true module Rack class Cors class Resource class CorsMisconfigurationError < StandardError def message 'Allowing credentials for wildcard origins is insecure.' \ " Please specify more restrictive origins or set 'credentials' to false in your CORS configuration." end end end end end rack-cors-2.0.2/lib/rack/cors/version.rb0000644000004100000410000000013014577710550020102 0ustar www-datawww-data# frozen_string_literal: true module Rack class Cors VERSION = '2.0.2' end end rack-cors-2.0.2/lib/rack/cors/result.rb0000644000004100000410000000262014577710550017741 0ustar www-datawww-data# frozen_string_literal: true module Rack class Cors class Result HEADER_KEY = 'x-rack-cors' MISS_NO_ORIGIN = 'no-origin' MISS_NO_PATH = 'no-path' MISS_NO_METHOD = 'no-method' MISS_DENY_METHOD = 'deny-method' MISS_DENY_HEADER = 'deny-header' attr_accessor :preflight, :hit, :miss_reason def hit? !!hit end def preflight? !!preflight end def miss(reason) self.hit = false self.miss_reason = reason end def self.hit(env) r = Result.new r.preflight = false r.hit = true env[Rack::Cors::ENV_KEY] = r end def self.miss(env, reason) r = Result.new r.preflight = false r.hit = false r.miss_reason = reason env[Rack::Cors::ENV_KEY] = r end def self.preflight(env) r = Result.new r.preflight = true env[Rack::Cors::ENV_KEY] = r end def append_header(headers) headers[HEADER_KEY] = if hit? preflight? ? 'preflight-hit' : 'hit' else [ (preflight? ? 'preflight-miss' : 'miss'), miss_reason ].join('; ') end end end end end rack-cors-2.0.2/lib/rack/cors.rb0000644000004100000410000001326014577710550016425 0ustar www-datawww-data# frozen_string_literal: true require 'logger' require_relative 'cors/resources' require_relative 'cors/resource' require_relative 'cors/result' require_relative 'cors/version' module Rack class Cors HTTP_ORIGIN = 'HTTP_ORIGIN' HTTP_X_ORIGIN = 'HTTP_X_ORIGIN' HTTP_ACCESS_CONTROL_REQUEST_METHOD = 'HTTP_ACCESS_CONTROL_REQUEST_METHOD' HTTP_ACCESS_CONTROL_REQUEST_HEADERS = 'HTTP_ACCESS_CONTROL_REQUEST_HEADERS' PATH_INFO = 'PATH_INFO' REQUEST_METHOD = 'REQUEST_METHOD' RACK_LOGGER = 'rack.logger' RACK_CORS = # retaining the old key for backwards compatibility ENV_KEY = 'rack.cors' OPTIONS = 'OPTIONS' DEFAULT_VARY_HEADERS = ['Origin'].freeze def initialize(app, opts = {}, &block) @app = app @debug_mode = !!opts[:debug] @logger = @logger_proc = nil logger = opts[:logger] if logger if logger.respond_to? :call @logger_proc = opts[:logger] else @logger = logger end end return unless block_given? if block.arity == 1 block.call(self) else instance_eval(&block) end end def debug? @debug_mode end def allow(&block) all_resources << (resources = Resources.new) if block.arity == 1 block.call(resources) else resources.instance_eval(&block) end end def call(env) env[HTTP_ORIGIN] ||= env[HTTP_X_ORIGIN] if env[HTTP_X_ORIGIN] path = evaluate_path(env) add_headers = nil if env[HTTP_ORIGIN] debug(env) do ['Incoming Headers:', " Origin: #{env[HTTP_ORIGIN]}", " Path-Info: #{path}", " Access-Control-Request-Method: #{env[HTTP_ACCESS_CONTROL_REQUEST_METHOD]}", " Access-Control-Request-Headers: #{env[HTTP_ACCESS_CONTROL_REQUEST_HEADERS]}"].join("\n") end if env[REQUEST_METHOD] == OPTIONS && env[HTTP_ACCESS_CONTROL_REQUEST_METHOD] return [400, {}, []] unless Rack::Utils.valid_path?(path) headers = process_preflight(env, path) debug(env) do "Preflight Headers:\n" + headers.collect { |kv| " #{kv.join(': ')}" }.join("\n") end return [200, headers, []] else add_headers = process_cors(env, path) end else Result.miss(env, Result::MISS_NO_ORIGIN) end # This call must be done BEFORE calling the app because for some reason # env[PATH_INFO] gets changed after that and it won't match. (At least # in rails 4.1.6) vary_resource = resource_for_path(path) status, headers, body = @app.call env if add_headers headers = add_headers.merge(headers) debug(env) do add_headers.each_pair do |key, value| headers["x-rack-cors-original-#{key}"] = value if headers.key?(key) end end end # Vary header should ALWAYS mention Origin if there's ANY chance for the # response to be different depending on the Origin header value. # Better explained here: http://www.fastly.com/blog/best-practices-for-using-the-vary-header/ if vary_resource vary = headers['vary'] cors_vary_headers = if vary_resource.vary_headers&.any? vary_resource.vary_headers else DEFAULT_VARY_HEADERS end headers['vary'] = ((vary ? [vary].flatten.map { |v| v.split(/,\s*/) }.flatten : []) + cors_vary_headers).uniq.join(', ') end result = env[ENV_KEY] result.append_header(headers) if debug? && result [status, headers, body] end protected def debug(env, message = nil, &block) (@logger || select_logger(env)).debug(message, &block) if debug? end def select_logger(env) @logger = if @logger_proc logger_proc = @logger_proc @logger_proc = nil logger_proc.call elsif defined?(Rails) && Rails.respond_to?(:logger) && Rails.logger Rails.logger elsif env[RACK_LOGGER] env[RACK_LOGGER] else ::Logger.new(STDOUT).tap { |logger| logger.level = ::Logger::Severity::DEBUG } end end def evaluate_path(env) path = env[PATH_INFO] if path path = Rack::Utils.unescape_path(path) path = Rack::Utils.clean_path_info(path) if Rack::Utils.valid_path?(path) end path end def all_resources @all_resources ||= [] end def process_preflight(env, path) result = Result.preflight(env) resource, error = match_resource(path, env) unless resource result.miss(error) return {} end resource.process_preflight(env, result) end def process_cors(env, path) resource, error = match_resource(path, env) if resource Result.hit(env) cors = resource.to_headers(env) cors else Result.miss(env, error) nil end end def resource_for_path(path_info) all_resources.each do |r| found = r.resource_for_path(path_info) return found if found end nil end def match_resource(path, env) origin = env[HTTP_ORIGIN] origin_matched = false all_resources.each do |r| next unless r.allow_origin?(origin, env) origin_matched = true found = r.match_resource(path, env) return [found, nil] if found end [nil, origin_matched ? Result::MISS_NO_PATH : Result::MISS_NO_ORIGIN] end end end rack-cors-2.0.2/LICENSE.txt0000644000004100000410000000205214577710550015264 0ustar www-datawww-dataCopyright (c) 2013 Calvin Yu MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. rack-cors-2.0.2/README.md0000644000004100000410000002011514577710550014720 0ustar www-datawww-data# Rack CORS Middleware [![Build Status](https://github.com/cyu/rack-cors/actions/workflows/ci.yaml/badge.svg)](https://github.com/cyu/rack-cors/actions) `Rack::Cors` provides support for Cross-Origin Resource Sharing (CORS) for Rack compatible web applications. 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) ## Installation Install the gem: `gem install rack-cors` Or in your Gemfile: ```ruby gem 'rack-cors' ``` ## Configuration ### Rails Configuration 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: ```ruby # config/initializers/cors.rb Rails.application.config.middleware.insert_before 0, Rack::Cors do allow do origins '*' resource '*', headers: :any, methods: [:get, :post, :patch, :put] end end ``` NOTE: If you create application with `--api` option, configuration is automatically generated in `config/initializers/cors.rb`. 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. 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). Read more about it here in the [Rails Guides](https://guides.rubyonrails.org/configuring.html#configuring-middleware) ### Rack Configuration NOTE: If you're running Rails, adding `config/initializers/cors.rb` should be enough. There is no need to update `config.ru` as well. In `config.ru`, configure `Rack::Cors` by passing a block to the `use` command: ```ruby use Rack::Cors do allow do origins 'localhost:3000', '127.0.0.1:3000', /\Ahttp:\/\/192\.168\.0\.\d{1,3}(:\d+)?\z/ # regular expressions can be used here resource '/file/list_all/', :headers => 'x-domain-token' resource '/file/at/*', methods: [:get, :post, :delete, :put, :patch, :options, :head], headers: 'x-domain-token', expose: ['Some-Custom-Response-Header'], max_age: 600 # headers to expose end allow do origins '*' resource '/public/*', headers: :any, methods: :get # Only allow a request for a specific host resource '/api/v1/*', headers: :any, methods: :get, if: proc { |env| env['HTTP_HOST'] == 'api.example.com' } end end ``` ### Configuration Reference #### Middleware Options * **debug** (boolean): Enables debug logging and `X-Rack-CORS` HTTP headers for debugging. * **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 initially configured, like `Rails.logger`. #### Origin Origins can be specified as a string, a regular expression, or as '\*' to allow all origins. **\*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`. Additionally, origins can be specified dynamically via a block of the following form: ```ruby origins { |source, env| true || false } ``` 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: * **methods** (string or array or `:any`): The HTTP methods allowed for the resource. * **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. * **expose** (string or array): The HTTP headers in the resource response can be exposed to the client. * **credentials** (boolean, default: `false`): Sets the `Access-Control-Allow-Credentials` response header. **Note:** If a wildcard (`*`) origin is specified, this option cannot be set to `true`. Read this [security article](http://web-in-security.blogspot.de/2017/07/cors-misconfigurations-on-large-scale.html) for more information. * **max_age** (number): Sets the `Access-Control-Max-Age` response header. * **if** (Proc): If the result of the proc is true, will process the request as a valid CORS request. * **vary** (string or array): A list of HTTP headers to add to the 'Vary' header. ## Common Gotchas ### Origin Matching When specifying an origin, make sure that it does not have a trailing slash. ### Testing Postman and/or cURL * 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. * Make sure your origin does not have a trailing slash. ### Positioning in the Middleware Stack 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. Here are some scenarios where incorrect positioning have created issues: * **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. * **Caching in the middleware.** Insert before `Rack::Cache` so that the proper CORS headers are written and not cached ones. * **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. You can run the following command to see what the middleware stack looks like: ```bash bundle exec rake middleware ``` 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: ```bash RAILS_ENV=production bundle exec rake middleware ``` ### Serving static files 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). In Heroku, you can serve static assets through the Rails container by setting `config.serve_static_assets = true` in `production.rb`. ### Custom Protocols (chrome-extension://, ionic://, etc.) 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 has a custom protocol (`chrome-extension://`, `ionic://`, etc.) simply exclude the protocol. [See issue.](https://github.com/cyu/rack-cors/issues/100) For example, instead of specifying `chrome-extension://aomjjhallfgjeglblehebfpbcfeobpga` specify `aomjjhallfgjeglblehebfpbcfeobpga` in `origins`. As of 2.0.0 (currently in RC1), you can specify origins with a custom protocol. ### Rails 6 Host Matching Rails 6 will block requests from unauthorized hosts, and this issue can be confused as a CORS related error. So in development, if you're making requests using something other than localhost or 127.0.0.1, make sure the server host has been authorized. [More info here](https://guides.rubyonrails.org/configuring.html#actiondispatch-hostauthorization) rack-cors-2.0.2/CHANGELOG.md0000644000004100000410000000600314577710550015252 0ustar www-datawww-data# Change Log All notable changes to this project will be documented in this file. ## 2.0.2 - 2024-03-04 ### Changed - Fix file permission issues with 2.0.1 release ## 2.0.1 - 2023-02-17 ### Changed - Use Rack::Utils::HeaderHash when Rack 2.x is detected ## 2.0.0 - 2023-02-14 ### Changed - Refactored codebase - Support declaring custom protocols in origin - Lowercased header names as defined by Rack spec - Fix issue with duplicate headers because of header name case ## 1.1.1 - 2019-12-29 ### Changed - Allow //* to match // and / paths ## 1.1.0 - 2019-11-19 ### Changed - Use Rack::Utils.escape_path instead of Rack::Utils.escape - Require Rack 2.0 for escape_path method - Don't try to clean path if invalid. - Return 400 (Bad Request) on preflights with invalid path ## 1.0.6 - 2019-11-14 ### Changed - Use Rack::Utils.escape to make compat with Rack 1.6.0 ## 1.0.5 - 2019-11-14 ### Changed - Update Gem spec to require rack >= 1.6.0 ## 1.0.4 - 2019-11-13 ### Security - Escape and resolve path before evaluating resource rules (thanks to Colby Morgan) ## 1.0.3 - 2019-03-24 ### Changed - Don't send 'Content-Type' header with pre-flight requests - Allow ruby array for vary header config ## 1.0.2 - 2017-10-22 ### Fixed - Automatically allow simple headers when headers are set ## 1.0.1 - 2017-07-18 ### Fixed - Allow lambda origin configuration ## 1.0.0 - 2017-07-15 ### Security - Don't implicitly accept 'null' origins when 'file://' is specified (https://github.com/cyu/rack-cors/pull/134) - Ignore '' origins (https://github.com/cyu/rack-cors/issues/139) - Default credentials option on resources to false (https://github.com/cyu/rack-cors/issues/95) - Don't allow credentials option to be true if '*' is specified is origin (https://github.com/cyu/rack-cors/pull/142) - Don't reflect Origin header when '*' is specified as origin (https://github.com/cyu/rack-cors/pull/142) ### Fixed - Don't respond immediately on non-matching preflight requests instead of sending them through the app (https://github.com/cyu/rack-cors/pull/106) ## 0.4.1 - 2017-02-01 ### Fixed - Return miss result in X-Rack-CORS instead of incorrectly returning preflight-hit ## 0.4.0 - 2015-04-15 ### Changed - Don't set HTTP_ORIGIN with HTTP_X_ORIGIN if nil ### Added - Calculate vary headers for non-CORS resources - Support custom vary headers for resource - Support :if option for resource - Support :any as a possible value for :methods option ### Fixed - Don't symbolize incoming HTTP request methods ## 0.3.1 - 2014-12-27 ### Changed - Changed the env key to rack.cors to avoid Rack::Lint warnings ## 0.3.0 - 2014-10-19 ### Added - Added support for defining a logger with a Proc - Return a X-Rack-CORS header when in debug mode detailing how Rack::Cors processed a request - Added support for non HTTP/HTTPS origins when just a domain is specified ### Changed - Changed the log level of the fallback logger to DEBUG - Print warning when attempting to use :any as an allowed method - Treat incoming `Origin: null` headers as file://