rage-rb 0.3.0 → 0.5.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +35 -5
- data/Gemfile +3 -0
- data/README.md +14 -12
- data/lib/rage/all.rb +27 -0
- data/lib/rage/application.rb +35 -6
- data/lib/rage/cli.rb +43 -44
- data/lib/rage/configuration.rb +22 -6
- data/lib/rage/controller/api.rb +52 -4
- data/lib/rage/errors.rb +4 -0
- data/lib/rage/fiber.rb +58 -10
- data/lib/rage/fiber_scheduler.rb +59 -32
- data/lib/rage/logger/logger.rb +164 -0
- data/lib/rage/logger/text_formatter.rb +46 -0
- data/lib/rage/params_parser.rb +45 -0
- data/lib/rage/request.rb +44 -0
- data/lib/rage/router/backend.rb +37 -4
- data/lib/rage/router/dsl.rb +236 -6
- data/lib/rage/router/handler_storage.rb +8 -5
- data/lib/rage/sidekiq_session.rb +72 -0
- data/lib/rage/templates/Gemfile +5 -1
- data/lib/rage/templates/Rakefile +1 -0
- data/lib/rage/templates/config-application.rb +6 -1
- data/lib/rage/templates/config-environments-development.rb +6 -3
- data/lib/rage/templates/config-environments-production.rb +7 -3
- data/lib/rage/templates/config-environments-test.rb +6 -3
- data/lib/rage/uploaded_file.rb +70 -0
- data/lib/rage/version.rb +1 -1
- data/lib/rage-rb.rb +7 -16
- data/rage.gemspec +1 -1
- metadata +13 -4
data/lib/rage/router/dsl.rb
CHANGED
@@ -9,14 +9,54 @@ class Rage::Router::DSL
|
|
9
9
|
Handler.new(@router).instance_eval(&block)
|
10
10
|
end
|
11
11
|
|
12
|
+
##
|
13
|
+
# This class implements routing logic for your application, providing API similar to Rails.
|
14
|
+
#
|
15
|
+
# Compared to the Rails router, the most notable difference is that a wildcard segment can only be in the last section of the path and cannot be named.
|
16
|
+
# Example:
|
17
|
+
# ```ruby
|
18
|
+
# get "/photos/*"
|
19
|
+
# ```
|
20
|
+
#
|
21
|
+
# Also, as this is an API-only framework, route helpers, like `photos_path` or `photos_url` are not being generated.
|
22
|
+
#
|
23
|
+
# #### Constraints
|
24
|
+
#
|
25
|
+
# Currently, the only constraint supported is the `host` constraint. The constraint value can be either string or a regular expression.
|
26
|
+
# Example:
|
27
|
+
# ```ruby
|
28
|
+
# get "/photos", to: "photos#index", constraints: { host: "myhost.com" }
|
29
|
+
# ```
|
30
|
+
#
|
31
|
+
# Parameter constraints are likely to be added in the future versions. Custom/lambda constraints are unlikely to be ever added.
|
32
|
+
#
|
33
|
+
# @example Set up a root handler
|
34
|
+
# root to: "pages#main"
|
35
|
+
# @example Set up multiple resources
|
36
|
+
# resources :magazines do
|
37
|
+
# resources :ads
|
38
|
+
# end
|
39
|
+
# @example Scope a set of routes to the given default options.
|
40
|
+
# scope path: ":account_id" do
|
41
|
+
# resources :projects
|
42
|
+
# end
|
43
|
+
# @example Scope routes to a specific namespace.
|
44
|
+
# namespace :admin do
|
45
|
+
# resources :posts
|
46
|
+
# end
|
12
47
|
class Handler
|
13
48
|
# @private
|
14
49
|
def initialize(router)
|
15
50
|
@router = router
|
16
51
|
|
52
|
+
@default_actions = %i(index create show update destroy)
|
53
|
+
@default_match_methods = %i(get post put patch delete head)
|
54
|
+
@scope_opts = %i(module path controller)
|
55
|
+
|
17
56
|
@path_prefixes = []
|
18
57
|
@module_prefixes = []
|
19
58
|
@defaults = []
|
59
|
+
@controllers = []
|
20
60
|
end
|
21
61
|
|
22
62
|
# Register a new GET route.
|
@@ -29,7 +69,7 @@ class Rage::Router::DSL
|
|
29
69
|
# get "/photos/:id", to: "photos#show", constraints: { host: /myhost/ }
|
30
70
|
# @example
|
31
71
|
# get "/photos(/:id)", to: "photos#show", defaults: { id: "-1" }
|
32
|
-
def get(path, to
|
72
|
+
def get(path, to: nil, constraints: nil, defaults: nil)
|
33
73
|
__on("GET", path, to, constraints, defaults)
|
34
74
|
end
|
35
75
|
|
@@ -43,7 +83,7 @@ class Rage::Router::DSL
|
|
43
83
|
# post "/photos", to: "photos#create", constraints: { host: /myhost/ }
|
44
84
|
# @example
|
45
85
|
# post "/photos", to: "photos#create", defaults: { format: "jpg" }
|
46
|
-
def post(path, to
|
86
|
+
def post(path, to: nil, constraints: nil, defaults: nil)
|
47
87
|
__on("POST", path, to, constraints, defaults)
|
48
88
|
end
|
49
89
|
|
@@ -57,7 +97,7 @@ class Rage::Router::DSL
|
|
57
97
|
# put "/photos/:id", to: "photos#update", constraints: { host: /myhost/ }
|
58
98
|
# @example
|
59
99
|
# put "/photos(/:id)", to: "photos#update", defaults: { id: "-1" }
|
60
|
-
def put(path, to
|
100
|
+
def put(path, to: nil, constraints: nil, defaults: nil)
|
61
101
|
__on("PUT", path, to, constraints, defaults)
|
62
102
|
end
|
63
103
|
|
@@ -71,7 +111,7 @@ class Rage::Router::DSL
|
|
71
111
|
# patch "/photos/:id", to: "photos#update", constraints: { host: /myhost/ }
|
72
112
|
# @example
|
73
113
|
# patch "/photos(/:id)", to: "photos#update", defaults: { id: "-1" }
|
74
|
-
def patch(path, to
|
114
|
+
def patch(path, to: nil, constraints: nil, defaults: nil)
|
75
115
|
__on("PATCH", path, to, constraints, defaults)
|
76
116
|
end
|
77
117
|
|
@@ -85,7 +125,7 @@ class Rage::Router::DSL
|
|
85
125
|
# delete "/photos/:id", to: "photos#destroy", constraints: { host: /myhost/ }
|
86
126
|
# @example
|
87
127
|
# delete "/photos(/:id)", to: "photos#destroy", defaults: { id: "-1" }
|
88
|
-
def delete(path, to
|
128
|
+
def delete(path, to: nil, constraints: nil, defaults: nil)
|
89
129
|
__on("DELETE", path, to, constraints, defaults)
|
90
130
|
end
|
91
131
|
|
@@ -98,6 +138,70 @@ class Rage::Router::DSL
|
|
98
138
|
__on("GET", "/", to, nil, nil)
|
99
139
|
end
|
100
140
|
|
141
|
+
# Match a URL pattern to one or more routes.
|
142
|
+
#
|
143
|
+
# @param path [String] the path for the route handler
|
144
|
+
# @param to [String, #call] the route handler in the format of "controller#action" or a callable
|
145
|
+
# @param constraints [Hash] a hash of constraints for the route
|
146
|
+
# @param defaults [Hash] a hash of default parameters for the route
|
147
|
+
# @param via [Symbol, Array<Symbol>] an array of HTTP methods to accept
|
148
|
+
# @example
|
149
|
+
# match "/photos/:id", to: "photos#show", via: [:get, :post]
|
150
|
+
# @example
|
151
|
+
# match "/photos/:id", to: "photos#show", via: :all
|
152
|
+
# @example
|
153
|
+
# match "/health", to: -> (env) { [200, {}, ["healthy"]] }
|
154
|
+
def match(path, to:, constraints: {}, defaults: nil, via: :all)
|
155
|
+
# via is either nil, or an array of symbols or its :all
|
156
|
+
http_methods = via
|
157
|
+
# if its :all or nil, then we use the default HTTP methods
|
158
|
+
if via == :all || via.nil?
|
159
|
+
http_methods = @default_match_methods
|
160
|
+
else
|
161
|
+
# if its an array of symbols, then we use the symbols as HTTP methods
|
162
|
+
http_methods = Array(via)
|
163
|
+
# then we check if the HTTP methods are valid
|
164
|
+
http_methods.each do |method|
|
165
|
+
raise ArgumentError, "Invalid HTTP method: #{method}" unless @default_match_methods.include?(method)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
http_methods.each do |method|
|
170
|
+
__on(method.to_s.upcase, path, to, constraints, defaults)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
# Register a new namespace.
|
175
|
+
#
|
176
|
+
# @param path [String] the path for the namespace
|
177
|
+
# @param options [Hash] a hash of options for the namespace
|
178
|
+
# @option options [String] :module the module name for the namespace
|
179
|
+
# @option options [String] :path the path for the namespace
|
180
|
+
# @example
|
181
|
+
# namespace :admin do
|
182
|
+
# get "/photos", to: "photos#index"
|
183
|
+
# end
|
184
|
+
# @example
|
185
|
+
# namespace :admin, path: "panel" do
|
186
|
+
# get "/photos", to: "photos#index"
|
187
|
+
# end
|
188
|
+
# @example
|
189
|
+
# namespace :admin, module: "admin" do
|
190
|
+
# get "/photos", to: "photos#index"
|
191
|
+
# end
|
192
|
+
def namespace(path, **options, &block)
|
193
|
+
path_prefix = options[:path] || path
|
194
|
+
module_prefix = options[:module] || path
|
195
|
+
|
196
|
+
@path_prefixes << path_prefix
|
197
|
+
@module_prefixes << module_prefix
|
198
|
+
|
199
|
+
instance_eval &block
|
200
|
+
|
201
|
+
@path_prefixes.pop
|
202
|
+
@module_prefixes.pop
|
203
|
+
end
|
204
|
+
|
101
205
|
# Scopes a set of routes to the given default options.
|
102
206
|
#
|
103
207
|
# @param [Hash] opts scope options.
|
@@ -120,15 +224,17 @@ class Rage::Router::DSL
|
|
120
224
|
# end
|
121
225
|
# end
|
122
226
|
def scope(opts, &block)
|
123
|
-
raise ArgumentError, "only
|
227
|
+
raise ArgumentError, "only :module, :path, and :controller options are accepted" if (opts.keys - @scope_opts).any?
|
124
228
|
|
125
229
|
@path_prefixes << opts[:path].delete_prefix("/").delete_suffix("/") if opts[:path]
|
126
230
|
@module_prefixes << opts[:module] if opts[:module]
|
231
|
+
@controllers << opts[:controller] if opts[:controller]
|
127
232
|
|
128
233
|
instance_eval &block
|
129
234
|
|
130
235
|
@path_prefixes.pop if opts[:path]
|
131
236
|
@module_prefixes.pop if opts[:module]
|
237
|
+
@controllers.pop if opts[:controller]
|
132
238
|
end
|
133
239
|
|
134
240
|
# Specify default parameters for a set of routes.
|
@@ -144,14 +250,120 @@ class Rage::Router::DSL
|
|
144
250
|
@defaults.pop
|
145
251
|
end
|
146
252
|
|
253
|
+
# Add a route to the collection.
|
254
|
+
#
|
255
|
+
# @example Add a `photos/search` path instead of `photos/:photo_id/search`
|
256
|
+
# resources :photos do
|
257
|
+
# collection do
|
258
|
+
# get "search"
|
259
|
+
# end
|
260
|
+
# end
|
261
|
+
def collection(&block)
|
262
|
+
orig_path_prefixes = @path_prefixes
|
263
|
+
@path_prefixes = @path_prefixes[0...-1] if @path_prefixes.last&.start_with?(":")
|
264
|
+
instance_eval &block
|
265
|
+
@path_prefixes = orig_path_prefixes
|
266
|
+
end
|
267
|
+
|
268
|
+
# Automatically create REST routes for a resource.
|
269
|
+
#
|
270
|
+
# @example Create five REST routes, all mapping to the `Photos` controller:
|
271
|
+
# resources :photos
|
272
|
+
# # GET /photos => photos#index
|
273
|
+
# # POST /photos => photos#create
|
274
|
+
# # GET /photos/:id => photos#show
|
275
|
+
# # PATCH/PUT /photos/:id => photos#update
|
276
|
+
# # DELETE /photos/:id => photos#destroy
|
277
|
+
# @note This helper doesn't generate the `new` and `edit` routes.
|
278
|
+
def resources(*_resources, **opts, &block)
|
279
|
+
# support calls with multiple resources, e.g. `resources :albums, :photos`
|
280
|
+
if _resources.length > 1
|
281
|
+
_resources.each { |_resource| resources(_resource, **opts, &block) }
|
282
|
+
return
|
283
|
+
end
|
284
|
+
|
285
|
+
_module, _path, _only, _except, _param = opts.values_at(:module, :path, :only, :except, :param)
|
286
|
+
raise ":param option can't contain colons" if _param&.include?(":")
|
287
|
+
|
288
|
+
_only = Array(_only) if _only
|
289
|
+
_except = Array(_except) if _except
|
290
|
+
actions = @default_actions.select do |action|
|
291
|
+
(_only.nil? || _only.include?(action)) && (_except.nil? || !_except.include?(action))
|
292
|
+
end
|
293
|
+
|
294
|
+
resource = _resources[0].to_s
|
295
|
+
_path ||= resource
|
296
|
+
_param ||= "id"
|
297
|
+
|
298
|
+
scope_opts = { path: _path }
|
299
|
+
scope_opts[:module] = _module if _module
|
300
|
+
|
301
|
+
scope(scope_opts) do
|
302
|
+
get("/", to: "#{resource}#index") if actions.include?(:index)
|
303
|
+
post("/", to: "#{resource}#create") if actions.include?(:create)
|
304
|
+
get("/:#{_param}", to: "#{resource}#show") if actions.include?(:show)
|
305
|
+
patch("/:#{_param}", to: "#{resource}#update") if actions.include?(:update)
|
306
|
+
put("/:#{_param}", to: "#{resource}#update") if actions.include?(:update)
|
307
|
+
delete("/:#{_param}", to: "#{resource}#destroy") if actions.include?(:destroy)
|
308
|
+
|
309
|
+
scope(path: ":#{to_singular(resource)}_#{_param}", controller: resource, &block) if block
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
313
|
+
# Mount a Rack-based application to be used within the application.
|
314
|
+
#
|
315
|
+
# @example
|
316
|
+
# mount Sidekiq::Web => "/sidekiq"
|
317
|
+
# @example
|
318
|
+
# mount Sidekiq::Web, at: "/sidekiq", via: :get
|
319
|
+
def mount(*args)
|
320
|
+
if args.first.is_a?(Hash)
|
321
|
+
app = args.first.keys.first
|
322
|
+
at = args.first.values.first
|
323
|
+
via = args[0][:via]
|
324
|
+
else
|
325
|
+
app = args.first
|
326
|
+
at = args[1][:at]
|
327
|
+
via = args[1][:via]
|
328
|
+
end
|
329
|
+
|
330
|
+
at = "/#{at}" unless at.start_with?("/")
|
331
|
+
at = at.delete_suffix("/") if at.end_with?("/")
|
332
|
+
|
333
|
+
http_methods = if via == :all || via.nil?
|
334
|
+
@default_match_methods.map { |method| method.to_s.upcase! }
|
335
|
+
else
|
336
|
+
Array(via).map! do |method|
|
337
|
+
raise ArgumentError, "Invalid HTTP method: #{method}" unless @default_match_methods.include?(method)
|
338
|
+
method.to_s.upcase!
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
@router.mount(at, app, http_methods)
|
343
|
+
end
|
344
|
+
|
147
345
|
private
|
148
346
|
|
149
347
|
def __on(method, path, to, constraints, defaults)
|
348
|
+
# handle calls without controller inside resources:
|
349
|
+
# resources :comments do
|
350
|
+
# post :like
|
351
|
+
# end
|
352
|
+
if !to
|
353
|
+
if @controllers.any?
|
354
|
+
to = "#{@controllers.last}##{path}"
|
355
|
+
else
|
356
|
+
raise "Missing :to key on routes definition, please check your routes."
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
# process path to ensure it starts with "/" and doesn't end with "/"
|
150
361
|
if path != "/"
|
151
362
|
path = "/#{path}" unless path.start_with?("/")
|
152
363
|
path = path.delete_suffix("/") if path.end_with?("/")
|
153
364
|
end
|
154
365
|
|
366
|
+
# correctly process root helpers inside `scope` calls
|
155
367
|
if path == "/" && @path_prefixes.any?
|
156
368
|
path = ""
|
157
369
|
end
|
@@ -166,5 +378,23 @@ class Rage::Router::DSL
|
|
166
378
|
@router.on(method, "#{path_prefix}#{path}", to, constraints: constraints || {}, defaults: defaults)
|
167
379
|
end
|
168
380
|
end
|
381
|
+
|
382
|
+
def to_singular(str)
|
383
|
+
@active_support_loaded ||= str.respond_to?(:singularize) || :false
|
384
|
+
return str.singularize if @active_support_loaded != :false
|
385
|
+
|
386
|
+
@endings ||= {
|
387
|
+
"ves" => "fe",
|
388
|
+
"ies" => "y",
|
389
|
+
"i" => "us",
|
390
|
+
"zes" => "ze",
|
391
|
+
"ses" => "s",
|
392
|
+
"es" => "",
|
393
|
+
"s" => ""
|
394
|
+
}
|
395
|
+
@regexp ||= Regexp.new("(#{@endings.keys.join("|")})$")
|
396
|
+
|
397
|
+
str.sub(@regexp, @endings)
|
398
|
+
end
|
169
399
|
end
|
170
400
|
end
|
@@ -22,7 +22,7 @@ class Rage::Router::HandlerStorage
|
|
22
22
|
params: params,
|
23
23
|
constraints: constraints,
|
24
24
|
handler: route[:handler],
|
25
|
-
create_params_object: compile_create_params_object(params, route[:defaults])
|
25
|
+
create_params_object: compile_create_params_object(params, route[:defaults], route[:meta])
|
26
26
|
}
|
27
27
|
|
28
28
|
constraints_keys = constraints.keys
|
@@ -47,16 +47,19 @@ class Rage::Router::HandlerStorage
|
|
47
47
|
|
48
48
|
private
|
49
49
|
|
50
|
-
def compile_create_params_object(param_keys, defaults)
|
51
|
-
lines = [
|
50
|
+
def compile_create_params_object(param_keys, defaults, meta)
|
51
|
+
lines = [
|
52
|
+
":controller => '#{meta[:controller]}'.freeze",
|
53
|
+
":action => '#{meta[:action]}'.freeze"
|
54
|
+
]
|
52
55
|
|
53
56
|
param_keys.each_with_index do |key, i|
|
54
|
-
lines << "
|
57
|
+
lines << ":#{key} => param_values[#{i}]"
|
55
58
|
end
|
56
59
|
|
57
60
|
if defaults
|
58
61
|
defaults.except(*param_keys.map(&:to_sym)).each do |key, value|
|
59
|
-
lines << "
|
62
|
+
lines << ":#{key} => '#{value}'.freeze"
|
60
63
|
end
|
61
64
|
end
|
62
65
|
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "digest"
|
4
|
+
require "base64"
|
5
|
+
|
6
|
+
##
|
7
|
+
# Used **specifically** for compatibility with Sidekiq's Web interface.
|
8
|
+
# Remove once we have real sessions or once Sidekiq's author decides they
|
9
|
+
# don't need cookie sessions to protect against CSRF.
|
10
|
+
#
|
11
|
+
class Rage::SidekiqSession
|
12
|
+
KEY = Digest::SHA2.hexdigest(ENV["SECRET_KEY_BASE"] || File.read("Gemfile.lock") + File.read("config/routes.rb"))
|
13
|
+
SESSION_KEY = "rage.sidekiq.session"
|
14
|
+
|
15
|
+
def self.with_session(env)
|
16
|
+
env["rack.session"] = session = self.new(env)
|
17
|
+
response = yield
|
18
|
+
|
19
|
+
if session.changed
|
20
|
+
Rack::Utils.set_cookie_header!(
|
21
|
+
response[1],
|
22
|
+
SESSION_KEY,
|
23
|
+
{ path: env["SCRIPT_NAME"], httponly: true, same_site: true, value: session.dump }
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
response
|
28
|
+
end
|
29
|
+
|
30
|
+
attr_reader :changed
|
31
|
+
|
32
|
+
def initialize(env)
|
33
|
+
@env = env
|
34
|
+
session = Rack::Utils.parse_cookies(@env)[SESSION_KEY]
|
35
|
+
@data = decode_session(session)
|
36
|
+
end
|
37
|
+
|
38
|
+
def [](key)
|
39
|
+
@data[key]
|
40
|
+
end
|
41
|
+
|
42
|
+
def[]=(key, value)
|
43
|
+
@changed = true
|
44
|
+
@data[key] = value
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_hash
|
48
|
+
@data
|
49
|
+
end
|
50
|
+
|
51
|
+
def dump
|
52
|
+
encoded_data = Marshal.dump(@data)
|
53
|
+
signature = OpenSSL::HMAC.hexdigest("SHA256", KEY, encoded_data)
|
54
|
+
|
55
|
+
Base64.urlsafe_encode64("#{encoded_data}--#{signature}")
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def decode_session(session)
|
61
|
+
return {} unless session
|
62
|
+
|
63
|
+
encoded_data, signature = Base64.urlsafe_decode64(session).split("--")
|
64
|
+
ref_signature = OpenSSL::HMAC.hexdigest("SHA256", KEY, encoded_data)
|
65
|
+
|
66
|
+
if Rack::Utils.secure_compare(signature, ref_signature)
|
67
|
+
Marshal.load(encoded_data)
|
68
|
+
else
|
69
|
+
{}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/rage/templates/Gemfile
CHANGED
@@ -1,6 +1,10 @@
|
|
1
1
|
source "https://rubygems.org"
|
2
2
|
|
3
|
-
gem "rage-rb"
|
3
|
+
gem "rage-rb", "<%= Rage::VERSION %>"
|
4
4
|
|
5
5
|
# Build JSON APIs with ease
|
6
6
|
# gem "alba"
|
7
|
+
|
8
|
+
# Get 50% to 150% boost when parsing JSON.
|
9
|
+
# Rage will automatically use FastJsonparser if it is available.
|
10
|
+
# gem "fast_jsonparser"
|
@@ -0,0 +1 @@
|
|
1
|
+
require_relative "config/application"
|
@@ -1,7 +1,10 @@
|
|
1
|
-
Rage.configure do
|
1
|
+
Rage.configure do
|
2
2
|
# Specify the number of server processes to run. Defaults to number of CPU cores.
|
3
|
-
config.workers_count = 1
|
3
|
+
config.server.workers_count = 1
|
4
4
|
|
5
5
|
# Specify the port the server will listen on.
|
6
|
-
config.port = 3000
|
6
|
+
config.server.port = 3000
|
7
|
+
|
8
|
+
# Specify the logger
|
9
|
+
config.logger = Rage::Logger.new(STDOUT)
|
7
10
|
end
|
@@ -1,7 +1,11 @@
|
|
1
|
-
Rage.configure do
|
1
|
+
Rage.configure do
|
2
2
|
# Specify the number of server processes to run. Defaults to number of CPU cores.
|
3
|
-
# config.workers_count = ENV.fetch("WEB_CONCURRENCY", 1)
|
3
|
+
# config.server.workers_count = ENV.fetch("WEB_CONCURRENCY", 1)
|
4
4
|
|
5
5
|
# Specify the port the server will listen on.
|
6
|
-
config.port = 3000
|
6
|
+
config.server.port = 3000
|
7
|
+
|
8
|
+
# Specify the logger
|
9
|
+
config.logger = Rage::Logger.new("log/production.log")
|
10
|
+
config.log_level = Logger::INFO
|
7
11
|
end
|
@@ -1,7 +1,10 @@
|
|
1
|
-
Rage.configure do
|
1
|
+
Rage.configure do
|
2
2
|
# Specify the number of server processes to run. Defaults to number of CPU cores.
|
3
|
-
config.workers_count = 1
|
3
|
+
config.server.workers_count = 1
|
4
4
|
|
5
5
|
# Specify the port the server will listen on.
|
6
|
-
config.port = 3000
|
6
|
+
config.server.port = 3000
|
7
|
+
|
8
|
+
# Specify the logger
|
9
|
+
config.logger = Rage::Logger.new("log/test.log")
|
7
10
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
##
|
4
|
+
# Models uploaded files.
|
5
|
+
#
|
6
|
+
# The actual file is accessible via the `file` accessor, though some
|
7
|
+
# of its interface is available directly for convenience.
|
8
|
+
#
|
9
|
+
# Rage will automatically unlink the files, so there is no need to clean them with a separate maintenance task.
|
10
|
+
class Rage::UploadedFile
|
11
|
+
# The basename of the file in the client.
|
12
|
+
attr_reader :original_filename
|
13
|
+
|
14
|
+
# A string with the MIME type of the file.
|
15
|
+
attr_reader :content_type
|
16
|
+
|
17
|
+
# A `File` object with the actual uploaded file. Note that some of its interface is available directly.
|
18
|
+
attr_reader :file
|
19
|
+
alias_method :tempfile, :file
|
20
|
+
|
21
|
+
def initialize(file, original_filename, content_type)
|
22
|
+
@file = file
|
23
|
+
@original_filename = original_filename
|
24
|
+
@content_type = content_type
|
25
|
+
end
|
26
|
+
|
27
|
+
# Shortcut for `file.read`.
|
28
|
+
def read(length = nil, buffer = nil)
|
29
|
+
@file.read(length, buffer)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Shortcut for `file.open`.
|
33
|
+
def open
|
34
|
+
@file.open
|
35
|
+
end
|
36
|
+
|
37
|
+
# Shortcut for `file.close`.
|
38
|
+
def close(unlink_now = false)
|
39
|
+
@file.close(unlink_now)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Shortcut for `file.path`.
|
43
|
+
def path
|
44
|
+
@file.path
|
45
|
+
end
|
46
|
+
|
47
|
+
# Shortcut for `file.to_path`.
|
48
|
+
def to_path
|
49
|
+
@file.to_path
|
50
|
+
end
|
51
|
+
|
52
|
+
# Shortcut for `file.rewind`.
|
53
|
+
def rewind
|
54
|
+
@file.rewind
|
55
|
+
end
|
56
|
+
|
57
|
+
# Shortcut for `file.size`.
|
58
|
+
def size
|
59
|
+
@file.size
|
60
|
+
end
|
61
|
+
|
62
|
+
# Shortcut for `file.eof?`.
|
63
|
+
def eof?
|
64
|
+
@file.eof?
|
65
|
+
end
|
66
|
+
|
67
|
+
def to_io
|
68
|
+
@file.to_io
|
69
|
+
end
|
70
|
+
end
|
data/lib/rage/version.rb
CHANGED
data/lib/rage-rb.rb
CHANGED
@@ -22,8 +22,9 @@ module Rage
|
|
22
22
|
@config ||= Rage::Configuration.new
|
23
23
|
end
|
24
24
|
|
25
|
-
def self.configure
|
26
|
-
|
25
|
+
def self.configure(&)
|
26
|
+
config.instance_eval(&)
|
27
|
+
config.__finalize
|
27
28
|
end
|
28
29
|
|
29
30
|
def self.env
|
@@ -38,6 +39,10 @@ module Rage
|
|
38
39
|
@root ||= Pathname.new(".").expand_path
|
39
40
|
end
|
40
41
|
|
42
|
+
def self.logger
|
43
|
+
@logger ||= config.logger
|
44
|
+
end
|
45
|
+
|
41
46
|
module Router
|
42
47
|
module Strategies
|
43
48
|
end
|
@@ -46,17 +51,3 @@ end
|
|
46
51
|
|
47
52
|
module RageController
|
48
53
|
end
|
49
|
-
|
50
|
-
require_relative "rage/application"
|
51
|
-
require_relative "rage/fiber"
|
52
|
-
require_relative "rage/fiber_scheduler"
|
53
|
-
require_relative "rage/configuration"
|
54
|
-
|
55
|
-
require_relative "rage/router/strategies/host"
|
56
|
-
require_relative "rage/router/backend"
|
57
|
-
require_relative "rage/router/constrainer"
|
58
|
-
require_relative "rage/router/dsl"
|
59
|
-
require_relative "rage/router/handler_storage"
|
60
|
-
require_relative "rage/router/node"
|
61
|
-
|
62
|
-
require_relative "rage/controller/api"
|
data/rage.gemspec
CHANGED