rocketio 0.0.0.pre.alpha → 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +5 -2
  3. data/LICENSE.txt +22 -0
  4. data/README.md +5 -22
  5. data/Rakefile +1 -7
  6. data/lib/rocketio.rb +3 -131
  7. data/lib/rocketio/version.rb +2 -2
  8. data/rocketio.gemspec +17 -21
  9. metadata +11 -146
  10. data/.travis.yml +0 -3
  11. data/bin/console +0 -14
  12. data/bin/setup +0 -7
  13. data/lib/rocketio/application.rb +0 -31
  14. data/lib/rocketio/controller.rb +0 -288
  15. data/lib/rocketio/controller/authentication.rb +0 -141
  16. data/lib/rocketio/controller/authorization.rb +0 -53
  17. data/lib/rocketio/controller/cookies.rb +0 -59
  18. data/lib/rocketio/controller/error_handlers.rb +0 -89
  19. data/lib/rocketio/controller/filters.rb +0 -119
  20. data/lib/rocketio/controller/flash.rb +0 -21
  21. data/lib/rocketio/controller/helpers.rb +0 -438
  22. data/lib/rocketio/controller/middleware.rb +0 -32
  23. data/lib/rocketio/controller/render.rb +0 -148
  24. data/lib/rocketio/controller/render/engine.rb +0 -76
  25. data/lib/rocketio/controller/render/layout.rb +0 -27
  26. data/lib/rocketio/controller/render/layouts.rb +0 -85
  27. data/lib/rocketio/controller/render/templates.rb +0 -83
  28. data/lib/rocketio/controller/request.rb +0 -115
  29. data/lib/rocketio/controller/response.rb +0 -84
  30. data/lib/rocketio/controller/sessions.rb +0 -64
  31. data/lib/rocketio/controller/token_auth.rb +0 -118
  32. data/lib/rocketio/controller/websocket.rb +0 -21
  33. data/lib/rocketio/error_templates/404.html +0 -3
  34. data/lib/rocketio/error_templates/409.html +0 -7
  35. data/lib/rocketio/error_templates/500.html +0 -3
  36. data/lib/rocketio/error_templates/501.html +0 -6
  37. data/lib/rocketio/error_templates/layout.html +0 -1
  38. data/lib/rocketio/exceptions.rb +0 -4
  39. data/lib/rocketio/router.rb +0 -65
  40. data/lib/rocketio/util.rb +0 -122
  41. data/test/aliases_test.rb +0 -54
  42. data/test/authentication_test.rb +0 -307
  43. data/test/authorization_test.rb +0 -91
  44. data/test/cache_control_test.rb +0 -268
  45. data/test/content_type_test.rb +0 -124
  46. data/test/cookies_test.rb +0 -49
  47. data/test/error_handlers_test.rb +0 -125
  48. data/test/etag_test.rb +0 -445
  49. data/test/filters_test.rb +0 -177
  50. data/test/halt_test.rb +0 -73
  51. data/test/helpers_test.rb +0 -171
  52. data/test/middleware_test.rb +0 -57
  53. data/test/redirect_test.rb +0 -135
  54. data/test/render/engine_test.rb +0 -71
  55. data/test/render/get.erb +0 -1
  56. data/test/render/items.erb +0 -1
  57. data/test/render/layout.erb +0 -1
  58. data/test/render/layout_test.rb +0 -104
  59. data/test/render/layouts/master.erb +0 -1
  60. data/test/render/layouts_test.rb +0 -145
  61. data/test/render/master.erb +0 -1
  62. data/test/render/post.erb +0 -1
  63. data/test/render/put.erb +0 -1
  64. data/test/render/render_test.rb +0 -101
  65. data/test/render/setup.rb +0 -14
  66. data/test/render/templates/a/get.erb +0 -1
  67. data/test/render/templates/master.erb +0 -1
  68. data/test/render/templates_test.rb +0 -146
  69. data/test/request_test.rb +0 -105
  70. data/test/response_test.rb +0 -119
  71. data/test/routes_test.rb +0 -70
  72. data/test/sendfile_test.rb +0 -209
  73. data/test/sessions_test.rb +0 -176
  74. data/test/setup.rb +0 -59
data/.travis.yml DELETED
@@ -1,3 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.2.2
data/bin/console DELETED
@@ -1,14 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "bundler/setup"
4
- require "rocketio"
5
-
6
- # You can add fixtures and/or initialization code here to make experimenting
7
- # with your gem easier. You can also use a different console, if you like.
8
-
9
- # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
11
- # Pry.start
12
-
13
- require "irb"
14
- IRB.start
data/bin/setup DELETED
@@ -1,7 +0,0 @@
1
- #!/bin/bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
-
5
- bundle install
6
-
7
- # Do any other automated setup that you need to do here
@@ -1,31 +0,0 @@
1
- module RocketIO
2
- class Application
3
-
4
- def initialize *args, &block
5
- controllers = args.empty? ? RocketIO.controllers : args.flatten
6
- if block
7
- controllers.each {|c| c.class_exec {define_method(:call!, block)}}
8
- end
9
- @router = Router.new(*controllers)
10
- end
11
-
12
- def call env
13
- catch :__response__ do # catch 404 errors and potential `halt` calls from middleware
14
- controller, path_params = @router.resolve_path(env[PATH_INFO])
15
-
16
- unless controller
17
- controller = RocketIO::Controller.initialize_controller
18
- controller.env = env
19
- controller.error(404)
20
- end
21
-
22
- controller = controller.initialize_controller(REQUEST_METHODS[env[REQUEST_METHOD]], path_params)
23
- chain = controller.middleware.reverse.inject(controller) {|app,ware| ware.call(app)}
24
- if controller.sessions
25
- chain = controller.sessions[0].new(chain, controller.sessions[1])
26
- end
27
- chain.call(env)
28
- end
29
- end
30
- end
31
- end
@@ -1,288 +0,0 @@
1
- module RocketIO
2
- class Controller
3
- extend Forwardable
4
-
5
- def_delegators 'self.class', :url, :dirname, :parameters_policy
6
- def_delegators :request, :session, :request_method
7
- def_delegators RocketIO, :indifferent_params, :indifferent_hash, :mime_type, :engine_const, :engine_class
8
- def_delegators CGI, :escape_html
9
-
10
- # defining get, post etc. methods that will be called
11
- # when a request matches current controller and appropriate request method used.
12
- #
13
- # by default all requests, except HEAD, will return a NotImplementedError.
14
- # override the methods you need to be handled by controller.
15
- #
16
- RocketIO::REQUEST_METHODS.each_value do |verb|
17
- define_method(verb) {|*| error(501)}
18
- end
19
- def head(*); end
20
-
21
- # call requested method.
22
- # also call #before, #around and #after filters.
23
- #
24
- # @param [Hash] env
25
- # @return [Rack::Response]
26
- #
27
- def call env
28
- catch :__response__ do
29
- begin
30
- self.env = env
31
- validate_or_request_authentication_if_needed
32
- validate_or_request_authorization_if_needed
33
- validate_parameters
34
-
35
- call! proc {
36
- invoke_before_filter
37
- invoke_around_filter proc {
38
- response.body = public_send(requested_method, *path_params_array)
39
- }
40
- invoke_after_filter
41
- }
42
- response.body ||= RocketIO::EMPTY_ARRAY
43
- response.body = [] if head? # dropping body on HEAD requests
44
- response.finish
45
- rescue Exception => e
46
- if RocketIO.development?
47
- puts "\e[0;31m%s\e[0m" % e.inspect
48
- e.backtrace.each {|l| puts " \e[0;36m%s\e[0m" % l}
49
- end
50
- error(500, e)
51
- end
52
- end
53
- end
54
-
55
- def call! app
56
- app.call
57
- end
58
-
59
- def env= env
60
- @__env__ = env
61
- end
62
-
63
- def env
64
- @__env__
65
- end
66
-
67
- def validate_parameters
68
- # enforce policy only if a method defined for current request method
69
- # cause stock REST methods accepting any number of arguments
70
- return unless policy = parameters_policy[requested_method]
71
-
72
- if path_params_array.size >= policy[:min]
73
- return if policy[:max] == :* || path_params_array.size <= policy[:max]
74
- end
75
-
76
- error(409)
77
- end
78
-
79
- def path_params
80
- @__path_params__ ||= begin
81
- rangemap = self.class.path_params[requested_method] ||
82
- raise(StandardError, 'No path_params map found for %s method' % requested_method)
83
- indifferent_params(rangemap.each_with_object({}) {|(m,r),o|
84
- o[m] = r.min == r.max ? path_params_array[r.min] : path_params_array[r]
85
- }).freeze
86
- end
87
- end
88
-
89
- def path_params_array
90
- @__path_params_array__
91
- end
92
-
93
- def params
94
- @__params__ ||= indifferent_params(request.params)
95
- end
96
-
97
- def request
98
- @__request__ ||= RocketIO::Request.new(env)
99
- end
100
-
101
- def response
102
- @__response__ ||= RocketIO::Response.new
103
- end
104
-
105
- def requested_method
106
- @__requested_method__ ||= RocketIO::REQUEST_METHODS[request_method]
107
- end
108
- end
109
-
110
- class << Controller
111
-
112
- def inherit setup, opts = {}
113
- opts[:from] || raise(ArgumentError, ':from option is required')
114
- __send__(:"define_#{setup}_methods", opts[:from])
115
- end
116
-
117
- def inherited base
118
- # registering new controller
119
- RocketIO.controllers.push(base)
120
-
121
- # new controller inherits all setups from superclass
122
- base.inherit :before, from: self
123
- base.inherit :around, from: self
124
- base.inherit :after, from: self
125
-
126
- base.inherit :basic_auth, from: self
127
- base.inherit :digest_auth, from: self
128
- base.inherit :token_auth, from: self
129
-
130
- base.inherit :error_handlers, from: self
131
- base.inherit :middleware, from: self
132
- base.inherit :sessions, from: self
133
-
134
- base.inherit :engine, from: self
135
- base.inherit :layout, from: self
136
- base.inherit :layouts, from: self
137
- base.inherit :templates, from: self
138
-
139
- # removing superclass name from new controller name
140
- path = RocketIO.underscore(base.name.to_s.sub(self.name.to_s + '::', '').gsub('::', '/'))
141
-
142
- # new controller uses for URL its underscored name prefixed by superclass URL
143
- base.map RocketIO.rootify_path(url, path)
144
-
145
- # setting dirname for new controller
146
- base.instance_variable_set(:@__dirname__, RocketIO.caller_to_dirname(caller).freeze)
147
- end
148
-
149
- # by default controllers will use underscored name for base URL.
150
- # this method allow to set a custom base URL.
151
- #
152
- # @example Users::Register will listen on /users/register by default
153
- # class Users
154
- # class Register < RocketIO
155
- #
156
- # end
157
- # end
158
- #
159
- # @note
160
- #
161
- # @example make Users::Register to listen on /users/join rather than /users/register
162
- #
163
- # class Users
164
- # class Register < RocketIO
165
- # map :join
166
- #
167
- # end
168
- # end
169
- #
170
- # @note if given URL starts with a slash it will ignore class name and set URL as is
171
- #
172
- # @example make Users::Register to listen on /members/join
173
- #
174
- # class Users < RocketIO
175
- # class Register < self
176
- # map '/members/join'
177
- #
178
- # end
179
- # end
180
- #
181
- # @param path [String || Symbol]
182
- #
183
- def map path
184
- path = path.to_s
185
- @__url__ = if path =~ /\A\//
186
- path
187
- else
188
- if superclass == Object
189
- RocketIO.rootify_path(path)
190
- else
191
- RocketIO.rootify_path(superclass.url, path)
192
- end
193
- end.freeze
194
- end
195
-
196
- # allow controllers to serve multiple URLs
197
- #
198
- # @param path [String || Symbol]
199
- #
200
- def alias_url path
201
- path = path.to_s
202
- path = if path =~ /\A\//
203
- path
204
- else
205
- if superclass == Object
206
- RocketIO.rootify_path(path)
207
- else
208
- RocketIO.rootify_path(superclass.url, path)
209
- end
210
- end.freeze
211
- aliases.push(path)
212
- end
213
-
214
- def aliases
215
- @__aliases__ ||= []
216
- end
217
-
218
- # build a URL from given chunks prefixing them with actual path
219
- #
220
- # @param *args [Array]
221
- # @return [String]
222
- def url *args
223
- return @__url__ if args.empty?
224
- query = if args.last.is_a?(Hash)
225
- RocketIO::QUERY_PREFIX + ::Rack::Utils.build_nested_query(args.pop)
226
- else
227
- RocketIO::EMPTY_STRING
228
- end
229
- ::File.join(@__url__, args.map!(&:to_s)) + query
230
- end
231
-
232
- def method_added meth
233
- parameters = instance_method(meth).parameters
234
- path_params[meth] = RocketIO.path_params(parameters).freeze
235
- if requested_method = RocketIO::REQUEST_METHODS.values.find {|verb| verb == meth}
236
- # REST methods should be called with a predetermined set of parameters.
237
- # setting an appropriate policy for just defined method based on its parameters.
238
- parameters_policy[requested_method] = RocketIO.parameters_policy(parameters).freeze
239
- end
240
- end
241
-
242
- # initializing the controller to process a HTTP request
243
- #
244
- # @param path_params [Array]
245
- # @return a RocketIO::Route instance
246
- def initialize_controller requested_method = nil, path_params_array = nil
247
- controller = allocate
248
- controller.instance_variable_set(:@__requested_method__, requested_method.to_sym) if requested_method
249
- controller.instance_variable_set(:@__path_params_array__, (path_params_array || []).freeze)
250
- controller
251
- end
252
-
253
- def parameters_policy
254
- @__parameters_policy__ ||= {}
255
- end
256
-
257
- def path_params
258
- @__path_params__ ||= {}
259
- end
260
-
261
- def dirname *args
262
- ::File.join(@__dirname__, args.map!(&:to_s))
263
- end
264
-
265
- # making controller to act as a Rack application
266
- def call env
267
- initialize_controller.call(env)
268
- end
269
-
270
- def api
271
- public_instance_methods(false)
272
- end
273
- end
274
- end
275
-
276
- require 'rocketio/controller/authentication'
277
- require 'rocketio/controller/authorization'
278
- require 'rocketio/controller/cookies'
279
- require 'rocketio/controller/error_handlers'
280
- require 'rocketio/controller/filters'
281
- require 'rocketio/controller/flash'
282
- require 'rocketio/controller/helpers'
283
- require 'rocketio/controller/middleware'
284
- require 'rocketio/controller/request'
285
- require 'rocketio/controller/response'
286
- require 'rocketio/controller/sessions'
287
- require 'rocketio/controller/websocket'
288
- require 'rocketio/controller/render'
@@ -1,141 +0,0 @@
1
- module RocketIO
2
- class Controller
3
-
4
- # easily restrict access to controller using basic auth
5
- #
6
- # @example protect all request methods
7
- # basic_auth do |user,pass|
8
- # user == 'admin' && pass == 'super secret password'
9
- # end
10
- #
11
- # @example protect only POST, PUT and DELETE request methods
12
- # basic_auth :post, :put, :delete do |user,pass|
13
- # user == 'admin' && pass == 'super secret password'
14
- # end
15
- #
16
- # @example use different credentials for GET and POST
17
- # basic_auth :get do |user,pass|
18
- # user == 'reader' && pass == 'readPass'
19
- # end
20
- #
21
- # basic_auth :post do |user,pass|
22
- # user == 'poster' && pass == 'writePass'
23
- # end
24
- #
25
- # @note authorization is composable, that's it, if superclass is protecting :get method
26
- # and current controller protects :post method,
27
- # both :get and :post will be protected in current controller
28
- #
29
- # @params *args [Array]
30
- # @param block [Proc]
31
- #
32
- def self.basic_auth *args, &block
33
- opts = args.last.is_a?(Hash) ? args.pop : {}
34
- rqms = args.any? ? args.map!(&:to_sym) : RocketIO::REQUEST_METHODS.values
35
- rqms.each do |rm|
36
- (@__basic_auth__ ||= {})[rm] = {
37
- class: Rack::Auth::Basic,
38
- arguments: [opts[:realm] || RocketIO::DEFAULT_AUTH_REALM].freeze,
39
- block: block,
40
- mock: RocketIO::HTTP_AUTHORIZATION_MOCKS[:basic]
41
- }.freeze
42
- end
43
- define_basic_auth_methods
44
- end
45
-
46
- def self.define_basic_auth_methods source = self
47
- prompts = (source.instance_variable_get(:@__basic_auth__) || {}).each_with_object(allocate.basic_auth.dup) do |(rm,p),o|
48
- method = :"__basic_auth__#{rm}__"
49
- define_method(method, &p[:block])
50
- o[rm] = p.merge(method: method).freeze
51
- end.freeze
52
- return if prompts.empty?
53
- define_method(:basic_auth) {prompts}
54
- end
55
-
56
- def basic_auth; RocketIO::EMPTY_HASH end
57
-
58
- # easily restrict access to controller using digest auth
59
- #
60
- # @example protect all request methods using hashed passwords
61
- # # hash the password somewhere in irb:
62
- # # ::Digest::MD5.hexdigest 'admin:AccessRestricted:somePassword'
63
- # # username ^ realm ^ password ^
64
- #
65
- # #=> 9d77d54decc22cdcfb670b7b79ee0ef0
66
- #
67
- # digest_auth :passwords_hashed => true, :realm => 'AccessRestricted' do |user|
68
- # {'admin' => '9d77d54decc22cdcfb670b7b79ee0ef0'}[user]
69
- # end
70
- #
71
- # @example protect all request methods using plain passwords
72
- # digest_auth do |user|
73
- # {'admin' => 'password'}[user]
74
- # end
75
- #
76
- # @example protect only POST, PUT and DELETE request methods
77
- # digest_auth :post, :put, :delete do |user|
78
- # {'admin' => 'password'}[user]
79
- # end
80
- #
81
- # @example use different credentials for GET and POST
82
- # digest_auth :get do |user|
83
- # {'user' => 'readPass'}[user]
84
- # end
85
- #
86
- # digest_auth :post do |user|
87
- # {'poster' => 'writePass'}[user]
88
- # end
89
- #
90
- # @params *args [Array]
91
- # @param block [Proc]
92
- #
93
- def self.digest_auth *args, &block
94
- opts = args.last.is_a?(Hash) ? args.pop : {}
95
- opts[:realm] ||= RocketIO::DEFAULT_AUTH_REALM
96
- opts[:opaque] ||= opts[:realm]
97
- rqms = args.any? ? args.map!(&:to_sym) : RocketIO::REQUEST_METHODS.values
98
- rqms.each do |rm|
99
- (@__digest_auth__ ||= {})[rm] = {
100
- class: Rack::Auth::Digest::MD5,
101
- arguments: [opts].freeze,
102
- block: block,
103
- mock: RocketIO::HTTP_AUTHORIZATION_MOCKS[:digest]
104
- }.freeze
105
- end
106
- define_digest_auth_methods
107
- end
108
-
109
- def self.define_digest_auth_methods source = self
110
- prompts = (source.instance_variable_get(:@__digest_auth__) || {}).each_with_object(allocate.digest_auth.dup) do |(rm,p),o|
111
- method = :"__digest_auth__#{rm}__"
112
- define_method(method, &p[:block])
113
- o[rm] = p.merge(method: method).freeze
114
- end.freeze
115
- return if prompts.empty?
116
- define_method(:digest_auth) {prompts}
117
- end
118
-
119
- def digest_auth; RocketIO::EMPTY_HASH end
120
-
121
- def user?
122
- env[RocketIO::REMOTE_USER]
123
- end
124
-
125
- # checks whether authentication is required and
126
- # send an authorization request if credentials not present or invalid
127
- def validate_or_request_authentication_if_needed
128
- return unless auth = digest_auth[requested_method] || basic_auth[requested_method]
129
- return unless prompt = auth[:class].new(proc {}, *auth[:arguments]) do |*a|
130
- self.__send__(auth[:method], *a)
131
- end.call(
132
- if RocketIO::HTTP_AUTHORIZATION_KEYS.detect {|key| env.has_key?(key)}
133
- env
134
- else
135
- env.merge(RocketIO::HTTP_AUTHORIZATION_KEYS.first => auth[:mock])
136
- end
137
- )
138
- throw(:__response__, prompt)
139
- end
140
- end
141
- end