rack-cors 0.1.0

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.

Files changed (4) hide show
  1. data/Rakefile +12 -0
  2. data/VERSION +1 -0
  3. data/lib/rack/cors.rb +130 -0
  4. metadata +64 -0
@@ -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
@@ -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
+