lennarb 0.1.6 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 133bc5b7fbe787ae7bf9d17f79cddb09d75f3e1d12e99deff891edae698b109a
4
- data.tar.gz: de9d4b466c30c19b1fd84e6d55c162f144904aa09d22d4bc874bb7291eb72ce8
3
+ metadata.gz: 3a9951f0d799cadd7b4c3025eeaa9b050dd3920524b0a256530b4c53bb924a74
4
+ data.tar.gz: 39e78cd19783b98bb9f88d064821207dbc506c94f6742b840bfc3e31ed6568e9
5
5
  SHA512:
6
- metadata.gz: 1aa540d8f1f3d7d82104f441f4d141249485597d34d80072bb2c5df38237ea2651dba35b4f2499f00be7c9d1a94755c2400aefbe102283ff5a0ea3341dc74e97
7
- data.tar.gz: 5660b98b90c019ff4501076845668ddea45210e701d91eae9b99c38a36ee7605511903178e986239934078d22aa8d7156d6efe4c73560e5c4951d7c734fa6f77
6
+ metadata.gz: 9ec6a17703b76f22f9f24f1d356c8bf190ed351d1629deeffaf5b871d3ae5907130d90d9329cc9b51f859659c75732fdb034dc029d81c7faed324979e536b090
7
+ data.tar.gz: 5efe46152e8796c8f07d19d0117da18c7868f07bf472be060de06ae140ff6cccbf69daf9d0b0883584875e600ecf0855ec52cffbef253c277325cbdbd2363d72
data/changelog.md CHANGED
@@ -5,6 +5,72 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.2.0] - 2024-08-01
9
+
10
+ ### Removed
11
+
12
+ - Remove `zeitwerk` gem to load the files in the project.
13
+ - Remove `console` gem to print the logs in the console.
14
+ - Remove `Lenna` module. Now, the `Lennarb` class is the main class of the project.
15
+ - Remove `Middleware` module.
16
+ - Remove `CLI` module.
17
+ - Remove `Cache` module
18
+
19
+ ### Changed
20
+
21
+ - Change `Lennarb::Application` class to `Lennarb` class.
22
+ - Request class and Response class now are in `Lennarb` class
23
+ - Change `Lennarb::Router` class to `Lennarb` class
24
+
25
+ ### Fixed
26
+
27
+ - Improve performance of the RPS (Requests per second), memory and CPU usage. Now the performance is similar to the [Roda](https://github.com/jeremyevans/roda/tree/master).
28
+
29
+ ## [0.1.7] - 2023-23-12
30
+
31
+ ### Added
32
+
33
+ - Add `console` gem to print the logs in the console.
34
+
35
+ - Add CLI module to:
36
+ - Create a new project with `lennarb new` command.
37
+ - Run the server with `lennarb server` command.
38
+
39
+ - Add simple guide to create and run a project with Lennarb. See [guides/command-line/readme.md](guides/command-line/readme.md) for more details.
40
+
41
+ - Add `Reload` middleware to reload the application in development environment. You can import and use this middleware in your application. Ex.
42
+
43
+ ```rb
44
+ # app.rb
45
+
46
+ require 'lenna/middleware/default/reload'
47
+
48
+ app = Lenna::Application.new
49
+
50
+ app.use Lenna::Middleware::Default::Reload
51
+ ```
52
+
53
+ In the next version, this middleware will be available by default in development environment.
54
+
55
+ - Add `root` method to `Lennarb` module to get the root path of the project. Ex.
56
+
57
+ ```rb
58
+ # app.rb
59
+
60
+ Lennarb.root.join('app.rb')
61
+ # => /home/user/project/app.rb
62
+ ```
63
+
64
+ - Add `zeitwerk` gem to load the files in the project.
65
+
66
+ ### Remove
67
+
68
+ - Remove `Logging` and `ErrorHandling` middlewares from any environment. Now, theses middlewares are only available in development environment.
69
+
70
+ ### Changed
71
+
72
+ - Change log level to `fatal` in test environment.
73
+
8
74
  ## [0.1.6] - 2023-21-12
9
75
 
10
76
  ### Changed
@@ -81,16 +147,16 @@ request.params = { name: 'John' }
81
147
  require 'lennarb'
82
148
 
83
149
  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
150
+ app.get '/hello' do |req, res|
151
+ res.status = 200
152
+ res['Content-Type'] = 'text/plain'
153
+ res.body = 'Hello World'
154
+ end
155
+ app.post '/hello' do |req, res|
156
+ res.status = 200
157
+ res['Content-Type'] = 'text/plain'
158
+ res.body = 'Hello World'
159
+ end
94
160
  end
95
161
 
96
162
  run app
data/exe/lenna ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Released under the MIT License.
5
+ # Copyright, 2023, by Aristóteles Coutinho.
6
+
7
+ # Require the main file
8
+ #
9
+ # @private `Since v0.1`
10
+ #
11
+ require 'lennarb'
12
+
13
+ # Show the version
14
+ #
15
+ puts Lennarb::VERSION
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2023-2024, by Aristóteles Coutinho.
5
+
6
+ class Lennarb
7
+ class Request < Rack::Request
8
+ # Initialize the request object
9
+ #
10
+ # @parameter [Hash] env
11
+ # @parameter [Hash] route_params
12
+ #
13
+ # @return [Request]
14
+ #
15
+ def initialize(env, route_params = {})
16
+ super(env)
17
+ @route_params = route_params
18
+ end
19
+
20
+ # Get the request body
21
+ #
22
+ # @return [String]
23
+ def params
24
+ @params ||= super.merge(@route_params)
25
+ end
26
+
27
+ private
28
+
29
+ # Get the query string
30
+ #
31
+ # @return [String]
32
+ #
33
+ def query_params
34
+ @query_params ||= Rack::Utils.parse_nested_query(query_string)
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,138 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2023-2024, by Aristóteles Coutinho.
5
+
6
+ class Lennarb
7
+ class Response
8
+ # @!attribute [rw] status
9
+ # @return [Integer]
10
+ #
11
+ attr_accessor :status
12
+
13
+ # @!attribute [r] body
14
+ # @return [Array]
15
+ #
16
+ attr_reader :body
17
+
18
+ # @!attribute [r] headers
19
+ # @return [Hash]
20
+ #
21
+ attr_reader :headers
22
+
23
+ # @!attribute [r] length
24
+ # @return [Integer]
25
+ #
26
+ attr_reader :length
27
+
28
+ # Constants
29
+ #
30
+ LOCATION = 'location'
31
+ private_constant :LOCATION
32
+
33
+ CONTENT_TYPE = 'content-type'
34
+ private_constant :CONTENT_TYPE
35
+
36
+ CONTENT_LENGTH = 'content-length'
37
+ private_constant :CONTENT_LENGTH
38
+
39
+ ContentType = { HTML: 'text/html', TEXT: 'text/plain', JSON: 'application/json' }.freeze
40
+ private_constant :ContentType
41
+
42
+ # Initialize the response object
43
+ #
44
+ # @return [Response]
45
+ #
46
+ def initialize
47
+ @status = 404
48
+ @headers = {}
49
+ @body = []
50
+ @length = 0
51
+ end
52
+
53
+ # Set the response header
54
+ #
55
+ # @parameter [String] key
56
+ #
57
+ # @return [String] value
58
+ #
59
+ def [](key)
60
+ @headers[key]
61
+ end
62
+
63
+ # Get the response header
64
+ #
65
+ # @parameter [String] key
66
+ # @parameter [String] value
67
+ #
68
+ # @return [String] value
69
+ #
70
+ def []=(key, value)
71
+ @headers[key] = value
72
+ end
73
+
74
+ # Write to the response body
75
+ #
76
+ # @parameter [String] str
77
+ #
78
+ # @return [String] str
79
+ #
80
+ def write(str)
81
+ str = str.to_s
82
+ @length += str.bytesize
83
+ @headers[CONTENT_LENGTH] ||= @length.to_s
84
+ @body << str
85
+ end
86
+
87
+ # Set the response type to text
88
+ #
89
+ # @parameter [String] str
90
+ #
91
+ # @return [String] str
92
+ #
93
+ def text(str)
94
+ @headers[CONTENT_TYPE] = ContentType[:TEXT]
95
+ write(str)
96
+ end
97
+
98
+ # Set the response type to html
99
+ #
100
+ # @parameter [String] str
101
+ #
102
+ # @return [String] str
103
+ #
104
+ def html(str)
105
+ @headers[CONTENT_TYPE] = ContentType[:HTML]
106
+ write(str)
107
+ end
108
+
109
+ # Set the response type to json
110
+ #
111
+ # @parameter [String] str
112
+ #
113
+ # @return [String] str
114
+ #
115
+ def json(str)
116
+ @headers[CONTENT_TYPE] = ContentType[:JSON]
117
+ write(str)
118
+ end
119
+
120
+ # Redirect the response
121
+ #
122
+ # @parameter [String] path
123
+ # @parameter [Integer] status, default: 302
124
+ #
125
+ def redirect(path, status = 302)
126
+ @headers[LOCATION] = path
127
+ @status = status
128
+ end
129
+
130
+ # Finish the response
131
+ #
132
+ # @return [Array] response
133
+ #
134
+ def finish
135
+ [@status, @headers, @body]
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2023-2024, by Aristóteles Coutinho.
5
+
6
+ class Lennarb
7
+ class RouteNode
8
+ attr_accessor :children, :blocks, :param_key
9
+
10
+ # Initialize the route node
11
+ #
12
+ # @return [RouteNode]
13
+ #
14
+ def initialize
15
+ @children = {}
16
+ @blocks = {}
17
+ @param_key = nil
18
+ end
19
+
20
+ # Add a route to the route node
21
+ #
22
+ # @parameter [Array] parts
23
+ # @parameter [String] http_method
24
+ # @parameter [Proc] block
25
+ #
26
+ # @return [void]
27
+ #
28
+ def add_route(parts, http_method, block)
29
+ current_node = self
30
+
31
+ parts.each do |part|
32
+ if part.start_with?(':')
33
+ key = :param
34
+ current_node.children[key] ||= RouteNode.new
35
+ current_node = current_node.children[key]
36
+ current_node.param_key = part[1..].to_sym
37
+ else
38
+ key = part
39
+ current_node.children[key] ||= RouteNode.new
40
+ current_node = current_node.children[key]
41
+ end
42
+ end
43
+
44
+ current_node.blocks[http_method] = block
45
+ end
46
+
47
+ # Match a route to the route node
48
+ #
49
+ # @parameter [Array] parts
50
+ # @parameter [String] http_method
51
+ #
52
+ # @return [Array]
53
+ #
54
+ def match_route(parts, http_method)
55
+ current_node = self
56
+ params = {}
57
+
58
+ parts.each do |part|
59
+ return [nil, nil] unless current_node.children.key?(part) || current_node.children[:param]
60
+
61
+ if current_node.children.key?(part)
62
+ current_node = current_node.children[part]
63
+ else
64
+ param_node = current_node.children[:param]
65
+ params[param_node.param_key] = part
66
+ current_node = param_node
67
+ end
68
+ end
69
+
70
+ [current_node.blocks[http_method], params]
71
+ end
72
+ end
73
+ end
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2023, by Aristóteles Coutinho.
4
+ # Copyright, 2023-2024, by Aristóteles Coutinho.
5
5
 
6
- module Lennarb
7
- VERSION = '0.1.6'
6
+ class Lennarb
7
+ VERSION = '0.2.0'
8
8
 
9
9
  public_constant :VERSION
10
10
  end
data/lib/lennarb.rb CHANGED
@@ -1,15 +1,97 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2023, by Aristóteles Coutinho.
4
+ # Copyright, 2023-2024, by Aristóteles Coutinho.
5
5
 
6
6
  ENV['RACK_ENV'] ||= 'development'
7
7
 
8
- # Extension for Array class
8
+ # Core extensions
9
9
  #
10
- require 'lennarb/array_extensions'
10
+ require 'pathname'
11
+ require 'rack'
11
12
 
12
13
  # Base class for Lennarb
13
14
  #
14
- require 'lenna/application'
15
- require 'lennarb/version'
15
+ require_relative 'lennarb/request'
16
+ require_relative 'lennarb/response'
17
+ require_relative 'lennarb/route_node'
18
+ require_relative 'lennarb/version'
19
+
20
+ class Lennarb
21
+ # Error class
22
+ #
23
+ class LennarbError < StandardError; end
24
+
25
+ # @attribute [r] root
26
+ # @return [RouteNode]
27
+ #
28
+ attr_reader :root
29
+
30
+ # Initialize the application
31
+ #
32
+ # @yield { ... } The application
33
+ #
34
+ # @return [Lennarb]
35
+ #
36
+ def initialize
37
+ @root = RouteNode.new
38
+ yield self if block_given?
39
+ end
40
+
41
+ # Split a path into parts
42
+ #
43
+ # @parameter [String] path
44
+ #
45
+ # @return [Array] parts. Ex. ['users', ':id']
46
+ #
47
+ SplitPath = ->(path) { path.split('/').reject(&:empty?) }
48
+ private_constant :SplitPath
49
+
50
+ # Call the application
51
+ #
52
+ # @parameter [Hash] env
53
+ #
54
+ # @return [Array] response
55
+ #
56
+ def call(env)
57
+ res = Response.new
58
+ http_method = env.fetch('REQUEST_METHOD').to_sym
59
+ parts = SplitPath[env.fetch('PATH_INFO')]
60
+
61
+ block, params = @root.match_route(parts, http_method)
62
+ return [404, { 'content-type' => 'text/plain' }, ['Not Found']] unless block
63
+
64
+ req = Request.new(env, params)
65
+ instance_exec(req, res, &block)
66
+
67
+ res.finish
68
+ end
69
+
70
+ # Add a routes
71
+ #
72
+ # @parameter [String] path
73
+ # @parameter [Proc] block
74
+ #
75
+ # @return [void]
76
+ #
77
+ def get(path, &block) = add_route(path, :GET, block)
78
+ def post(path, &block) = add_route(path, :POST, block)
79
+ def put(path, &block) = add_route(path, :PUT, block)
80
+ def patch(path, &block) = add_route(path, :PATCH, block)
81
+ def delete(path, &block) = add_route(path, :DELETE, block)
82
+
83
+ private
84
+
85
+ # Add a route
86
+ #
87
+ # @parameter [String] path
88
+ # @parameter [String] http_method
89
+ # @parameter [Proc] block
90
+ #
91
+ # @return [void]
92
+ #
93
+ def add_route(path, http_method, block)
94
+ parts = SplitPath[path]
95
+ @root.add_route(parts, http_method, block)
96
+ end
97
+ end
data/license.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # MIT License
2
2
 
3
- Copyright, 2023, by Aristóteles Coutinho.
3
+ Copyright, 2023-2024, by Aristóteles Coutinho.
4
+ Copyright, 2023, by aristotelesbr.
4
5
 
5
6
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
7
  of this software and associated documentation files (the "Software"), to deal
data/readme.md CHANGED
@@ -1,26 +1,43 @@
1
1
  # Lennarb
2
2
 
3
- Lennarb is a experimental lightweight, fast, and modular web framework for Ruby based on Rack.
3
+ Lennarb is a lightweight, fast, and modular web framework for Ruby based on Rack. The **Lennarb** supports Ruby (MRI) 3.0+
4
4
 
5
- ## Usage
5
+ **Basic Usage**
6
+
7
+ ```ruby
8
+ require "lennarb"
9
+
10
+ Lennarb.new do |router|
11
+ router.get("/hello/:name") do |req, res|
12
+ name = req.params[:name]
13
+ res.html("Hello, #{name}!")
14
+ end
15
+ end
16
+ ```
6
17
 
7
- Please see the [project documentation](https://aristotelesbr.github.io/lennarb) for more details.
18
+ ## Performance
8
19
 
9
- - [Getting Started](https://aristotelesbr.github.io/lennarbguides/getting-started/index) - This guide show you how to use the `lennarb`
20
+ ### 1. Requests per Second (RPS)
10
21
 
11
- - [Middlewares](https://aristotelesbr.github.io/lennarbguides/middlewares/index) - This guide shows how to use middlewares in Lennarb.
22
+ | Position | Application | 10 RPS | 100 RPS | 1.000 RPS | 10.000 RPS |
23
+ | -------- | ----------- | ---------- | ---------- | --------- | ---------- |
24
+ | 1 | Lenna | 126.252,36 | 108.086,55 | 87.111,91 | 68.460,64 |
25
+ | 2 | Roda | 123.360,37 | 88.380,56 | 66.990,77 | 48.108,29 |
26
+ | 3 | Syro | 114.105,38 | 80.909,39 | 61.415,86 | 46.639,81 |
27
+ | 4 | Hanami-API | 68.089,18 | 52.851,88 | 40.801,78 | 27.996,00 |
12
28
 
13
- - [Namespace routes](https://aristotelesbr.github.io/lennarbguides/namespace-routes/index) - This guide show you how to use namespace routes.
29
+ This table ranks the routers by the number of requests they can process per second. Higher numbers indicate better performance.
30
+
31
+ Plese see [Performance](https://aristotelesbr.github.io/lennarb/guides/performance/index.html) for more information.
32
+
33
+ ## Usage
14
34
 
15
- ## Contributing
35
+ - [Getting Started](https://aristotelesbr.github.io/lennarb/guides/getting-started/index) - This guide covers getting up and running with **Lennarb**.
16
36
 
17
- We welcome contributions to this project.
37
+ - [Performance](https://aristotelesbr.github.io/lennarb/guides/performance/index.html) - The **Lennarb** is very fast. The following benchmarks were performed on a MacBook Pro (Retina, 13-inch, Early 2013) with 2,7 GHz Intel Core i7 and 8 GB 1867 MHz DDR3. Based on [jeremyevans/r10k](https://github.com/jeremyevans/r10k) using the following [template build](static/r10k/build/lennarb.rb).
18
38
 
19
- 1. Fork it.
20
- 2. Create your feature branch (`git checkout -b my-new-feature`).
21
- 3. Commit your changes (`git commit -am 'Add some feature'`).
22
- 4. Push to the branch (`git push origin my-new-feature`).
23
- 5. Create new Pull Request.
39
+ - [Response](https://aristotelesbr.github.io/lennarb/guides/response/index.html) - This is the response guide.
40
+ The `res` object is used to send a response to the client. The Lennarb use a custom response object to send responses to the client. The `res` object is an instance of `Lennarb::Response`.
24
41
 
25
42
  ### Developer Certificate of Origin
26
43
 
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: 0.1.6
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aristóteles Coutinho
8
8
  autorequire:
9
- bindir: bin
9
+ bindir: exe
10
10
  cert_chain: []
11
- date: 2023-12-21 00:00:00.000000000 Z
11
+ date: 2024-01-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
@@ -48,16 +48,30 @@ dependencies:
48
48
  name: bake
49
49
  requirement: !ruby/object:Gem::Requirement
50
50
  requirements:
51
- - - ">="
51
+ - - "~>"
52
52
  - !ruby/object:Gem::Version
53
53
  version: 0.18.2
54
54
  type: :development
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
- - - ">="
58
+ - - "~>"
59
59
  - !ruby/object:Gem::Version
60
60
  version: 0.18.2
61
+ - !ruby/object:Gem::Dependency
62
+ name: bundler
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '2.2'
68
+ type: :development
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '2.2'
61
75
  - !ruby/object:Gem::Dependency
62
76
  name: covered
63
77
  requirement: !ruby/object:Gem::Requirement
@@ -72,6 +86,20 @@ dependencies:
72
86
  - - "~>"
73
87
  - !ruby/object:Gem::Version
74
88
  version: 0.25.1
89
+ - !ruby/object:Gem::Dependency
90
+ name: minitest
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '5.20'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '5.20'
75
103
  - !ruby/object:Gem::Dependency
76
104
  name: puma
77
105
  requirement: !ruby/object:Gem::Requirement
@@ -86,6 +114,20 @@ dependencies:
86
114
  - - "~>"
87
115
  - !ruby/object:Gem::Version
88
116
  version: '6.4'
117
+ - !ruby/object:Gem::Dependency
118
+ name: rake
119
+ requirement: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '13.0'
124
+ type: :development
125
+ prerelease: false
126
+ version_requirements: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - "~>"
129
+ - !ruby/object:Gem::Version
130
+ version: '13.0'
89
131
  - !ruby/object:Gem::Dependency
90
132
  name: rack-test
91
133
  requirement: !ruby/object:Gem::Requirement
@@ -130,24 +172,17 @@ dependencies:
130
172
  version: 0.33.0
131
173
  description:
132
174
  email:
133
- executables: []
175
+ executables:
176
+ - lenna
134
177
  extensions: []
135
178
  extra_rdoc_files: []
136
179
  files:
137
180
  - changelog.md
138
- - lib/lenna/application.rb
139
- - lib/lenna/middleware/app.rb
140
- - lib/lenna/middleware/default/error_handler.rb
141
- - lib/lenna/middleware/default/logging.rb
142
- - lib/lenna/router.rb
143
- - lib/lenna/router/builder.rb
144
- - lib/lenna/router/cache.rb
145
- - lib/lenna/router/namespace_stack.rb
146
- - lib/lenna/router/request.rb
147
- - lib/lenna/router/response.rb
148
- - lib/lenna/router/route_matcher.rb
181
+ - exe/lenna
149
182
  - lib/lennarb.rb
150
- - lib/lennarb/array_extensions.rb
183
+ - lib/lennarb/request.rb
184
+ - lib/lennarb/response.rb
185
+ - lib/lennarb/route_node.rb
151
186
  - lib/lennarb/version.rb
152
187
  - license.md
153
188
  - readme.md
@@ -168,14 +203,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
168
203
  requirements:
169
204
  - - ">="
170
205
  - !ruby/object:Gem::Version
171
- version: '3.0'
206
+ version: '3.1'
172
207
  required_rubygems_version: !ruby/object:Gem::Requirement
173
208
  requirements:
174
209
  - - ">="
175
210
  - !ruby/object:Gem::Version
176
211
  version: '0'
177
212
  requirements: []
178
- rubygems_version: 3.5.1
213
+ rubygems_version: 3.5.3
179
214
  signing_key:
180
215
  specification_version: 4
181
216
  summary: A lightweight and experimental web framework for Ruby.