forked from darron/cors.io
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconfig.ru
111 lines (91 loc) · 3.46 KB
/
config.ru
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
require "bundler"
Bundler.setup
Bundler.require
module Rack
class CorsPrefetch
def cors_headers(env)
host = env['HTTP_ORIGIN']
if env['Access-Control-Request-Headers']
headers = env['Access-Control-Request-Headers']
else
default_headers = 'Accept, Accept-Charset, Accept-Encoding, Accept-Language, Authorization, Content-Length, Content-Type, Host, Origin, Proxy-Connection, Referer, User-Agent, X-Requested-With, X-Redmine-API-Key'
custom_headers = env.keys.select{ |k| k =~ /^HTTP_X_/ }.map { |k| k.downcase.gsub(/_/, '-').gsub(/^http-/, '') }.join ', '
headers = [default_headers, custom_headers].compact.join ', '
end
puts 'env'
puts env.inspect
headers = {
'Access-Control-Allow-Methods' => 'POST, GET, PUT, PATCH, DELETE',
'Access-Control-Max-Age' => '86400', # 24 hours
'Access-Control-Allow-Headers' => headers,
# 'Access-Control-Allow-Headers' => ,
'Access-Control-Allow-Credentials' => 'true',
'Access-Control-Allow-Origin' => host
}
puts headers.inspect
headers
end
FORCED_SSL_MSG = "CORS requests only allowed via https://"
def initialize(app)
@app = app
# @force_ssl = true
end
def call(env)
force_ssl(env) || process_preflight(env) || process_cors(env) || process_failed(env)
end
private
def force_ssl(env)
return if !@force_ssl || ssl_request?(env)
log("NonSSL", env)
[403, {'Content-Type' => 'text/plain'}, [FORCED_SSL_MSG]]
end
def process_preflight(env)
return unless env['HTTP_ORIGIN'] && env['HTTP_ACCESS_CONTROL_REQUEST_METHOD'] && env['REQUEST_METHOD'] == 'OPTIONS'
log("Preflight", env)
[204, cors_headers(env), []]
end
def process_cors(env)
log("Cors", env)
status, headers, body = @app.call(env)
env['rack.errors'].write "status: #{status}\n"
headers.each do |key, val|
env['rack.errors'].write "#{key}: #{val}\n"
end
env['rack.errors'].write "\n#{body.inspect}\n\n"
[status, headers.merge(cors_headers(env)), body]
end
def process_failed(env)
log("Failed", env)
[404, {'Content-Type' => 'text/plain'}, []]
end
# Fixed in rack >= 1.3
def ssl_request?(env)
if env['HTTPS'] == 'on'
'https'
elsif env['HTTP_X_FORWARDED_PROTO']
env['HTTP_X_FORWARDED_PROTO'].split(',')[0]
else
env['rack.url_scheme']
end == 'https'
end
def log(kind, env)
logger = @logger || env['rack.errors']
logger.write(
"#{kind} request #{env['REQUEST_PATH']} \n" +
"origin: #{env['HTTP_ORIGIN']} \n" +
"referer: #{env['HTTP_REFERER']} \n" +
"authorization: #{env["HTTP_AUTHORIZATION"]} \n" +
"method: #{env['REQUEST_METHOD']} \n\n"
)
end
end
end
use Rack::CorsPrefetch
use Rack::StreamingProxy do |request|
# inside the request block, return the full URI to redirect the request to,
# or nil/false if the request should continue on down the middleware stack.
protocol, host, path = request.url.scan(/^(https?):\/\/[^\/]+\/([^\/]+)(.*)/).flatten
puts "redirecting to #{protocol}://#{host}#{path}"
"#{protocol}://#{host}#{path}"
end
run proc{|env| [200, {"Content-Type" => "text/plain"}, ""] }