lennarb 0.1.5 → 0.1.6
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 +165 -0
- data/lib/lenna/application.rb +53 -0
- data/lib/lenna/middleware/app.rb +107 -92
- data/lib/lenna/middleware/default/error_handler.rb +184 -179
- data/lib/lenna/middleware/default/logging.rb +79 -81
- data/lib/lenna/router/builder.rb +111 -86
- data/lib/lenna/router/cache.rb +44 -30
- data/lib/lenna/router/namespace_stack.rb +66 -62
- data/lib/lenna/router/request.rb +125 -101
- data/lib/lenna/router/response.rb +505 -375
- data/lib/lenna/router/route_matcher.rb +56 -57
- data/lib/lenna/router.rb +186 -154
- data/lib/lennarb/array_extensions.rb +25 -11
- data/lib/lennarb/version.rb +5 -2
- data/lib/lennarb.rb +8 -1
- data/license.md +21 -0
- data/readme.md +31 -0
- metadata +64 -56
- data/CHANGELOG.md +0 -62
- data/LICENCE +0 -24
- data/README.md +0 -229
- data/lib/lenna/base.rb +0 -52
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 133bc5b7fbe787ae7bf9d17f79cddb09d75f3e1d12e99deff891edae698b109a
|
4
|
+
data.tar.gz: de9d4b466c30c19b1fd84e6d55c162f144904aa09d22d4bc874bb7291eb72ce8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1aa540d8f1f3d7d82104f441f4d141249485597d34d80072bb2c5df38237ea2651dba35b4f2499f00be7c9d1a94755c2400aefbe102283ff5a0ea3341dc74e97
|
7
|
+
data.tar.gz: 5660b98b90c019ff4501076845668ddea45210e701d91eae9b99c38a36ee7605511903178e986239934078d22aa8d7156d6efe4c73560e5c4951d7c734fa6f77
|
data/changelog.md
ADDED
@@ -0,0 +1,165 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
7
|
+
|
8
|
+
## [0.1.6] - 2023-21-12
|
9
|
+
|
10
|
+
### Changed
|
11
|
+
|
12
|
+
- Update `README.md` with the new features. Move examples to `guides` folder.
|
13
|
+
- Replace `rubocop` to `standard` gem to lint the code.
|
14
|
+
- Move `puma` gem to development dependencies.
|
15
|
+
- Use tabs instead of spaces to indent the code.
|
16
|
+
- Add default middlewares to `Lennarb::Router` class. Now, the `Lennarb::Router` class has the following middlewares by default:
|
17
|
+
|
18
|
+
- `Lennarb::Middleware::Default::Logging`
|
19
|
+
- `Lennarb::Middleware::Default::ErrorHandling`
|
20
|
+
|
21
|
+
- Replace `assign_status` to `=` on Response
|
22
|
+
|
23
|
+
```rb
|
24
|
+
response.status = 200
|
25
|
+
```
|
26
|
+
|
27
|
+
- Rename `Lenna::Base` to `Lenna::Application` and accept a block to build the routes. Ex.
|
28
|
+
|
29
|
+
```rb
|
30
|
+
Lenna::Application.new do |app|
|
31
|
+
app.get '/hello' do |req, res|
|
32
|
+
res.status = 200
|
33
|
+
res['Content-Type'] = 'text/plain'
|
34
|
+
res.body = 'Hello World'
|
35
|
+
end
|
36
|
+
app.post '/hello' do |req, res|
|
37
|
+
res.status = 200
|
38
|
+
res['Content-Type'] = 'text/plain'
|
39
|
+
res.body = 'Hello World'
|
40
|
+
end
|
41
|
+
end
|
42
|
+
```
|
43
|
+
|
44
|
+
- The Middleware app now implements [Singleton](https://ruby-doc.org/stdlib-2.5.1/libdoc/singleton/rdoc/Singleton.html) pattern to manager state.
|
45
|
+
|
46
|
+
### Added
|
47
|
+
|
48
|
+
- Add `standard` gem to lint the code.
|
49
|
+
- Add `maintenance` gropu to `Gemfile` with:
|
50
|
+
- Add `bake-gem` gem to run the tasks.
|
51
|
+
- Add `bake-modernize` gem to update the code to the latest Ruby version.
|
52
|
+
- Add `utopia-project` gem to generate the project.
|
53
|
+
- Add `bake-github-pages` to generate the GitHub Pages.
|
54
|
+
- Add `bake` gem to run the tasks.
|
55
|
+
- Add `puma` gem to run the development server.
|
56
|
+
- Add alias to `assign_header` to `[]=` on Response. Now, you can use:
|
57
|
+
|
58
|
+
```rb
|
59
|
+
response['Content-Type'] = 'application/json'
|
60
|
+
```
|
61
|
+
|
62
|
+
- Add alias to `assign_body` to `:body=` on Response. Now, you can use:
|
63
|
+
|
64
|
+
```rb
|
65
|
+
response.body = 'Hello World'
|
66
|
+
```
|
67
|
+
|
68
|
+
- Add alias to `assign_params` to `:params=` on Request. Now, you can use:
|
69
|
+
|
70
|
+
```rb
|
71
|
+
request.params = { name: 'John' }
|
72
|
+
```
|
73
|
+
|
74
|
+
### Removed
|
75
|
+
|
76
|
+
- Remove `listen` method to run development server. Now, you must be use `.config.ru` file to run the development server. Ex.
|
77
|
+
|
78
|
+
```rb
|
79
|
+
# .config.ru
|
80
|
+
|
81
|
+
require 'lennarb'
|
82
|
+
|
83
|
+
app = Lennarb::Application.new do |app|
|
84
|
+
app.get '/hello' do |req, res|
|
85
|
+
res.status = 200
|
86
|
+
res['Content-Type'] = 'text/plain'
|
87
|
+
res.body = 'Hello World'
|
88
|
+
end
|
89
|
+
app.post '/hello' do |req, res|
|
90
|
+
res.status = 200
|
91
|
+
res['Content-Type'] = 'text/plain'
|
92
|
+
res.body = 'Hello World'
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
run app
|
97
|
+
```
|
98
|
+
|
99
|
+
- Remove Rakefile. Now, you must be use `bake` gem to run the tasks. Ex.
|
100
|
+
|
101
|
+
```sh
|
102
|
+
bundle exec bake test
|
103
|
+
```
|
104
|
+
|
105
|
+
## Bug Fixes
|
106
|
+
|
107
|
+
- Fix default middlewares to `Lennarb::Router` class. Now, the `Lennarb::Router` class has the following middlewares by default:
|
108
|
+
- `Lennarb::Middleware::Default::Logging`
|
109
|
+
- `Lennarb::Middleware::Default::ErrorHandling`
|
110
|
+
|
111
|
+
## [0.1.5] - 2023-25-11
|
112
|
+
|
113
|
+
### Added
|
114
|
+
|
115
|
+
- Add `assign_params` method to Request class
|
116
|
+
|
117
|
+
## [0.1.4] - 2023-25-11
|
118
|
+
|
119
|
+
### Fixed
|
120
|
+
|
121
|
+
- Internal docmentation methods
|
122
|
+
- Fix `post_params` from Resquest router class
|
123
|
+
|
124
|
+
### Added
|
125
|
+
|
126
|
+
- Add basic documentation for usage. See [README.md](README.md) for more details.
|
127
|
+
|
128
|
+
## [0.1.3] - 2023-24-11
|
129
|
+
|
130
|
+
## [0.1.2] - 2023-23-11
|
131
|
+
|
132
|
+
### Added
|
133
|
+
|
134
|
+
- Implemented a specific error handler for Content-Type related errors, enhancing the system's ability to respond appropriately based on whether the request Content-Type is JSON or HTML.
|
135
|
+
|
136
|
+
### Removed
|
137
|
+
|
138
|
+
- Removed the debug gem from development dependencies, streamlining the development environment setup.
|
139
|
+
|
140
|
+
### Fixed
|
141
|
+
|
142
|
+
- Fixed a bug that prevented the correct reading of the Content-Type header in requests, ensuring proper handling of content types.
|
143
|
+
|
144
|
+
## [0.1.1] - 2023-23-11
|
145
|
+
|
146
|
+
### Added
|
147
|
+
|
148
|
+
- Introduced `Array.wrap` extension to the `Array` class for more reliable conversion of objects to arrays within the Lennarb router environment. This method ensures consistent array wrapping of single objects and `nil` values.
|
149
|
+
|
150
|
+
### Changed
|
151
|
+
|
152
|
+
- Refactored the `put_header` method to use the `Array.wrap` method for more predictable header value handling.
|
153
|
+
- Renamed methods to have a consistent `assign_` prefix to standardize the API interface:
|
154
|
+
- `put_header` to `assign_header`
|
155
|
+
- `write_body` to `assign_body`
|
156
|
+
- `set_params` to `assign_params`
|
157
|
+
- `update_status` to `assign_status`
|
158
|
+
|
159
|
+
### Deprecated
|
160
|
+
|
161
|
+
### Removed
|
162
|
+
|
163
|
+
### Fixed
|
164
|
+
|
165
|
+
### Security
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2023, by Aristóteles Coutinho.
|
5
|
+
|
6
|
+
# Internal dependencies
|
7
|
+
#
|
8
|
+
require 'lenna/middleware/default/error_handler'
|
9
|
+
require 'lenna/middleware/default/logging'
|
10
|
+
require 'lenna/router'
|
11
|
+
|
12
|
+
# The Lenna module is used to namespace the framework.
|
13
|
+
#
|
14
|
+
# @public
|
15
|
+
#
|
16
|
+
module Lenna
|
17
|
+
# The base class is used to start the server.
|
18
|
+
#
|
19
|
+
# @public
|
20
|
+
#
|
21
|
+
class Application < Router
|
22
|
+
# Initialize the base class
|
23
|
+
#
|
24
|
+
# @yield { ... } the block to be evaluated in the context of the instance.
|
25
|
+
#
|
26
|
+
# @return [void | Application] Returns the instance if a block is given.
|
27
|
+
#
|
28
|
+
def initialize
|
29
|
+
super
|
30
|
+
yield self if block_given?
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# The base module is used to include the base class.
|
35
|
+
#
|
36
|
+
# @public
|
37
|
+
#
|
38
|
+
module Base
|
39
|
+
def self.included(base)
|
40
|
+
base.extend(ClassMethods)
|
41
|
+
end
|
42
|
+
|
43
|
+
module ClassMethods
|
44
|
+
# Initialize the base module
|
45
|
+
#
|
46
|
+
# @return [Lenna::Application] Returns the instance.
|
47
|
+
#
|
48
|
+
# @public
|
49
|
+
#
|
50
|
+
def app = @app ||= Lenna::Application.new
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/lenna/middleware/app.rb
CHANGED
@@ -1,103 +1,118 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# Released under the MIT License.
|
4
|
+
# Copyright, 2023, by Aristóteles Coutinho.
|
5
|
+
|
6
|
+
require 'singleton'
|
7
|
+
|
3
8
|
module Lenna
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
9
|
+
module Middleware
|
10
|
+
# The MiddlewareManager class is responsible for managing the middlewares.
|
11
|
+
#
|
12
|
+
# @attr global_middlewares [Array] the global middlewares
|
13
|
+
# @attr middleware_chains_cache [Hash] the middleware chains cache
|
14
|
+
#
|
15
|
+
# Middleware chains are cached by action.
|
16
|
+
# The middlewares that are added to a specific route are added to the
|
17
|
+
# global middlewares.
|
18
|
+
#
|
19
|
+
# @private Since `v0.1.0`
|
20
|
+
#
|
21
|
+
class App
|
22
|
+
include Singleton
|
23
|
+
|
24
|
+
# @return [Array] the global middlewares.
|
25
|
+
#
|
26
|
+
attr_accessor :global_middlewares
|
27
|
+
# @return [Hash] the middleware chains cache.
|
28
|
+
#
|
29
|
+
attr_accessor :middleware_chains_cache
|
23
30
|
|
24
|
-
|
25
|
-
|
31
|
+
# This method will initialize the global middlewares and the
|
32
|
+
# middleware chains cache.
|
33
|
+
#
|
34
|
+
# @return [void]
|
35
|
+
#
|
36
|
+
def initialize
|
37
|
+
@global_middlewares = []
|
38
|
+
@middleware_chains_cache = {}
|
39
|
+
end
|
26
40
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
@middleware_chains_cache = {}
|
37
|
-
end
|
41
|
+
# This method is used to reset the global middlewares and the middleware
|
42
|
+
# chains cache.
|
43
|
+
#
|
44
|
+
# @return [void]
|
45
|
+
#
|
46
|
+
def reset!
|
47
|
+
@global_middlewares = []
|
48
|
+
@middleware_chains_cache = {}
|
49
|
+
end
|
38
50
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
@middleware_chains_cache = {}
|
48
|
-
end
|
49
|
-
end
|
51
|
+
# This method is used to add a middleware to the global middlewares.
|
52
|
+
# @parameter middlewares [Array] the middlewares to be used
|
53
|
+
# @return [void]
|
54
|
+
#
|
55
|
+
def use(middlewares)
|
56
|
+
@global_middlewares += Array(middlewares)
|
57
|
+
@middleware_chains_cache = {}
|
58
|
+
end
|
50
59
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
60
|
+
# This method is used to fetch or build the middleware chain for the given
|
61
|
+
# action and route middlewares.
|
62
|
+
#
|
63
|
+
# @parameter action [Proc] the action to be executed
|
64
|
+
# @parameter route_middlewares [Array] the middlewares to be used
|
65
|
+
# @return [Proc] the middleware chain
|
66
|
+
#
|
67
|
+
#
|
68
|
+
def fetch_or_build_middleware_chain(
|
69
|
+
action,
|
70
|
+
route_middlewares,
|
71
|
+
http_method: nil,
|
72
|
+
path: nil
|
73
|
+
)
|
74
|
+
signature =
|
75
|
+
if http_method && path
|
76
|
+
[http_method, path, route_middlewares].hash.to_s
|
77
|
+
else
|
78
|
+
['global', route_middlewares].hash.to_s
|
79
|
+
end
|
63
80
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
end
|
68
|
-
end
|
81
|
+
@middleware_chains_cache[signature] ||=
|
82
|
+
build_middleware_chain(action, route_middlewares)
|
83
|
+
end
|
69
84
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
85
|
+
# This method is used to build the middleware chain for the given action
|
86
|
+
# and middlewares.
|
87
|
+
#
|
88
|
+
# @parameter action [Proc] the action to be executed
|
89
|
+
# @parameter middlewares [Array] the middlewares to be used
|
90
|
+
# @return [Proc] the middleware chain
|
91
|
+
#
|
92
|
+
# ex.
|
93
|
+
# Given the action:
|
94
|
+
# `->(req, res) { res << 'Hello' }` and the
|
95
|
+
# middlewares [mw1, mw2], the middleware
|
96
|
+
# chain will be:
|
97
|
+
# mw1 -> mw2 -> action
|
98
|
+
# The action will be the last middleware in the
|
99
|
+
# chain.
|
100
|
+
#
|
101
|
+
def build_middleware_chain(action, middlewares)
|
102
|
+
all_middlewares = (@global_middlewares + Array(middlewares))
|
88
103
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
104
|
+
all_middlewares.reverse.reduce(action) do |next_middleware, middleware|
|
105
|
+
->(req, res) {
|
106
|
+
middleware.call(
|
107
|
+
req,
|
108
|
+
res,
|
109
|
+
-> {
|
110
|
+
next_middleware.call(req, res)
|
111
|
+
}
|
112
|
+
)
|
113
|
+
}
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
103
118
|
end
|