strelka-cors 0.0.1

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.
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env rspec -cfd
2
+
3
+ require_relative '../../helpers'
4
+
5
+ require 'strelka'
6
+ require 'mongrel2/testing'
7
+ require 'strelka/testing'
8
+
9
+ require 'strelka/httprequest/cors'
10
+
11
+
12
+ describe Strelka::HTTPRequest::CORS do
13
+
14
+ before( :all ) do
15
+ @request_factory = Mongrel2::RequestFactory.new(
16
+ host: 'telomere.com',
17
+ port: '80',
18
+ route: '/api/v1'
19
+ )
20
+ end
21
+
22
+
23
+ let( :get_request ) do
24
+ req = @request_factory.get( '/api/v1/test' )
25
+ req.extend( described_class )
26
+ req
27
+ end
28
+
29
+
30
+ describe "header accessors" do
31
+
32
+ it "adds a convenience method for accessing the Origin header" do
33
+ expect {
34
+ get_request.header[ :origin ] = 'http://acme.com/api/v1/test'
35
+ }.to change { get_request.origin }.to( URI('http://acme.com/api/v1/test') )
36
+ end
37
+
38
+ end
39
+
40
+
41
+ describe "predicates" do
42
+
43
+ let( :options_request ) do
44
+ req = @request_factory.options( '/api/v1/test' )
45
+ req.extend( described_class )
46
+ end
47
+
48
+
49
+ it "knows when it's a cross-origin request" do
50
+ get_request.headers.merge!( origin: 'http://acme.com/' )
51
+ expect( get_request ).to be_cross_origin
52
+ end
53
+
54
+
55
+ it "knows it's not a cross-origin request when its Origin matches its Host" do
56
+ get_request.headers.merge!( host: 'acme.com', origin: 'http://acme.com/' )
57
+ expect( get_request ).to_not be_cross_origin
58
+ end
59
+
60
+
61
+ it "knows when it's a preflight request" do
62
+ options_request.header.host = 'telomere.com'
63
+ options_request.header.origin = 'http://acme.com/'
64
+ options_request.header.access_control_request_method = 'POST'
65
+
66
+ expect( options_request ).to be_preflight
67
+ end
68
+
69
+
70
+ it "knows it's not a preflight request when it doesn't have an Access-Control-Request-Method header" do
71
+ options_request.header.host = 'telomere.com'
72
+ options_request.header.origin = 'http://acme.com/'
73
+ options_request.header.access_control_request_method = nil
74
+
75
+ expect( options_request ).to_not be_preflight
76
+ end
77
+
78
+
79
+ it "knows it's not a preflight request when its verb isn't OPTIONS" do
80
+ get_request.header.host = 'telomere.com'
81
+ get_request.header.origin = 'http://acme.com/'
82
+ get_request.header.access_control_request_method = 'POST'
83
+
84
+ expect( get_request ).to_not be_preflight
85
+ end
86
+
87
+
88
+ end
89
+
90
+ end
91
+
@@ -0,0 +1,234 @@
1
+ #!/usr/bin/env rspec -cfd
2
+
3
+ require_relative '../../helpers'
4
+
5
+ require 'strelka'
6
+ require 'mongrel2/testing'
7
+ require 'strelka/testing'
8
+
9
+ require 'strelka/httprequest/cors'
10
+ require 'strelka/httpresponse/cors'
11
+
12
+
13
+ describe Strelka::HTTPResponse::CORS do
14
+
15
+ before( :all ) do
16
+ @request_factory = Mongrel2::RequestFactory.new(
17
+ host: 'telomere.com',
18
+ port: '80',
19
+ route: '/api/v1',
20
+ headers: {
21
+ origin: 'https://telomere.com'
22
+ }
23
+ )
24
+ end
25
+
26
+
27
+ let( :regular_request ) do
28
+ req = @request_factory.get( '/api/v1/test' )
29
+ req.extend( Strelka::HTTPRequest::CORS )
30
+ req.response.extend( described_class )
31
+ req
32
+ end
33
+
34
+ let( :regular_response ) do
35
+ regular_request.response
36
+ end
37
+
38
+
39
+ let( :preflight_request ) do
40
+ req = @request_factory.options( '/api/v1/test', access_control_request_method: 'POST' )
41
+ req.extend( Strelka::HTTPRequest::CORS )
42
+ req.response.extend( described_class )
43
+ req
44
+ end
45
+
46
+ let( :preflight_response ) do
47
+ preflight_request.response
48
+ end
49
+
50
+
51
+ describe "header accessors" do
52
+
53
+ it "adds a convenience method for setting allowed origin" do
54
+ regular_response.allow_origin( 'http://acme.com' )
55
+
56
+ expect {
57
+ regular_response.add_cors_headers
58
+ }.to change { regular_response.header.access_control_allow_origin }.to( 'http://acme.com' )
59
+ end
60
+
61
+
62
+ it "adds a convenience method for allowing any origin" do
63
+ regular_response.allow_any_origin
64
+
65
+ expect {
66
+ regular_response.add_cors_headers
67
+ }.to change { regular_response.header.access_control_allow_origin }.to( '*' )
68
+ end
69
+
70
+
71
+ it "sets the `Vary` response header to `Origin` if it specifies an explicit Origin" do
72
+ regular_response.allow_origin( 'http://acme.com' )
73
+
74
+ expect {
75
+ regular_response.add_cors_headers
76
+ }.to change { regular_response.header.vary }.to( match(/\borigin\b/i) )
77
+ end
78
+
79
+
80
+ it "doesn't set the `Vary` response header to `Origin` if it allows any origin" do
81
+ regular_response.allow_any_origin
82
+
83
+ expect {
84
+ regular_response.add_cors_headers
85
+ }.to_not change { regular_response.header.vary }
86
+ end
87
+
88
+
89
+ it "adds `Origin` to an existing Vary header if it specifies an explicit Origin" do
90
+ regular_response.allow_origin( 'http://acme.com' )
91
+ regular_response.header.vary = 'content-encoding, content-type'
92
+
93
+ regular_response.add_cors_headers
94
+
95
+ expect( regular_response.header.vary.downcase.split(/\s*,\s*/) ).
96
+ to include( 'origin', 'content-encoding', 'content-type' )
97
+ end
98
+
99
+
100
+ it "adds a convenience method for allowing a single header" do
101
+ preflight_response.allow_header :content_type
102
+ preflight_response.allow_header :x_thingfish_owner
103
+
104
+ expect {
105
+ preflight_response.add_cors_headers
106
+ }.to change { preflight_response.header.access_control_allow_headers }
107
+ expect( preflight_response.header.access_control_allow_headers.split ).to include(
108
+ 'Content-Type',
109
+ 'X-Thingfish-Owner'
110
+ )
111
+ end
112
+
113
+
114
+ it "adds a convenience method for allowing several headers" do
115
+ preflight_response.allow_headers :content_type, :vary
116
+ preflight_response.allow_headers 'x-ordered-by', 'x-offset', 'x-set-size'
117
+
118
+ expect {
119
+ preflight_response.add_cors_headers
120
+ }.to change { preflight_response.header.access_control_allow_headers }
121
+ expect( preflight_response.header.access_control_allow_headers.split ).to include(
122
+ 'Content-Type',
123
+ 'Vary',
124
+ 'X-Ordered-By',
125
+ 'X-Offset',
126
+ 'X-Set-Size'
127
+ )
128
+ end
129
+
130
+
131
+ it "adds a convenience method for setting the set of allowed request headers" do
132
+ preflight_response.allowed_headers = ['content-type', 'x-sorted-by']
133
+
134
+ expect {
135
+ preflight_response.add_cors_headers
136
+ }.to change { preflight_response.header.access_control_allow_headers }
137
+ expect( preflight_response.header.access_control_allow_headers.split ).to include(
138
+ 'Content-Type',
139
+ 'X-Sorted-By'
140
+ )
141
+ end
142
+
143
+
144
+ it "doesn't set exposed headers on a response to a preflight request" do
145
+ preflight_response.expose_headers( :content_type, :content_disposition )
146
+ preflight_response.add_cors_headers
147
+
148
+ expect( preflight_response.headers.access_control_exposed_headers ).to be_nil
149
+ end
150
+
151
+
152
+ it "adds a convenience method for exposing a single header" do
153
+ regular_response.expose_header :content_type
154
+ regular_response.expose_header :x_thingfish_owner
155
+
156
+ expect {
157
+ regular_response.add_cors_headers
158
+ }.to change { regular_response.header.access_control_expose_headers }
159
+ expect( regular_response.header.access_control_expose_headers.split ).to include(
160
+ 'Content-Type',
161
+ 'X-Thingfish-Owner'
162
+ )
163
+ end
164
+
165
+
166
+ it "adds a convenience method for exposing several of the response headers" do
167
+ regular_response.expose_headers :content_type, :vary
168
+ regular_response.expose_headers 'x-ordered-by', 'x-offset', 'x-set-size'
169
+
170
+ expect {
171
+ regular_response.add_cors_headers
172
+ }.to change { regular_response.header.access_control_expose_headers }
173
+ expect( regular_response.header.access_control_expose_headers.split ).to include(
174
+ 'Content-Type',
175
+ 'Vary',
176
+ 'X-Ordered-By',
177
+ 'X-Offset',
178
+ 'X-Set-Size'
179
+ )
180
+ end
181
+
182
+
183
+ it "adds a convenience method for setting the set of exposed response headers" do
184
+ regular_response.exposed_headers = ['content-type', 'x-sorted-by']
185
+
186
+ expect {
187
+ regular_response.add_cors_headers
188
+ }.to change { regular_response.header.access_control_expose_headers }
189
+ expect( regular_response.header.access_control_expose_headers.split ).to include(
190
+ 'Content-Type',
191
+ 'X-Sorted-By'
192
+ )
193
+ end
194
+
195
+
196
+ it "doesn't set allowed headers on a response to a regular request" do
197
+ regular_response.allow_headers( :content_type, :content_disposition )
198
+ regular_response.add_cors_headers
199
+
200
+ expect( regular_response.headers.access_control_allow_headers ).to be_nil
201
+ end
202
+
203
+
204
+ it "adds a convenience method for allowing particular HTTP methods" do
205
+ preflight_response.allow_methods( :GET, :POST, :PATCH )
206
+ preflight_response.add_cors_headers
207
+
208
+ expect(
209
+ preflight_response.header.access_control_allow_methods.split
210
+ ).to include( 'GET', 'POST', 'PATCH' )
211
+ end
212
+
213
+
214
+ it "adds a convenience method for allowing cookies (credentials)" do
215
+ preflight_response.allow_credentials
216
+ preflight_response.add_cors_headers
217
+
218
+ expect( preflight_response.header.access_control_allow_credentials ).to eq( 'true' )
219
+ end
220
+
221
+
222
+ it "adds a convenience method for setting the maximum number of seconds a preflight " \
223
+ "request can be cached" do
224
+ preflight_response.access_control_max_age = 300
225
+ preflight_response.add_cors_headers
226
+
227
+ expect( preflight_response.header.access_control_max_age ).to eq( '300' )
228
+ end
229
+
230
+ end
231
+
232
+
233
+ end
234
+
metadata ADDED
@@ -0,0 +1,231 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: strelka-cors
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Michael Granger
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain:
11
+ - |
12
+ -----BEGIN CERTIFICATE-----
13
+ MIIEbDCCAtSgAwIBAgIBATANBgkqhkiG9w0BAQsFADA+MQwwCgYDVQQDDANnZWQx
14
+ GTAXBgoJkiaJk/IsZAEZFglGYWVyaWVNVUQxEzARBgoJkiaJk/IsZAEZFgNvcmcw
15
+ HhcNMTYwODIwMTgxNzQyWhcNMTcwODIwMTgxNzQyWjA+MQwwCgYDVQQDDANnZWQx
16
+ GTAXBgoJkiaJk/IsZAEZFglGYWVyaWVNVUQxEzARBgoJkiaJk/IsZAEZFgNvcmcw
17
+ ggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQC/JWGRHO+USzR97vXjkFgt
18
+ 83qeNf2KHkcvrRTSnR64i6um/ziin0I0oX23H7VYrDJC9A/uoUa5nGRJS5Zw/+wW
19
+ ENcvWVZS4iUzi4dsYJGY6yEOsXh2CcF46+QevV8iE+UmbkU75V7Dy1JCaUOyizEt
20
+ TH5UHsOtUU7k9TYARt/TgYZKuaoAMZZd5qyVqhF1vV+7/Qzmp89NGflXf2xYP26a
21
+ 4MAX2qqKX/FKXqmFO+AGsbwYTEds1mksBF3fGsFgsQWxftG8GfZQ9+Cyu2+l1eOw
22
+ cZ+lPcg834G9DrqW2zhqUoLr1MTly4pqxYGb7XoDhoR7dd1kFE2a067+DzWC/ADt
23
+ +QkcqWUm5oh1fN0eqr7NsZlVJDulFgdiiYPQiIN7UNsii4Wc9aZqBoGcYfBeQNPZ
24
+ soo/6za/bWajOKUmDhpqvaiRv9EDpVLzuj53uDoukMMwxCMfgb04+ckQ0t2G7wqc
25
+ /D+K9JW9DDs3Yjgv9k4h7YMhW5gftosd+NkNC/+Y2CkCAwEAAaN1MHMwCQYDVR0T
26
+ BAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFHKN/nkRusdqCJEuq3lgB3fJvyTg
27
+ MBwGA1UdEQQVMBOBEWdlZEBGYWVyaWVNVUQub3JnMBwGA1UdEgQVMBOBEWdlZEBG
28
+ YWVyaWVNVUQub3JnMA0GCSqGSIb3DQEBCwUAA4IBgQAPJzKiT0zBU7kpqe0aS2qb
29
+ FI0PJ4y5I8buU4IZGUD5NEt/N7pZNfOyBxkrZkXhS44Fp+xwBH5ebLbq/WY78Bqd
30
+ db0z6ZgW4LMYMpWFfbXsRbd9TU2f52L8oMAhxOvF7Of5qJMVWuFQ8FPagk2iHrdH
31
+ inYLQagqAF6goWTXgAJCdPd6SNeeSNqA6vlY7CV1Jh5kfNJJ6xu/CVij1GzCLu/5
32
+ DMOr26DBv+qLJRRC/2h34uX71q5QgeOyxvMg+7V3u/Q06DXyQ2VgeeqiwDFFpEH0
33
+ PFkdPO6ZqbTRcLfNH7mFgCBJjsfSjJrn0sPBlYyOXgCoByfZnZyrIMH/UY+lgQqS
34
+ 6Von1VDsfQm0eJh5zYZD64ZF86phSR7mUX3mXItwH04HrZwkWpvgd871DZVR3i1n
35
+ w8aNA5re5+Rt/Vvjxj5AcEnZnZiz5x959NaddQocX32Z1unHw44pzRNUur1GInfW
36
+ p4vpx2kUSFSAGjtCbDGTNV2AH8w9OU4xEmNz8c5lyoA=
37
+ -----END CERTIFICATE-----
38
+ date: 2016-11-04 00:00:00.000000000 Z
39
+ dependencies:
40
+ - !ruby/object:Gem::Dependency
41
+ name: strelka
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '0.11'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '0.11'
54
+ - !ruby/object:Gem::Dependency
55
+ name: hoe-mercurial
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '1.4'
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '1.4'
68
+ - !ruby/object:Gem::Dependency
69
+ name: hoe-deveiate
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '0.8'
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '0.8'
82
+ - !ruby/object:Gem::Dependency
83
+ name: hoe-highline
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '0.2'
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '0.2'
96
+ - !ruby/object:Gem::Dependency
97
+ name: rspec
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '3.2'
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '3.2'
110
+ - !ruby/object:Gem::Dependency
111
+ name: simplecov
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '0.9'
117
+ type: :development
118
+ prerelease: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '0.9'
124
+ - !ruby/object:Gem::Dependency
125
+ name: timecop
126
+ requirement: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: '0.7'
131
+ type: :development
132
+ prerelease: false
133
+ version_requirements: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - "~>"
136
+ - !ruby/object:Gem::Version
137
+ version: '0.7'
138
+ - !ruby/object:Gem::Dependency
139
+ name: rdoc
140
+ requirement: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - "~>"
143
+ - !ruby/object:Gem::Version
144
+ version: '4.0'
145
+ type: :development
146
+ prerelease: false
147
+ version_requirements: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - "~>"
150
+ - !ruby/object:Gem::Version
151
+ version: '4.0'
152
+ - !ruby/object:Gem::Dependency
153
+ name: hoe
154
+ requirement: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - "~>"
157
+ - !ruby/object:Gem::Version
158
+ version: '3.15'
159
+ type: :development
160
+ prerelease: false
161
+ version_requirements: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - "~>"
164
+ - !ruby/object:Gem::Version
165
+ version: '3.15'
166
+ description: "This is a Strelka application plugin for describing rules for [Cross-Origin
167
+ Resource Sharing (CORS)](http://www.w3.org/TR/cors/).\n\nNOTE: It's still a work
168
+ in progress.\n\nBy default, the plugin has paranoid defaults, and doesn't do anything.
169
+ You'll need to grant access to the resources you want to share.\n\nTo grant access,
170
+ you declare one or more `access_control` blocks which can modify responses to matching
171
+ access-control requests. All the blocks which match the incoming request's URI are
172
+ called with the request and response objects in the order in which they're declared:
173
+ \n\n\t# Allow access to all resources from any origin by default\n\taccess_control
174
+ do |req, res|\n\t\tres.allow_origin '*'\n\t\tres.allow_methods 'GET', 'POST'\n\t\tres.allow_credentials\n\t\tres.allow_headers
175
+ :content_type\n\tend\n\n\nThese are applied in the order you declare them, with
176
+ each matching block passed the request if it matches. This happens before the application
177
+ gets the request, so it can do any further modification it needs to, and so it can
178
+ block requests from disallowed origins/methods/etc.\n\nThere are a number of helper
179
+ methods added to the request and response objects for applying and declaring access-control
180
+ rules when this plugin is loaded:"
181
+ email:
182
+ - ged@FaerieMUD.org
183
+ executables: []
184
+ extensions: []
185
+ extra_rdoc_files:
186
+ - History.md
187
+ - Manifest.txt
188
+ - README.md
189
+ files:
190
+ - ChangeLog
191
+ - History.md
192
+ - Manifest.txt
193
+ - README.md
194
+ - Rakefile
195
+ - lib/strelka/app/cors.rb
196
+ - lib/strelka/cors.rb
197
+ - lib/strelka/httprequest/cors.rb
198
+ - lib/strelka/httpresponse/cors.rb
199
+ - spec/helpers.rb
200
+ - spec/strelka/app/cors_spec.rb
201
+ - spec/strelka/cors_spec.rb
202
+ - spec/strelka/httprequest/cors_spec.rb
203
+ - spec/strelka/httpresponse/cors_spec.rb
204
+ homepage: http://deveiate.org/projects/strelka-cors
205
+ licenses:
206
+ - BSD-3-Clause
207
+ metadata: {}
208
+ post_install_message:
209
+ rdoc_options:
210
+ - "--main"
211
+ - README.md
212
+ require_paths:
213
+ - lib
214
+ required_ruby_version: !ruby/object:Gem::Requirement
215
+ requirements:
216
+ - - ">="
217
+ - !ruby/object:Gem::Version
218
+ version: 2.2.0
219
+ required_rubygems_version: !ruby/object:Gem::Requirement
220
+ requirements:
221
+ - - ">="
222
+ - !ruby/object:Gem::Version
223
+ version: '0'
224
+ requirements: []
225
+ rubyforge_project:
226
+ rubygems_version: 2.5.1
227
+ signing_key:
228
+ specification_version: 4
229
+ summary: This is a Strelka application plugin for describing rules for [Cross-Origin
230
+ Resource Sharing (CORS)](http://www.w3.org/TR/cors/)
231
+ test_files: []