rack-cors 0.1.0
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.
- data/Rakefile +12 -0
- data/VERSION +1 -0
- data/lib/rack/cors.rb +130 -0
- metadata +64 -0
data/Rakefile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
begin
|
2
|
+
require 'jeweler'
|
3
|
+
Jeweler::Tasks.new do |gemspec|
|
4
|
+
gemspec.name = "rack-cors"
|
5
|
+
gemspec.summary = "Middleware for enabling Cross-Origin Resource Sharing in Rack apps"
|
6
|
+
gemspec.email = "csyu77@gmail.com"
|
7
|
+
gemspec.homepage = "http://github.com/cyu/rack-cors"
|
8
|
+
gemspec.authors = ["Calvin Yu"]
|
9
|
+
end
|
10
|
+
rescue LoadError
|
11
|
+
puts "Jeweler not available. Install it with: gem install jeweler"
|
12
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/lib/rack/cors.rb
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
module Rack
|
2
|
+
class Cors
|
3
|
+
|
4
|
+
def initialize(app)
|
5
|
+
@app = app
|
6
|
+
yield self if block_given?
|
7
|
+
end
|
8
|
+
|
9
|
+
def allow
|
10
|
+
all_resources << (resources = Resources.new)
|
11
|
+
yield resources
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(env)
|
15
|
+
cors_headers = nil
|
16
|
+
if env['HTTP_ORIGIN']
|
17
|
+
if env['REQUEST_METHOD'] == 'OPTIONS'
|
18
|
+
headers = process_preflight(env)
|
19
|
+
return [200, headers, []] if headers
|
20
|
+
end
|
21
|
+
cors_headers = process_cors(env)
|
22
|
+
end
|
23
|
+
status, headers, body = @app.call env
|
24
|
+
headers = headers.merge(cors_headers) if cors_headers
|
25
|
+
[status, headers, body]
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
def all_resources
|
30
|
+
@all_resources ||= []
|
31
|
+
end
|
32
|
+
|
33
|
+
def process_preflight(env)
|
34
|
+
resource = find_resource(env['HTTP_ORIGIN'], env['PATH_INFO'])
|
35
|
+
resource.to_preflight_headers(env) if resource
|
36
|
+
end
|
37
|
+
|
38
|
+
def process_cors(env)
|
39
|
+
resource = find_resource(env['HTTP_ORIGIN'], env['PATH_INFO'])
|
40
|
+
resource.to_headers(env) if resource
|
41
|
+
end
|
42
|
+
|
43
|
+
def find_resource(origin, path)
|
44
|
+
allowed = all_resources.detect {|r| r.allow_origin?(origin)}
|
45
|
+
allowed ? allowed.find_resource(path) : nil
|
46
|
+
end
|
47
|
+
|
48
|
+
class Resources
|
49
|
+
def initialize
|
50
|
+
@origins = []
|
51
|
+
@resources = []
|
52
|
+
end
|
53
|
+
|
54
|
+
def origins(*args)
|
55
|
+
@origins = args.flatten.collect{|n| "http://#{n}" unless n.match(/^https?:\/\//)}
|
56
|
+
end
|
57
|
+
|
58
|
+
def resource(path, opts={})
|
59
|
+
@resources << Resource.new(path, opts)
|
60
|
+
end
|
61
|
+
|
62
|
+
def allow_origin?(source)
|
63
|
+
@origins.include?(source)
|
64
|
+
end
|
65
|
+
|
66
|
+
def find_resource(path)
|
67
|
+
@resources.detect{|r| r.match?(path)}
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class Resource
|
72
|
+
attr_accessor :path, :methods, :headers, :max_age, :credentials, :pattern
|
73
|
+
|
74
|
+
def initialize(path, opts = {})
|
75
|
+
self.path = path
|
76
|
+
self.methods = ensure_enum(opts[:methods]) || [:get]
|
77
|
+
self.credentials = opts[:credentials] || true
|
78
|
+
self.headers = ensure_enum(opts[:headers]) || nil
|
79
|
+
self.max_age = opts[:max_age] || 1728000
|
80
|
+
self.pattern = compile(path)
|
81
|
+
end
|
82
|
+
|
83
|
+
def match?(path)
|
84
|
+
pattern =~ path
|
85
|
+
end
|
86
|
+
|
87
|
+
def to_headers(env)
|
88
|
+
{ 'Access-Control-Allow-Origin' => env['HTTP_ORIGIN'],
|
89
|
+
'Access-Control-Allow-Methods' => methods.collect{|m| m.to_s.upcase}.join(', '),
|
90
|
+
'Access-Control-Allow-Credentials' => credentials.to_s,
|
91
|
+
'Access-Control-Max-Age' => max_age.to_s }
|
92
|
+
end
|
93
|
+
|
94
|
+
def to_preflight_headers(env)
|
95
|
+
h = to_headers(env)
|
96
|
+
h.merge!('Access-Control-Allow-Headers' => headers.join(', ')) if headers
|
97
|
+
h
|
98
|
+
end
|
99
|
+
|
100
|
+
protected
|
101
|
+
def ensure_enum(v)
|
102
|
+
return nil if v.nil?
|
103
|
+
[v] unless v.respond_to?(:join)
|
104
|
+
end
|
105
|
+
|
106
|
+
def compile(path)
|
107
|
+
if path.respond_to? :to_str
|
108
|
+
special_chars = %w{. + ( )}
|
109
|
+
pattern =
|
110
|
+
path.to_str.gsub(/((:\w+)|[\*#{special_chars.join}])/) do |match|
|
111
|
+
case match
|
112
|
+
when "*"
|
113
|
+
"(.*?)"
|
114
|
+
when *special_chars
|
115
|
+
Regexp.escape(match)
|
116
|
+
else
|
117
|
+
"([^/?&#]+)"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
/^#{pattern}$/
|
121
|
+
elsif path.respond_to? :match
|
122
|
+
path
|
123
|
+
else
|
124
|
+
raise TypeError, path
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
end
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rack-cors
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Calvin Yu
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-06-02 00:00:00 -04:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description:
|
22
|
+
email: csyu77@gmail.com
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files: []
|
28
|
+
|
29
|
+
files:
|
30
|
+
- Rakefile
|
31
|
+
- VERSION
|
32
|
+
- lib/rack/cors.rb
|
33
|
+
has_rdoc: true
|
34
|
+
homepage: http://github.com/cyu/rack-cors
|
35
|
+
licenses: []
|
36
|
+
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options:
|
39
|
+
- --charset=UTF-8
|
40
|
+
require_paths:
|
41
|
+
- lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
segments:
|
47
|
+
- 0
|
48
|
+
version: "0"
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
segments:
|
54
|
+
- 0
|
55
|
+
version: "0"
|
56
|
+
requirements: []
|
57
|
+
|
58
|
+
rubyforge_project:
|
59
|
+
rubygems_version: 1.3.6
|
60
|
+
signing_key:
|
61
|
+
specification_version: 3
|
62
|
+
summary: Middleware for enabling Cross-Origin Resource Sharing in Rack apps
|
63
|
+
test_files: []
|
64
|
+
|