Skip to content

Commit 7832b4c

Browse files
nicolasalexandre9jeffladiray
authored andcommitted
feat(cors): add access control allow private network handling (#554)
1 parent a838fa8 commit 7832b4c

File tree

4 files changed

+93
-0
lines changed

4 files changed

+93
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
/test/dummy/db/*.sqlite3
1212
/spec/dummy/log/
1313
/spec/dummy/db/*.sqlite3
14+
/spec/dummy/tmp/
1415
/tmp/
1516
.byebug_history
1617

lib/forest_liana/engine.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,21 @@
88
require_relative 'bootstrapper'
99
require_relative 'collection'
1010

11+
module Rack
12+
class Cors
13+
class Resource
14+
def to_preflight_headers(env)
15+
h = to_headers(env)
16+
h['Access-Control-Allow-Private-Network'] = 'true' if env['HTTP_ACCESS_CONTROL_REQUEST_PRIVATE_NETWORK'] == 'true'
17+
if env[HTTP_ACCESS_CONTROL_REQUEST_HEADERS]
18+
h.merge!('Access-Control-Allow-Headers' => env[HTTP_ACCESS_CONTROL_REQUEST_HEADERS])
19+
end
20+
h
21+
end
22+
end
23+
end
24+
end
25+
1126
module ForestLiana
1227
class Engine < ::Rails::Engine
1328
isolate_namespace ForestLiana

spec/requests/cors_spec.rb

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
require 'rails_helper'
2+
require 'rack/test'
3+
require 'rack/cors'
4+
5+
class CaptureResult
6+
def initialize(app, options = {})
7+
@app = app
8+
@result_holder = options[:holder]
9+
end
10+
11+
def call(env)
12+
env['HTTP_ACCESS_CONTROL_REQUEST_PRIVATE_NETWORK'] = 'true'
13+
response = @app.call(env)
14+
@result_holder.cors_result = env[Rack::Cors::RACK_CORS]
15+
response
16+
end
17+
end
18+
19+
describe Rack::Cors do
20+
21+
include Rack::Test::Methods
22+
23+
attr_accessor :cors_result
24+
25+
def load_app(name, options = {})
26+
test = self
27+
Rack::Builder.new do
28+
use CaptureResult, holder: test
29+
eval File.read(File.dirname(__FILE__) + "/#{name}.ru")
30+
use FakeProxy if options[:proxy]
31+
map('/') do
32+
run(lambda do |_env|
33+
[
34+
200,
35+
{
36+
'Content-Type' => 'text/html',
37+
},
38+
['success']
39+
]
40+
end)
41+
end
42+
end
43+
end
44+
45+
let(:app) { load_app('test') }
46+
47+
describe 'preflight requests' do
48+
it 'should allow private network' do
49+
preflight_request('http://localhost:3000', '/')
50+
assert !last_response.headers['Access-Control-Allow-Private-Network'].nil?
51+
assert last_response.headers['Access-Control-Allow-Private-Network'] == 'true'
52+
end
53+
end
54+
55+
protected
56+
57+
def preflight_request(origin, path, opts = {})
58+
header 'Origin', origin
59+
unless opts.key?(:method) && opts[:method].nil?
60+
header 'Access-Control-Request-Method', opts[:method] ? opts[:method].to_s.upcase : 'GET'
61+
end
62+
header 'Access-Control-Request-Headers', opts[:headers] if opts[:headers]
63+
options path
64+
end
65+
end

spec/requests/test.ru

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
require 'rack/cors'
2+
3+
use Rack::Lint
4+
use Rack::Cors do
5+
allow do
6+
origins 'localhost:3000',
7+
'127.0.0.1:3000'
8+
9+
resource '/', headers: :any, methods: :any
10+
resource '/options', methods: :options
11+
end
12+
end

0 commit comments

Comments
 (0)