rocketio 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -5
  3. data/.pryrc +2 -0
  4. data/.travis.yml +3 -0
  5. data/README.md +22 -5
  6. data/Rakefile +7 -1
  7. data/bin/console +14 -0
  8. data/bin/setup +7 -0
  9. data/lib/rocketio.rb +131 -3
  10. data/lib/rocketio/application.rb +31 -0
  11. data/lib/rocketio/controller.rb +288 -0
  12. data/lib/rocketio/controller/authentication.rb +141 -0
  13. data/lib/rocketio/controller/authorization.rb +53 -0
  14. data/lib/rocketio/controller/cookies.rb +59 -0
  15. data/lib/rocketio/controller/error_handlers.rb +89 -0
  16. data/lib/rocketio/controller/filters.rb +119 -0
  17. data/lib/rocketio/controller/flash.rb +21 -0
  18. data/lib/rocketio/controller/helpers.rb +438 -0
  19. data/lib/rocketio/controller/middleware.rb +32 -0
  20. data/lib/rocketio/controller/render.rb +148 -0
  21. data/lib/rocketio/controller/render/engine.rb +76 -0
  22. data/lib/rocketio/controller/render/layout.rb +27 -0
  23. data/lib/rocketio/controller/render/layouts.rb +85 -0
  24. data/lib/rocketio/controller/render/templates.rb +83 -0
  25. data/lib/rocketio/controller/request.rb +115 -0
  26. data/lib/rocketio/controller/response.rb +84 -0
  27. data/lib/rocketio/controller/sessions.rb +64 -0
  28. data/lib/rocketio/controller/token_auth.rb +118 -0
  29. data/lib/rocketio/controller/websocket.rb +21 -0
  30. data/lib/rocketio/error_templates/404.html +3 -0
  31. data/lib/rocketio/error_templates/409.html +7 -0
  32. data/lib/rocketio/error_templates/500.html +3 -0
  33. data/lib/rocketio/error_templates/501.html +6 -0
  34. data/lib/rocketio/error_templates/layout.html +1 -0
  35. data/lib/rocketio/exceptions.rb +4 -0
  36. data/lib/rocketio/router.rb +65 -0
  37. data/lib/rocketio/util.rb +122 -0
  38. data/lib/rocketio/version.rb +2 -2
  39. data/rocketio.gemspec +21 -17
  40. data/test/aliases_test.rb +54 -0
  41. data/test/authentication_test.rb +307 -0
  42. data/test/authorization_test.rb +91 -0
  43. data/test/cache_control_test.rb +268 -0
  44. data/test/content_type_test.rb +124 -0
  45. data/test/cookies_test.rb +49 -0
  46. data/test/error_handlers_test.rb +125 -0
  47. data/test/etag_test.rb +445 -0
  48. data/test/filters_test.rb +177 -0
  49. data/test/halt_test.rb +73 -0
  50. data/test/helpers_test.rb +171 -0
  51. data/test/middleware_test.rb +57 -0
  52. data/test/redirect_test.rb +135 -0
  53. data/test/render/engine_test.rb +71 -0
  54. data/test/render/get.erb +1 -0
  55. data/test/render/items.erb +1 -0
  56. data/test/render/layout.erb +1 -0
  57. data/test/render/layout_test.rb +104 -0
  58. data/test/render/layouts/master.erb +1 -0
  59. data/test/render/layouts_test.rb +145 -0
  60. data/test/render/master.erb +1 -0
  61. data/test/render/post.erb +1 -0
  62. data/test/render/put.erb +1 -0
  63. data/test/render/render_test.rb +101 -0
  64. data/test/render/setup.rb +14 -0
  65. data/test/render/templates/a/get.erb +1 -0
  66. data/test/render/templates/master.erb +1 -0
  67. data/test/render/templates_test.rb +146 -0
  68. data/test/request_test.rb +105 -0
  69. data/test/response_test.rb +119 -0
  70. data/test/routes_test.rb +70 -0
  71. data/test/sendfile_test.rb +209 -0
  72. data/test/sessions_test.rb +176 -0
  73. data/test/setup.rb +59 -0
  74. metadata +144 -9
  75. data/LICENSE.txt +0 -22
@@ -0,0 +1,70 @@
1
+ require 'setup'
2
+
3
+ class A < RocketIO::Controller
4
+ def get(x); [:a, x]*':' end
5
+ def post; url end
6
+
7
+ class B <self
8
+ def get(x = nil); [:b, x]*':' end
9
+
10
+ class C < self
11
+ def get(x = nil); [:c, x]*':' end
12
+ end
13
+ end
14
+ end
15
+
16
+ class D < RocketIO::Controller
17
+ end
18
+
19
+ spec :Routes do
20
+ test 'paths' do
21
+ assert(A.url) == '/a'
22
+ assert(A::B.url) == '/a/b'
23
+ assert(A::B::C.url) == '/a/b/c'
24
+ end
25
+
26
+ it 'overrides inherited REST methods' do
27
+ app(A)
28
+ post
29
+ assert(last_response).is_ok
30
+
31
+ app(D)
32
+ post
33
+ assert(last_response).is_unimplemented
34
+ end
35
+
36
+ it 'inherits REST methods from supercontroller' do
37
+ app(A::B)
38
+ get
39
+ assert(last_response).is_ok_with_body 'b:'
40
+
41
+ post
42
+ assert(last_response).is_ok_with_body '/a/b'
43
+ end
44
+
45
+ context :router do
46
+ before {app mock_app(A, A::B, A::B::C)}
47
+
48
+ test '"a" does not serve /a/b' do
49
+ get '/a/x'
50
+ assert(last_response).is_ok_with_body 'a:x'
51
+
52
+ get '/a/b'
53
+ assert(last_response).is_ok_with_body 'b:'
54
+
55
+ get '/a/b/x'
56
+ assert(last_response).is_ok_with_body 'b:x'
57
+ end
58
+
59
+ test '"b" does not serve /a/b/c' do
60
+ get '/a/b'
61
+ assert(last_response).is_ok_with_body 'b:'
62
+
63
+ get '/a/b/c'
64
+ assert(last_response).is_ok_with_body 'c:'
65
+
66
+ get '/a/b/c/x'
67
+ assert(last_response).is_ok_with_body 'c:x'
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,209 @@
1
+ # Copyright (c) 2007, 2008, 2009 Blake Mizerany
2
+ # Copyright (c) 2010, 2011, 2012, 2013, 2014 Konstantin Haase
3
+ # Copyright (c) 2015 Slee Woo
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person
6
+ # obtaining a copy of this software and associated documentation
7
+ # files (the "Software"), to deal in the Software without
8
+ # restriction, including without limitation the rights to use,
9
+ # copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the
11
+ # Software is furnished to do so, subject to the following
12
+ # conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be
15
+ # included in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19
+ # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24
+ # OTHER DEALINGS IN THE SOFTWARE.
25
+
26
+ require 'setup'
27
+
28
+ spec 'attachment' do
29
+
30
+ def attachment_app(filename=nil)
31
+ app mock_controller('/attachment') {
32
+ define_method :get do
33
+ attachment filename
34
+ response.write("<html></html>")
35
+ end
36
+ }
37
+ end
38
+
39
+ it 'sets the Content-Type response header' do
40
+ attachment_app('test.xml')
41
+ get '/attachment'
42
+ assert(last_response['Content-Type']) == 'application/xml'
43
+ assert(last_response.body) == '<html></html>'
44
+ end
45
+
46
+ it 'sets the Content-Type response header without extname' do
47
+ attachment_app('test')
48
+ get '/attachment'
49
+ assert(last_response['Content-Type']) == 'text/html'
50
+ assert(last_response.body) == '<html></html>'
51
+ end
52
+
53
+ it 'sets the Content-Type response header with extname' do
54
+ app mock_controller('/attachment') {
55
+ def get
56
+ content_type :atom
57
+ attachment 'test.xml'
58
+ response.write("<html></html>")
59
+ end
60
+ }
61
+
62
+ get '/attachment'
63
+ assert(last_response['Content-Type']) == 'application/atom+xml'
64
+ assert(last_response.body) == '<html></html>'
65
+ end
66
+ end
67
+
68
+ spec 'send_file' do
69
+ before do
70
+ @file = File.dirname(__FILE__) + '/file.txt'
71
+ File.open(@file, 'wb') { |io| io.write('Hello World') }
72
+ end
73
+
74
+ after do
75
+ File.unlink @file
76
+ @file = nil
77
+ end
78
+
79
+ def send_file_app(opts={})
80
+ path = @file
81
+ app mock_controller('/file.txt') {
82
+ define_method(:get) {send_file(path, opts)}
83
+ }
84
+ get('/file.txt')
85
+ end
86
+
87
+ it "sends the contents of the file" do
88
+ send_file_app
89
+ assert(last_response).ok?
90
+ assert(last_response.body) == File.read(@file)
91
+ end
92
+
93
+ it 'sets the Content-Type response header if a mime-type can be located' do
94
+ send_file_app
95
+ assert(last_response['Content-Type']) == 'text/plain'
96
+ end
97
+
98
+ it 'sets the Content-Type response header if type option is set to a file extension' do
99
+ send_file_app :type => 'html'
100
+ assert(last_response['Content-Type']) == 'text/html'
101
+ end
102
+
103
+ it 'sets the Content-Type response header if type option is set to a mime type' do
104
+ send_file_app :type => 'application/octet-stream'
105
+ assert(last_response['Content-Type']) == 'application/octet-stream'
106
+ end
107
+
108
+ it 'sets the Content-Length response header' do
109
+ send_file_app
110
+ assert(last_response['Content-Length']) == File.read(@file).length.to_s
111
+ end
112
+
113
+ it 'sets the Last-Modified response header' do
114
+ send_file_app
115
+ assert(last_response['Last-Modified']) == File.mtime(@file).httpdate
116
+ end
117
+
118
+ it 'allows passing in a different Last-Modified response header with :last_modified' do
119
+ time = Time.now
120
+ send_file_app :last_modified => time
121
+ assert(last_response['Last-Modified']) == time.httpdate
122
+ end
123
+
124
+ it "returns a 404 when not found" do
125
+ app mock_controller {
126
+ def get; send_file 'this-file-does-not-exist.txt'; end
127
+ }
128
+ get
129
+ assert(last_response).not_found?
130
+ end
131
+
132
+ it "does not set the Content-Disposition header by default" do
133
+ send_file_app
134
+ assert(last_response['Content-Disposition']).nil?
135
+ end
136
+
137
+ it "sets the Content-Disposition header when :disposition set to 'attachment'" do
138
+ send_file_app :disposition => 'attachment'
139
+ assert(last_response['Content-Disposition']) == 'attachment; filename="file.txt"'
140
+ end
141
+
142
+ it "does not set add a file name if filename is false" do
143
+ send_file_app :disposition => 'inline', :filename => false
144
+ assert(last_response['Content-Disposition']) == 'inline'
145
+ end
146
+
147
+ it "sets the Content-Disposition header when :disposition set to 'inline'" do
148
+ send_file_app :disposition => 'inline'
149
+ assert(last_response['Content-Disposition']) == 'inline; filename="file.txt"'
150
+ end
151
+
152
+ it "sets the Content-Disposition header when :filename provided" do
153
+ send_file_app :filename => 'foo.txt'
154
+ assert(last_response['Content-Disposition']) == 'attachment; filename="foo.txt"'
155
+ end
156
+
157
+ it 'allows setting a custom status code' do
158
+ send_file_app :status => 201
159
+ assert(last_response.status) == 201
160
+ end
161
+
162
+ it "is able to send files with unknown mime type" do
163
+ file = File.dirname(__FILE__) + '/file.foobar'
164
+ File.open(file, 'wb') { |io| io.write('Hello World') }
165
+
166
+ app mock_controller('/file.txt') {
167
+ define_method(:get) {send_file(file)}
168
+ }
169
+ get('/file.txt')
170
+ File.unlink(file)
171
+
172
+ assert(last_response['Content-Type']) == 'application/octet-stream'
173
+ end
174
+
175
+ it "does not override Content-Type if already set and no explicit type is given" do
176
+ path = @file
177
+ app mock_controller {
178
+ define_method :get do
179
+ content_type :png
180
+ send_file path
181
+ end
182
+ }
183
+ get
184
+ assert(last_response['Content-Type']) == 'image/png'
185
+ end
186
+
187
+ it "does override Content-Type even if already set, if explicit type is given" do
188
+ path = @file
189
+ app mock_controller {
190
+ define_method :get do
191
+ content_type :png
192
+ send_file path, :type => :gif
193
+ end
194
+ }
195
+ get
196
+ assert(last_response['Content-Type']) == 'image/gif'
197
+ end
198
+
199
+ it 'can have :status option as a string' do
200
+ path = @file
201
+ app mock_controller {
202
+ define_method :post do
203
+ send_file path, :status => '422'
204
+ end
205
+ }
206
+ post
207
+ assert(last_response.status) == 422
208
+ end
209
+ end
@@ -0,0 +1,176 @@
1
+ # Copyright (c) 2007, 2008, 2009 Blake Mizerany
2
+ # Copyright (c) 2010, 2011, 2012, 2013, 2014 Konstantin Haase
3
+ # Copyright (c) 2015 Slee Woo
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person
6
+ # obtaining a copy of this software and associated documentation
7
+ # files (the "Software"), to deal in the Software without
8
+ # restriction, including without limitation the rights to use,
9
+ # copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the
11
+ # Software is furnished to do so, subject to the following
12
+ # conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be
15
+ # included in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19
+ # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24
+ # OTHER DEALINGS IN THE SOFTWARE.
25
+
26
+ require 'setup'
27
+
28
+ spec :Sessions do
29
+ before do
30
+ env.clear
31
+ end
32
+
33
+ it 'inherits sessions setup from superclass' do
34
+ a = mock_controller {
35
+ sessions :cookies
36
+ }
37
+ b = mock_controller(:b, a) {
38
+ def get(y); session[:x] = y end
39
+ def post; session[:x] end
40
+ }
41
+ app mock_app(a, b)
42
+ get :b, :y
43
+ post :b
44
+ assert(last_response.body) == 'y'
45
+ end
46
+
47
+ it 'explicitly inherits sessions setup' do
48
+ a = mock_controller {
49
+ sessions :cookies
50
+ }
51
+ b = mock_controller(:b) {
52
+ inherit :sessions, from: a
53
+ def get(y); session[:x] = y end
54
+ def post; session[:x] end
55
+ }
56
+ app mock_app(a, b)
57
+ get :b, :y
58
+ post :b
59
+ assert(last_response.body) == 'y'
60
+ end
61
+
62
+ it 'directly overrides sessions setup inherited from superclass' do
63
+ a = mock_controller {
64
+ sessions :cookies
65
+ }
66
+ b = mock_controller(:b, a) {
67
+ sessions nil
68
+ def get(y); session[:x] = y end
69
+ def post; session[:x] end
70
+ }
71
+ app mock_app(a, b)
72
+ get :b, :y
73
+ post :b
74
+ assert(last_response.body) == ''
75
+ end
76
+
77
+ it 'uses `inherit` to override sessions setup inherited from superclass' do
78
+ a = mock_controller {
79
+ sessions :cookies
80
+ }
81
+ b = mock_controller(:b, a) {
82
+ sessions false
83
+ def get(y); session[:x] = y end
84
+ def post; session[:x] end
85
+ }
86
+ c = mock_controller(a) {
87
+ inherit :sessions, from: b
88
+ def get(y); session[:x] = y end
89
+ def post; session[:x] end
90
+ }
91
+ app mock_app(a, b)
92
+ get :b, :y
93
+ post :b
94
+ assert(last_response.body) == ''
95
+ end
96
+
97
+ it 'uses the existing rack.session' do
98
+ app mock_app(mock_controller {
99
+ sessions :cookies
100
+ define_method(:get) {session[:foo]}
101
+ })
102
+
103
+ env['rack.session'] = { :foo => 'bar' }
104
+ get
105
+ assert(last_response.body) == 'bar'
106
+ end
107
+
108
+ it 'creates a new session when none provided' do
109
+ a = mock_controller {
110
+ sessions :cookies, secret: 'svss'
111
+
112
+ define_method :get do
113
+ fail('session[:foo] already set') unless session[:foo].nil?
114
+ session[:foo] = 'bar'
115
+ redirect '/hi'
116
+ end
117
+ }
118
+ b = mock_controller('hi') {
119
+ sessions :cookies, secret: 'svss'
120
+ define_method(:get) {"hi #{session[:foo]}"}
121
+ }
122
+ app mock_app(a, b)
123
+
124
+ get
125
+ follow_redirect!
126
+ assert(last_response.body) == 'hi bar'
127
+ end
128
+
129
+ it 'inserts session middleware' do
130
+ app mock_app(mock_controller {
131
+ sessions :cookies
132
+
133
+ define_method :get do
134
+ unless env['rack.session'] && env['rack.session.options']
135
+ fail('session middleware not inserted')
136
+ end
137
+ 'ok'
138
+ end
139
+ })
140
+
141
+ get
142
+ assert(last_response.body) == 'ok'
143
+ end
144
+
145
+ it 'sets a default session secret' do
146
+ app mock_app(mock_controller {
147
+ sessions :cookies
148
+
149
+ define_method :get do
150
+ unless env['rack.session.options'][:secret]
151
+ fail('default session secret not set')
152
+ end
153
+ 'ok'
154
+ end
155
+ })
156
+
157
+ get
158
+ assert(last_response.body) == 'ok'
159
+ end
160
+
161
+ it 'accepts an options hash' do
162
+ app mock_app(mock_controller {
163
+ sessions :cookies, secret: 'svss'
164
+
165
+ define_method :get do
166
+ unless env['rack.session.options'][:secret]
167
+ fail('looks like option hash not set/used')
168
+ end
169
+ 'ok'
170
+ end
171
+ })
172
+
173
+ get
174
+ assert(last_response.body) == 'ok'
175
+ end
176
+ end