lennarb 1.2.0 → 1.3.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 +20 -0
- data/lib/lennarb/plugin.rb +45 -31
- data/lib/lennarb/plugins/hooks.rb +117 -0
- data/lib/lennarb/plugins/mount.rb +66 -0
- data/lib/lennarb/request.rb +76 -37
- data/lib/lennarb/response.rb +133 -133
- data/lib/lennarb/route_node.rb +49 -67
- data/lib/lennarb/version.rb +2 -2
- data/lib/lennarb.rb +138 -124
- data/license.md +1 -2
- metadata +5 -4
- data/lib/lennarb/application/base.rb +0 -283
data/lib/lennarb.rb
CHANGED
@@ -8,9 +8,6 @@
|
|
8
8
|
require 'pathname'
|
9
9
|
require 'rack'
|
10
10
|
|
11
|
-
# Base class for Lennarb
|
12
|
-
#
|
13
|
-
require_relative 'lennarb/application/base'
|
14
11
|
require_relative 'lennarb/plugin'
|
15
12
|
require_relative 'lennarb/request'
|
16
13
|
require_relative 'lennarb/response'
|
@@ -18,127 +15,144 @@ require_relative 'lennarb/route_node'
|
|
18
15
|
require_relative 'lennarb/version'
|
19
16
|
|
20
17
|
class Lennarb
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
# Add a routes
|
85
|
-
#
|
86
|
-
# @parameter [String] path
|
87
|
-
# @parameter [Proc] block
|
88
|
-
#
|
89
|
-
# @returns [void]
|
90
|
-
#
|
91
|
-
def get(path, &block) = add_route(path, :GET, block)
|
92
|
-
def put(path, &block) = add_route(path, :PUT, block)
|
93
|
-
def post(path, &block) = add_route(path, :POST, block)
|
94
|
-
def head(path, &block) = add_route(path, :HEAD, block)
|
95
|
-
def patch(path, &block) = add_route(path, :PATCH, block)
|
96
|
-
def delete(path, &block) = add_route(path, :DELETE, block)
|
97
|
-
def options(path, &block) = add_route(path, :OPTIONS, block)
|
98
|
-
|
99
|
-
# Add plugin to extend the router
|
100
|
-
#
|
101
|
-
# @parameter [String] plugin_name
|
102
|
-
# @parameter [args] *args
|
103
|
-
# @parameter [Block] block
|
104
|
-
#
|
105
|
-
# @returns [void]
|
106
|
-
#
|
107
|
-
def plugin(plugin_name, *, &)
|
108
|
-
return if @_applied_plugins.include?(plugin_name)
|
109
|
-
|
110
|
-
plugin_module = Plugin.load(plugin_name)
|
111
|
-
extend plugin_module::InstanceMethods if defined?(plugin_module::InstanceMethods)
|
112
|
-
self.class.extend plugin_module::ClassMethods if defined?(plugin_module::ClassMethods)
|
113
|
-
plugin_module.setup(self.class, *, &) if plugin_module.respond_to?(:setup)
|
114
|
-
|
115
|
-
@_applied_plugins << plugin_name
|
116
|
-
end
|
117
|
-
|
118
|
-
# Merge the other RouteNode into the current one
|
119
|
-
#
|
120
|
-
# @parameter other [RouteNode] The other RouteNode to merge into the current one
|
121
|
-
#
|
122
|
-
# @return [void]
|
123
|
-
#
|
124
|
-
def merge!(other)
|
125
|
-
raise "Expected a Lennarb instance, got #{other.class}" unless other.is_a?(Lennarb)
|
126
|
-
|
127
|
-
@_root.merge!(other._root)
|
18
|
+
class LennarbError < StandardError; end
|
19
|
+
|
20
|
+
attr_reader :_root, :_plugins, :_loaded_plugins, :_middlewares, :_app
|
21
|
+
|
22
|
+
def self.use(middleware, *args, &block)
|
23
|
+
@_middlewares ||= []
|
24
|
+
@_middlewares << [middleware, args, block]
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.get(path, &block) = add_route(path, :GET, block)
|
28
|
+
def self.put(path, &block) = add_route(path, :PUT, block)
|
29
|
+
def self.post(path, &block) = add_route(path, :POST, block)
|
30
|
+
def self.head(path, &block) = add_route(path, :HEAD, block)
|
31
|
+
def self.patch(path, &block) = add_route(path, :PATCH, block)
|
32
|
+
def self.delete(path, &block) = add_route(path, :DELETE, block)
|
33
|
+
def self.options(path, &block) = add_route(path, :OPTIONS, block)
|
34
|
+
|
35
|
+
def self.inherited(subclass)
|
36
|
+
super
|
37
|
+
subclass.instance_variable_set(:@_root, RouteNode.new)
|
38
|
+
subclass.instance_variable_set(:@_plugins, [])
|
39
|
+
subclass.instance_variable_set(:@_middlewares, @_middlewares&.dup || [])
|
40
|
+
|
41
|
+
Plugin.load_defaults! if Plugin.load_defaults?
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.plugin(plugin_name, *, &)
|
45
|
+
@_loaded_plugins ||= {}
|
46
|
+
@_plugins ||= []
|
47
|
+
|
48
|
+
return if @_loaded_plugins.key?(plugin_name)
|
49
|
+
|
50
|
+
plugin_module = Plugin.load(plugin_name)
|
51
|
+
plugin_module.configure(self, *, &) if plugin_module.respond_to?(:configure)
|
52
|
+
|
53
|
+
@_loaded_plugins[plugin_name] = plugin_module
|
54
|
+
@_plugins << plugin_name
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.freeze!
|
58
|
+
app = new
|
59
|
+
app.freeze!
|
60
|
+
app
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.add_route(path, http_method, block)
|
64
|
+
@_root ||= RouteNode.new
|
65
|
+
parts = path.split('/').reject(&:empty?)
|
66
|
+
@_root.add_route(parts, http_method, block)
|
67
|
+
end
|
68
|
+
|
69
|
+
private_class_method :add_route
|
70
|
+
|
71
|
+
def initialize
|
72
|
+
@_mutex = Mutex.new
|
73
|
+
@_root = self.class.instance_variable_get(:@_root)&.dup || RouteNode.new
|
74
|
+
@_plugins = self.class.instance_variable_get(:@_plugins)&.dup || []
|
75
|
+
@_loaded_plugins = self.class.instance_variable_get(:@_loaded_plugins)&.dup || {}
|
76
|
+
@_middlewares = self.class.instance_variable_get(:@_middlewares)&.dup || []
|
77
|
+
|
78
|
+
build_app
|
79
|
+
|
80
|
+
yield self if block_given?
|
128
81
|
end
|
129
82
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
83
|
+
def call(env) = @_mutex.synchronize { @_app.call(env) }
|
84
|
+
|
85
|
+
def freeze!
|
86
|
+
return self if @_mounted
|
87
|
+
|
88
|
+
@_root.freeze
|
89
|
+
@_plugins.freeze
|
90
|
+
@_loaded_plugins.freeze
|
91
|
+
@_middlewares.freeze
|
92
|
+
@_app.freeze if @_app.respond_to?(:freeze)
|
93
|
+
self
|
94
|
+
end
|
95
|
+
|
96
|
+
def get(path, &block) = add_route(path, :GET, block)
|
97
|
+
def put(path, &block) = add_route(path, :PUT, block)
|
98
|
+
def post(path, &block) = add_route(path, :POST, block)
|
99
|
+
def head(path, &block) = add_route(path, :HEAD, block)
|
100
|
+
def patch(path, &block) = add_route(path, :PATCH, block)
|
101
|
+
def delete(path, &block) = add_route(path, :DELETE, block)
|
102
|
+
def options(path, &block) = add_route(path, :OPTIONS, block)
|
103
|
+
|
104
|
+
def plugin(plugin_name, *, &)
|
105
|
+
return if @_loaded_plugins.key?(plugin_name)
|
106
|
+
|
107
|
+
plugin_module = Plugin.load(plugin_name)
|
108
|
+
self.class.extend plugin_module::ClassMethods if plugin_module.const_defined?(:ClassMethods)
|
109
|
+
self.class.include plugin_module::InstanceMethods if plugin_module.const_defined?(:InstanceMethods)
|
110
|
+
plugin_module.configure(self, *, &) if plugin_module.respond_to?(:configure)
|
111
|
+
@_loaded_plugins[plugin_name] = plugin_module
|
112
|
+
@_plugins << plugin_name
|
113
|
+
end
|
114
|
+
|
115
|
+
private
|
116
|
+
|
117
|
+
def build_app
|
118
|
+
@_app = method(:process_request)
|
119
|
+
|
120
|
+
@_middlewares.reverse_each do |middleware, args, block|
|
121
|
+
@_app = middleware.new(@_app, *args, &block)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def process_request(env)
|
126
|
+
http_method = env[Rack::REQUEST_METHOD].to_sym
|
127
|
+
parts = env[Rack::PATH_INFO].split('/').reject(&:empty?)
|
128
|
+
|
129
|
+
block, params = @_root.match_route(parts, http_method)
|
130
|
+
return not_found unless block
|
131
|
+
|
132
|
+
res = Response.new
|
133
|
+
req = Request.new(env, params)
|
134
|
+
|
135
|
+
catch(:halt) do
|
136
|
+
instance_exec(req, res, &block)
|
137
|
+
res.finish
|
138
|
+
end
|
139
|
+
rescue StandardError => e
|
140
|
+
handle_error(e)
|
141
|
+
end
|
142
|
+
|
143
|
+
def handle_error(error)
|
144
|
+
case error
|
145
|
+
when ArgumentError
|
146
|
+
[400, { 'content-type' => 'text/plain' }, ["Bad Request: #{error.message}"]]
|
147
|
+
else
|
148
|
+
[500, { 'content-type' => 'text/plain' }, ["Internal Server Error: #{error.message}"]]
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def not_found = [404, { 'content-type' => 'text/plain' }, ['Not Found']]
|
153
|
+
|
154
|
+
def add_route(path, http_method, block)
|
155
|
+
parts = path.split('/').reject(&:empty?)
|
156
|
+
@_root.add_route(parts, http_method, block)
|
157
|
+
end
|
144
158
|
end
|
data/license.md
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# MIT License
|
2
2
|
|
3
|
-
Copyright
|
4
|
-
Copyright, 2023, by aristotelesbr.
|
3
|
+
Copyright (c) 2023-2025 Aristótels Coutinho
|
5
4
|
|
6
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
6
|
of this software and associated documentation files (the "Software"), to deal
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lennarb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aristóteles Coutinho
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-11-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colorize
|
@@ -180,8 +180,9 @@ files:
|
|
180
180
|
- changelog.md
|
181
181
|
- exe/lenna
|
182
182
|
- lib/lennarb.rb
|
183
|
-
- lib/lennarb/application/base.rb
|
184
183
|
- lib/lennarb/plugin.rb
|
184
|
+
- lib/lennarb/plugins/hooks.rb
|
185
|
+
- lib/lennarb/plugins/mount.rb
|
185
186
|
- lib/lennarb/request.rb
|
186
187
|
- lib/lennarb/response.rb
|
187
188
|
- lib/lennarb/route_node.rb
|
@@ -212,7 +213,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
212
213
|
- !ruby/object:Gem::Version
|
213
214
|
version: '0'
|
214
215
|
requirements: []
|
215
|
-
rubygems_version: 3.5.
|
216
|
+
rubygems_version: 3.5.23
|
216
217
|
signing_key:
|
217
218
|
specification_version: 4
|
218
219
|
summary: Lennarb provides a lightweight yet robust solution for web routing in Ruby,
|
@@ -1,283 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Released under the MIT License.
|
4
|
-
# Copyright, 2023-2024, by Aristóteles Coutinho.
|
5
|
-
|
6
|
-
require 'colorize'
|
7
|
-
|
8
|
-
class Lennarb
|
9
|
-
module Application
|
10
|
-
class Base
|
11
|
-
# @attribute [r] _route
|
12
|
-
# @returns [RouteNode]
|
13
|
-
#
|
14
|
-
# @attribute [r] _middlewares
|
15
|
-
# @returns [Array]
|
16
|
-
#
|
17
|
-
# @attribute [r] _global_after_hooks
|
18
|
-
# @returns [Array]
|
19
|
-
#
|
20
|
-
# @attribute [r] _global_before_hooks
|
21
|
-
# @returns [Array]
|
22
|
-
#
|
23
|
-
# @attribute [r] _after_hooks
|
24
|
-
# @returns [RouteNode]
|
25
|
-
#
|
26
|
-
# @attribute [r] _before_hooks
|
27
|
-
# @returns [RouteNode]
|
28
|
-
#
|
29
|
-
attr_accessor :_route, :_global_after_hooks, :_global_before_hooks, :_after_hooks, :_before_hooks
|
30
|
-
|
31
|
-
# Initialize the Application
|
32
|
-
#
|
33
|
-
# @returns [Base]
|
34
|
-
#
|
35
|
-
class << self
|
36
|
-
def inherited(subclass)
|
37
|
-
super
|
38
|
-
_applications << subclass
|
39
|
-
subclass.instance_variable_set(:@_route, Lennarb.new)
|
40
|
-
subclass.instance_variable_set(:@_middlewares, [])
|
41
|
-
subclass.instance_variable_set(:@_global_after_hooks, [])
|
42
|
-
subclass.instance_variable_set(:@_global_before_hooks, [])
|
43
|
-
subclass.instance_variable_set(:@_after_hooks, Lennarb::RouteNode.new)
|
44
|
-
subclass.instance_variable_set(:@_before_hooks, Lennarb::RouteNode.new)
|
45
|
-
end
|
46
|
-
|
47
|
-
def get(...) = @_route.get(...)
|
48
|
-
def put(...) = @_route.put(...)
|
49
|
-
def post(...) = @_route.post(...)
|
50
|
-
def head(...) = @_route.head(...)
|
51
|
-
def match(...) = @_route.match(...)
|
52
|
-
def patch(...) = @_route.patch(...)
|
53
|
-
def delete(...) = @_route.delete(...)
|
54
|
-
def options(...) = @_route.options(...)
|
55
|
-
|
56
|
-
# @returns [Array] middlewares
|
57
|
-
#
|
58
|
-
def _middlewares = @_middlewares ||= []
|
59
|
-
|
60
|
-
# @returns [Array] applications
|
61
|
-
#
|
62
|
-
def _applications = @_applications ||= []
|
63
|
-
|
64
|
-
# Mount a controller
|
65
|
-
#
|
66
|
-
# @parameter [Class] controller
|
67
|
-
#
|
68
|
-
def mount(controller_class)
|
69
|
-
_applications << controller_class
|
70
|
-
puts "Mounted controller: #{controller_class}"
|
71
|
-
end
|
72
|
-
|
73
|
-
# Use a middleware
|
74
|
-
#
|
75
|
-
# @parameter [Object] middleware
|
76
|
-
# @parameter [Array] args
|
77
|
-
# @parameter [Block] block
|
78
|
-
#
|
79
|
-
# @returns [Array] middlewares
|
80
|
-
#
|
81
|
-
def use(middleware, *args, &block)
|
82
|
-
@_middlewares << [middleware, args, block]
|
83
|
-
end
|
84
|
-
|
85
|
-
# Add a before hook
|
86
|
-
#
|
87
|
-
# @parameter [String] path
|
88
|
-
# @parameter [Block] block
|
89
|
-
#
|
90
|
-
def before(path = nil, &block)
|
91
|
-
if path
|
92
|
-
parts = path.split('/').reject(&:empty?)
|
93
|
-
@_before_hooks.add_route(parts, :before, block)
|
94
|
-
else
|
95
|
-
@_global_before_hooks << block
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
# Add a after hook
|
100
|
-
#
|
101
|
-
# @parameter [String] path
|
102
|
-
# @parameter [Block] block
|
103
|
-
#
|
104
|
-
def after(path = nil, &block)
|
105
|
-
if path
|
106
|
-
parts = path.split('/').reject(&:empty?)
|
107
|
-
@_after_hooks.add_route(parts, :after, block)
|
108
|
-
else
|
109
|
-
@_global_after_hooks << block
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
# Run the Application
|
114
|
-
#
|
115
|
-
# @returns [Base] self
|
116
|
-
#
|
117
|
-
# When you use this method, the application will be frozen. And you can't add more routes after that.
|
118
|
-
# This method is used to run the application in a Rack server so, you can use the `rackup` command
|
119
|
-
# to run the application.
|
120
|
-
# Ex. rackup -p 3000
|
121
|
-
# This command will use the following middleware:
|
122
|
-
# - Rack::ShowExceptions
|
123
|
-
# - Rack::MethodOverride
|
124
|
-
# - Rack::Head
|
125
|
-
# - Rack::ContentLength
|
126
|
-
#
|
127
|
-
def run!
|
128
|
-
stack = Rack::Builder.new
|
129
|
-
|
130
|
-
use Rack::ShowExceptions if test? || development?
|
131
|
-
use Rack::MethodOverride
|
132
|
-
use Rack::Head
|
133
|
-
use Rack::ContentLength
|
134
|
-
|
135
|
-
_middlewares.each do |(middleware, args, block)|
|
136
|
-
stack.use(middleware, *args, &block)
|
137
|
-
end
|
138
|
-
|
139
|
-
_applications.each do |app|
|
140
|
-
app_route = app.instance_variable_get(:@_route)
|
141
|
-
|
142
|
-
app_after_hooks = app.instance_variable_get(:@_after_hooks)
|
143
|
-
app_before_hooks = app.instance_variable_get(:@_before_hooks)
|
144
|
-
global_after_hooks = app.instance_variable_get(:@_global_after_hooks)
|
145
|
-
global_before_hooks = app.instance_variable_get(:@_global_before_hooks)
|
146
|
-
|
147
|
-
@_route.merge!(app_route)
|
148
|
-
@_before_hooks.merge!(app_before_hooks)
|
149
|
-
@_after_hooks.merge!(app_after_hooks)
|
150
|
-
|
151
|
-
@_global_before_hooks.concat(global_before_hooks)
|
152
|
-
@_global_after_hooks.concat(global_after_hooks)
|
153
|
-
end
|
154
|
-
|
155
|
-
stack.run ->(env) do
|
156
|
-
catch(:halt) do
|
157
|
-
execute_hooks(@_before_hooks, env, :before)
|
158
|
-
res = @_route.call(env)
|
159
|
-
execute_hooks(@_after_hooks, env, :after)
|
160
|
-
res
|
161
|
-
rescue StandardError => e
|
162
|
-
render_error if production?
|
163
|
-
|
164
|
-
puts e.message.red
|
165
|
-
puts e.backtrace
|
166
|
-
raise e
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
@_route.freeze!
|
171
|
-
stack.to_app
|
172
|
-
end
|
173
|
-
|
174
|
-
def test? = ENV['RACK_ENV'] == 'test' || ENV['LENNARB_ENV'] == 'test'
|
175
|
-
def production? = ENV['RACK_ENV'] == 'production' || ENV['LENNARB_ENV'] == 'production'
|
176
|
-
def development? = ENV['RACK_ENV'] == 'development' || ENV['LENNARB_ENV'] == 'development'
|
177
|
-
|
178
|
-
# Render a not found
|
179
|
-
#
|
180
|
-
# @returns [void]
|
181
|
-
#
|
182
|
-
def render_not_found(content = nil)
|
183
|
-
default = File.exist?('public/404.html')
|
184
|
-
body = content || default || 'Not Found'
|
185
|
-
throw :halt, [404, { 'content-type' => 'text/html' }, [body]]
|
186
|
-
end
|
187
|
-
|
188
|
-
# Render an error
|
189
|
-
#
|
190
|
-
# @returns [void]
|
191
|
-
#
|
192
|
-
def render_error(content = nil)
|
193
|
-
default = File.exist?('public/500.html')
|
194
|
-
body = content || default || 'Internal Server Error'
|
195
|
-
throw :halt, [500, { 'content-type' => 'text/html' }, [body]]
|
196
|
-
end
|
197
|
-
|
198
|
-
# Redirect to a path
|
199
|
-
#
|
200
|
-
# @parameter [String] path
|
201
|
-
# @parameter [Integer] status default is 302
|
202
|
-
#
|
203
|
-
def redirect(path, status = 302) = throw :halt, [status, { 'location' => path }, []]
|
204
|
-
|
205
|
-
# Include a plugin in the application
|
206
|
-
#
|
207
|
-
# @parameter [String] plugin_name
|
208
|
-
# @parameter [Array] args
|
209
|
-
# @parameter [Block] block
|
210
|
-
#
|
211
|
-
# @returns [void]
|
212
|
-
#
|
213
|
-
def plugin(plugin_name, *, &)
|
214
|
-
@_route.plugin(plugin_name, *, &)
|
215
|
-
plugin_module = @_route.class::Plugin.load(plugin_name)
|
216
|
-
|
217
|
-
include plugin_module::InstanceMethods if plugin_module.const_defined?(:InstanceMethods)
|
218
|
-
extend plugin_module::ClassMethods if plugin_module.const_defined?(:ClassMethods)
|
219
|
-
end
|
220
|
-
|
221
|
-
private
|
222
|
-
|
223
|
-
# Execute the hooks
|
224
|
-
#
|
225
|
-
# @parameter [RouteNode] hook_route
|
226
|
-
# @parameter [Hash] env
|
227
|
-
# @parameter [Symbol] action
|
228
|
-
#
|
229
|
-
# @returns [void]
|
230
|
-
#
|
231
|
-
def execute_hooks(hook_route, env, action)
|
232
|
-
execute_global_hooks(env, action)
|
233
|
-
|
234
|
-
execute_route_hooks(hook_route, env, action)
|
235
|
-
end
|
236
|
-
|
237
|
-
# Execute the global hooks
|
238
|
-
#
|
239
|
-
# @parameter [Hash] env
|
240
|
-
# @parameter [Symbol] action
|
241
|
-
#
|
242
|
-
# @returns [void]
|
243
|
-
#
|
244
|
-
def execute_global_hooks(env, action)
|
245
|
-
global_hooks = action == :before ? @_global_before_hooks : @_global_after_hooks
|
246
|
-
global_hooks.each { |hook| hook.call(env) }
|
247
|
-
end
|
248
|
-
|
249
|
-
# Execute the route hooks
|
250
|
-
#
|
251
|
-
# @parameter [RouteNode] hook_route
|
252
|
-
# @parameter [Hash] env
|
253
|
-
# @parameter [Symbol] action
|
254
|
-
#
|
255
|
-
# @returns [void]
|
256
|
-
#
|
257
|
-
def execute_route_hooks(hook_route, env, action)
|
258
|
-
parts = parse_path(env)
|
259
|
-
return unless parts
|
260
|
-
|
261
|
-
block, = hook_route.match_route(parts, action)
|
262
|
-
block&.call(env)
|
263
|
-
end
|
264
|
-
|
265
|
-
# Parse the path
|
266
|
-
#
|
267
|
-
# @parameter [Hash] env
|
268
|
-
#
|
269
|
-
# @returns [Array] parts
|
270
|
-
#
|
271
|
-
def parse_path(env) = env[Rack::PATH_INFO]&.split('/')&.reject(&:empty?)
|
272
|
-
|
273
|
-
# Check if the request is a HTML request
|
274
|
-
#
|
275
|
-
# @parameter [Hash] env
|
276
|
-
#
|
277
|
-
# @returns [Boolean]
|
278
|
-
#
|
279
|
-
def html_request?(env) = env['HTTP_ACCEPT']&.include?('text/html')
|
280
|
-
end
|
281
|
-
end
|
282
|
-
end
|
283
|
-
end
|