rage-rb 1.4.0 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/README.md +1 -1
- data/lib/rage/cli.rb +1 -3
- data/lib/rage/controller/api.rb +22 -0
- data/lib/rage/router/backend.rb +10 -4
- data/lib/rage/router/dsl.rb +40 -0
- data/lib/rage/router/util.rb +15 -0
- data/lib/rage/templates/config.ru +0 -1
- data/lib/rage/version.rb +1 -1
- data/lib/rage-rb.rb +21 -23
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 24a5bc4310d226a4072c06ac0a3cb015eb52163e7c37fc85aced61f5705b6ef5
|
4
|
+
data.tar.gz: 8bedd5b522c64c945a44fa4cb97e19f48d5b3a3aa46bb5687183c4cf3eac75f3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 10feb1fe42789d8470ecf9d7754be26b58db2f160f24c7e82aac8a831a5c4b828d297e01c2535b8e914d167de2bcf40a843b1964c5d1f3102ef4429016fefabd
|
7
|
+
data.tar.gz: 87c3ee06201e71f691b7158f911c0cfbf7763d2021801d298885c890772082a934d91fdb5df8c0f6bf65110acd480fd839ef19d6e9adc39d1c78d165a0e2701f
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,21 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [1.5.0] - 2024-05-08
|
4
|
+
|
5
|
+
### Added
|
6
|
+
|
7
|
+
- Allow to have both Rails and Rage controllers in one application (#83).
|
8
|
+
- Add `authenticate_or_request_with_http_token` (#85).
|
9
|
+
- Add the `member` and `controller` route helpers (#86).
|
10
|
+
|
11
|
+
### Changed
|
12
|
+
|
13
|
+
- Deprecate `Rage.load_middlewares` (#83).
|
14
|
+
|
15
|
+
### Fixed
|
16
|
+
|
17
|
+
- Correctly init console in Rails mode (credit to [efibootmgr](https://github.com/efibootmgr)) (#84).
|
18
|
+
|
3
19
|
## [1.4.0] - 2024-05-01
|
4
20
|
|
5
21
|
### Added
|
data/README.md
CHANGED
@@ -155,8 +155,8 @@ Status | Changes
|
|
155
155
|
:white_check_mark: | ~~Add request logging.~~
|
156
156
|
:white_check_mark: | ~~Automatic code reloading in development with Zeitwerk.~~
|
157
157
|
:white_check_mark: | ~~Support conditional get with `etag` and `last_modified`.~~
|
158
|
+
:white_check_mark: | ~~Expose the `cookies` and `session` objects.~~
|
158
159
|
⏳ | Expose the `send_data` and `send_file` methods.
|
159
|
-
⏳ | Expose the `cookies` and `session` objects.
|
160
160
|
⏳ | Implement Iodine-based equivalent of Action Cable.
|
161
161
|
|
162
162
|
## Development
|
data/lib/rage/cli.rb
CHANGED
@@ -116,10 +116,8 @@ module Rage
|
|
116
116
|
def environment
|
117
117
|
require File.expand_path("config/application.rb", Dir.pwd)
|
118
118
|
|
119
|
-
# in Rails mode we delegate code loading to Rails, and thus need
|
120
|
-
# to manually load application code for CLI utilities to work
|
121
119
|
if Rage.config.internal.rails_mode
|
122
|
-
require "
|
120
|
+
require File.expand_path("config/environment.rb", Dir.pwd)
|
123
121
|
end
|
124
122
|
end
|
125
123
|
|
data/lib/rage/controller/api.rb
CHANGED
@@ -428,6 +428,28 @@ class RageController::API
|
|
428
428
|
yield token
|
429
429
|
end
|
430
430
|
|
431
|
+
# Authenticate using an HTTP Bearer token, or otherwise render an HTTP header requesting the client to send a
|
432
|
+
# Bearer token. For the authentication to be considered successful, the block should return a non-nil value.
|
433
|
+
#
|
434
|
+
# @yield [token] token value extracted from the `Authorization` header
|
435
|
+
# @example
|
436
|
+
# before_action :authenticate
|
437
|
+
#
|
438
|
+
# def authenticate
|
439
|
+
# authenticate_or_request_with_http_token do |token|
|
440
|
+
# ApiToken.find_by(token: token)
|
441
|
+
# end
|
442
|
+
# end
|
443
|
+
def authenticate_or_request_with_http_token
|
444
|
+
authenticate_with_http_token { |token| yield(token) } || request_http_token_authentication
|
445
|
+
end
|
446
|
+
|
447
|
+
# Render an HTTP header requesting the client to send a Bearer token for authentication.
|
448
|
+
def request_http_token_authentication
|
449
|
+
headers["Www-Authenticate"] = "Token"
|
450
|
+
render plain: "HTTP Token: Access denied.", status: 401
|
451
|
+
end
|
452
|
+
|
431
453
|
if !defined?(::ActionController::Parameters)
|
432
454
|
# Get the request data. The keys inside the hash are symbols, so `params.keys` returns an array of `Symbol`.<br>
|
433
455
|
# You can also load Strong Params to have Rage automatically wrap `params` in an instance of `ActionController::Parameters`.<br>
|
data/lib/rage/router/backend.rb
CHANGED
@@ -68,12 +68,18 @@ class Rage::Router::Backend
|
|
68
68
|
raise "Invalid route handler format, expected to match the 'controller#action' pattern" unless handler =~ STRING_HANDLER_REGEXP
|
69
69
|
|
70
70
|
controller, action = Rage::Router::Util.path_to_class($1), $2
|
71
|
-
run_action_method_name = controller.__register_action(action.to_sym)
|
72
71
|
|
73
|
-
|
74
|
-
|
72
|
+
if controller.ancestors.include?(RageController::API)
|
73
|
+
run_action_method_name = controller.__register_action(action.to_sym)
|
75
74
|
|
76
|
-
|
75
|
+
meta[:controller] = $1
|
76
|
+
meta[:action] = $2
|
77
|
+
|
78
|
+
handler = eval("->(env, params) { #{controller}.new(env, params).#{run_action_method_name} }")
|
79
|
+
else
|
80
|
+
# this is a Rails controller; notify `Rage::Router::Util::Cascade` to forward the request to Rails
|
81
|
+
handler = ->(_, _) { [404, { "X-Cascade" => "pass" }, []] }
|
82
|
+
end
|
77
83
|
else
|
78
84
|
raise "Non-string route handler should respond to `call`" unless handler.respond_to?(:call)
|
79
85
|
# while regular handlers are expected to be called with the `env` and `params` objects,
|
data/lib/rage/router/dsl.rb
CHANGED
@@ -209,6 +209,7 @@ class Rage::Router::DSL
|
|
209
209
|
# @param [Hash] opts scope options.
|
210
210
|
# @option opts [String] :module module option
|
211
211
|
# @option opts [String] :path path option
|
212
|
+
# @option opts [String] :controller controller option
|
212
213
|
# @example Route `/photos` to `Api::PhotosController`
|
213
214
|
# scope module: "api" do
|
214
215
|
# get "photos", to: "photos#index"
|
@@ -217,6 +218,11 @@ class Rage::Router::DSL
|
|
217
218
|
# scope path: "admin" do
|
218
219
|
# get "photos", to: "photos#index"
|
219
220
|
# end
|
221
|
+
# @example Route `/like` to `photos#like` and `/dislike` to `photos#dislike`
|
222
|
+
# scope controller: "photos" do
|
223
|
+
# post "like"
|
224
|
+
# post "dislike"
|
225
|
+
# end
|
220
226
|
# @example Nested calls
|
221
227
|
# scope module: "admin" do
|
222
228
|
# get "photos", to: "photos#index"
|
@@ -252,6 +258,19 @@ class Rage::Router::DSL
|
|
252
258
|
@defaults.pop
|
253
259
|
end
|
254
260
|
|
261
|
+
# Scopes routes to a specific controller.
|
262
|
+
#
|
263
|
+
# @example
|
264
|
+
# controller "photos" do
|
265
|
+
# post "like"
|
266
|
+
# post "dislike"
|
267
|
+
# end
|
268
|
+
def controller(controller, &block)
|
269
|
+
@controllers << controller
|
270
|
+
instance_eval &block
|
271
|
+
@controllers.pop
|
272
|
+
end
|
273
|
+
|
255
274
|
# Add a route to the collection.
|
256
275
|
#
|
257
276
|
# @example Add a `photos/search` path instead of `photos/:photo_id/search`
|
@@ -267,6 +286,27 @@ class Rage::Router::DSL
|
|
267
286
|
@path_prefixes = orig_path_prefixes
|
268
287
|
end
|
269
288
|
|
289
|
+
# Add a member route.
|
290
|
+
#
|
291
|
+
# @example Add a `photos/:id/preview` path instead of `photos/:photo_id/preview`
|
292
|
+
# resources :photos do
|
293
|
+
# member do
|
294
|
+
# get "preview"
|
295
|
+
# end
|
296
|
+
# end
|
297
|
+
def member(&block)
|
298
|
+
orig_path_prefixes = @path_prefixes
|
299
|
+
|
300
|
+
if (param_prefix = @path_prefixes.last)&.start_with?(":") && @controllers.any?
|
301
|
+
member_prefix = param_prefix.delete_prefix(":#{to_singular(@controllers.last)}_")
|
302
|
+
@path_prefixes = [*@path_prefixes[0...-1], ":#{member_prefix}"]
|
303
|
+
end
|
304
|
+
|
305
|
+
instance_eval &block
|
306
|
+
|
307
|
+
@path_prefixes = orig_path_prefixes
|
308
|
+
end
|
309
|
+
|
270
310
|
# Automatically create REST routes for a resource.
|
271
311
|
#
|
272
312
|
# @example Create five REST routes, all mapping to the `Photos` controller:
|
data/lib/rage/router/util.rb
CHANGED
@@ -30,4 +30,19 @@ class Rage::Router::Util
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
end
|
33
|
+
|
34
|
+
# @private
|
35
|
+
class Cascade
|
36
|
+
def initialize(rage_app, rails_app)
|
37
|
+
@rage_app = rage_app
|
38
|
+
@rails_app = rails_app
|
39
|
+
end
|
40
|
+
|
41
|
+
def call(env)
|
42
|
+
result = @rage_app.call(env)
|
43
|
+
return result if result[0] == :__http_defer__ || result[1]["X-Cascade".freeze] != "pass".freeze
|
44
|
+
|
45
|
+
@rails_app.call(env)
|
46
|
+
end
|
47
|
+
end
|
33
48
|
end
|
data/lib/rage/version.rb
CHANGED
data/lib/rage-rb.rb
CHANGED
@@ -7,7 +7,25 @@ require "pathname"
|
|
7
7
|
|
8
8
|
module Rage
|
9
9
|
def self.application
|
10
|
-
Application.new(__router)
|
10
|
+
app = Application.new(__router)
|
11
|
+
|
12
|
+
config.middleware.middlewares.reverse.inject(app) do |next_in_chain, (middleware, args, block)|
|
13
|
+
# in Rails compatibility mode we first check if the middleware is a part of the Rails middleware stack;
|
14
|
+
# if it is - it is expected to be built using `ActionDispatch::MiddlewareStack::Middleware#build`
|
15
|
+
if Rage.config.internal.rails_mode
|
16
|
+
rails_middleware = Rails.application.config.middleware.middlewares.find { |m| m.name == middleware.name }
|
17
|
+
end
|
18
|
+
|
19
|
+
if rails_middleware
|
20
|
+
rails_middleware.build(next_in_chain)
|
21
|
+
else
|
22
|
+
middleware.new(next_in_chain, *args, &block)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.multi_application
|
28
|
+
Rage::Router::Util::Cascade.new(application, Rails.application)
|
11
29
|
end
|
12
30
|
|
13
31
|
def self.routes
|
@@ -43,28 +61,8 @@ module Rage
|
|
43
61
|
@logger ||= config.logger
|
44
62
|
end
|
45
63
|
|
46
|
-
def self.load_middlewares(
|
47
|
-
|
48
|
-
# in Rails compatibility mode we first check if the middleware is a part of the Rails middleware stack;
|
49
|
-
# if it is - it is expected to be built using `ActionDispatch::MiddlewareStack::Middleware#build`, but Rack
|
50
|
-
# expects the middleware to respond to `#new`, so we wrap the middleware into a helper module
|
51
|
-
if Rage.config.internal.rails_mode
|
52
|
-
rails_middleware = Rails.application.config.middleware.middlewares.find { |m| m.name == middleware.name }
|
53
|
-
if rails_middleware
|
54
|
-
wrapper = Module.new do
|
55
|
-
extend self
|
56
|
-
attr_accessor :middleware
|
57
|
-
def new(app, *, &)
|
58
|
-
middleware.build(app)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
wrapper.middleware = rails_middleware
|
62
|
-
middleware = wrapper
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
rack_builder.use(middleware, *args, &block)
|
67
|
-
end
|
64
|
+
def self.load_middlewares(_)
|
65
|
+
puts "`Rage.load_middlewares` is deprecated and has been merged into `Rage.application`. Please remove this call."
|
68
66
|
end
|
69
67
|
|
70
68
|
def self.code_loader
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rage-rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Roman Samoilov
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-05-
|
11
|
+
date: 2024-05-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|