lennarb 1.4.1 → 1.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/.github/workflows/coverage.yaml +11 -33
- data/.github/workflows/documentation.yaml +32 -13
- data/.gitignore +9 -0
- data/.yardopts +8 -0
- data/CODE_OF_CONDUCT.md +118 -0
- data/CONTRIBUTING.md +155 -0
- data/README.pt-BR.md +147 -0
- data/Rakefile +32 -1
- data/changelog.md +38 -0
- data/gems.rb +3 -22
- data/guides/getting-started/readme.md +11 -7
- data/guides/mounting-applications/readme.md +38 -0
- data/lennarb.gemspec +4 -4
- data/lib/lennarb/app.rb +199 -118
- data/lib/lennarb/base.rb +314 -0
- data/lib/lennarb/config.rb +23 -5
- data/lib/lennarb/constants.rb +12 -0
- data/lib/lennarb/environment.rb +11 -7
- data/lib/lennarb/errors.rb +17 -0
- data/lib/lennarb/helpers.rb +40 -0
- data/lib/lennarb/hooks.rb +71 -0
- data/lib/lennarb/logger.rb +100 -0
- data/lib/lennarb/middleware/request_logger.rb +117 -0
- data/lib/lennarb/middleware_stack.rb +56 -0
- data/lib/lennarb/parameter_filter.rb +76 -0
- data/lib/lennarb/request.rb +51 -41
- data/lib/lennarb/request_handler.rb +39 -9
- data/lib/lennarb/response.rb +23 -21
- data/lib/lennarb/route_node.rb +17 -5
- data/lib/lennarb/routes.rb +43 -47
- data/lib/lennarb/version.rb +2 -2
- data/lib/lennarb.rb +22 -2
- data/logo/lennarb.svg +11 -0
- data/readme.md +176 -35
- metadata +36 -23
- data/lib/lennarb/constansts.rb +0 -6
- data/logo/lennarb.png +0 -0
data/lib/lennarb/response.rb
CHANGED
@@ -1,22 +1,24 @@
|
|
1
1
|
module Lennarb
|
2
|
+
# Response object
|
3
|
+
#
|
2
4
|
class Response
|
3
5
|
# @!attribute [rw] status
|
4
|
-
#
|
6
|
+
# @return [Integer]
|
5
7
|
#
|
6
8
|
attr_accessor :status
|
7
9
|
|
8
10
|
# @!attribute [r] body
|
9
|
-
#
|
11
|
+
# @retrn [Array]
|
10
12
|
#
|
11
13
|
attr_reader :body
|
12
14
|
|
13
15
|
# @!attribute [r] headers
|
14
|
-
#
|
16
|
+
# @retrn [Hash]
|
15
17
|
#
|
16
18
|
attr_reader :headers
|
17
19
|
|
18
20
|
# @!attribute [r] length
|
19
|
-
#
|
21
|
+
# @retrn [Integer]
|
20
22
|
#
|
21
23
|
attr_reader :length
|
22
24
|
|
@@ -33,7 +35,7 @@ module Lennarb
|
|
33
35
|
|
34
36
|
# Initialize the response object
|
35
37
|
#
|
36
|
-
# @
|
38
|
+
# @retrn [Response]
|
37
39
|
#
|
38
40
|
def initialize
|
39
41
|
@status = 200
|
@@ -44,9 +46,9 @@ module Lennarb
|
|
44
46
|
|
45
47
|
# Set the response header
|
46
48
|
#
|
47
|
-
# @
|
49
|
+
# @param [String] key
|
48
50
|
#
|
49
|
-
# @
|
51
|
+
# @retrn [String] value
|
50
52
|
#
|
51
53
|
def [](key)
|
52
54
|
@headers[key]
|
@@ -54,10 +56,10 @@ module Lennarb
|
|
54
56
|
|
55
57
|
# Get the response header
|
56
58
|
#
|
57
|
-
# @
|
58
|
-
# @
|
59
|
+
# @param [String] key
|
60
|
+
# @param [String] value
|
59
61
|
#
|
60
|
-
# @
|
62
|
+
# @retrn [String] value
|
61
63
|
#
|
62
64
|
def []=(key, value)
|
63
65
|
@headers[key] = value
|
@@ -65,9 +67,9 @@ module Lennarb
|
|
65
67
|
|
66
68
|
# Write to the response body
|
67
69
|
#
|
68
|
-
# @
|
70
|
+
# @param [String] str
|
69
71
|
#
|
70
|
-
# @
|
72
|
+
# @retrn [String] str
|
71
73
|
#
|
72
74
|
def write(str)
|
73
75
|
str = str.to_s
|
@@ -78,9 +80,9 @@ module Lennarb
|
|
78
80
|
|
79
81
|
# Set the response type to text
|
80
82
|
#
|
81
|
-
# @
|
83
|
+
# @param [String] str
|
82
84
|
#
|
83
|
-
# @
|
85
|
+
# @retrn [String] str
|
84
86
|
#
|
85
87
|
def text(str)
|
86
88
|
@headers[CONTENT_TYPE] = Lennarb::CONTENT_TYPE[:TEXT]
|
@@ -89,9 +91,9 @@ module Lennarb
|
|
89
91
|
|
90
92
|
# Set the response type to html
|
91
93
|
#
|
92
|
-
# @
|
94
|
+
# @param [String] str
|
93
95
|
#
|
94
|
-
# @
|
96
|
+
# @retrn [String] str
|
95
97
|
#
|
96
98
|
def html(str)
|
97
99
|
@headers[CONTENT_TYPE] = Lennarb::CONTENT_TYPE[:HTML]
|
@@ -100,9 +102,9 @@ module Lennarb
|
|
100
102
|
|
101
103
|
# Set the response type to json
|
102
104
|
#
|
103
|
-
# @
|
105
|
+
# @param [String] str
|
104
106
|
#
|
105
|
-
# @
|
107
|
+
# @retrn [String] str
|
106
108
|
#
|
107
109
|
def json(str)
|
108
110
|
json_str = JSON.generate(str)
|
@@ -116,8 +118,8 @@ module Lennarb
|
|
116
118
|
|
117
119
|
# Redirect the response
|
118
120
|
#
|
119
|
-
# @
|
120
|
-
# @
|
121
|
+
# @param [String] path
|
122
|
+
# @param [Integer] status, default: 302
|
121
123
|
#
|
122
124
|
def redirect(path, status = 302)
|
123
125
|
@headers[LOCATION] = path
|
@@ -128,7 +130,7 @@ module Lennarb
|
|
128
130
|
|
129
131
|
# Finish the response
|
130
132
|
#
|
131
|
-
# @
|
133
|
+
# @retrn [Array] response
|
132
134
|
#
|
133
135
|
def finish
|
134
136
|
[@status, @headers, @body]
|
data/lib/lennarb/route_node.rb
CHANGED
@@ -1,8 +1,20 @@
|
|
1
1
|
module Lennarb
|
2
|
+
# RouteNode is key to the routing system. It is a tree structure that
|
3
|
+
# represents the routes of the application.
|
4
|
+
#
|
5
|
+
# @example
|
6
|
+
# node = RouteNode.new
|
7
|
+
# node.add_route(["foo", "bar"], :GET, -> {})
|
8
|
+
#
|
9
|
+
# @note RouteNode use a trie data structure to store the routes and match them.
|
10
|
+
#
|
2
11
|
class RouteNode
|
3
|
-
DuplicateRouteError = Class.new(StandardError)
|
4
12
|
attr_accessor :static_children, :dynamic_children, :blocks, :param_key
|
5
13
|
|
14
|
+
# Initialize the route node.
|
15
|
+
#
|
16
|
+
# @retrn [RouteNode]
|
17
|
+
#
|
6
18
|
def initialize
|
7
19
|
@blocks = {}
|
8
20
|
@param_key = nil
|
@@ -16,7 +28,7 @@ module Lennarb
|
|
16
28
|
# @param http_method [String] The HTTP method.
|
17
29
|
# @param block [Proc] The block to be executed when the route is matched.
|
18
30
|
#
|
19
|
-
# @
|
31
|
+
# @retrn [void]
|
20
32
|
#
|
21
33
|
def add_route(parts, http_method, block)
|
22
34
|
current_node = self
|
@@ -43,7 +55,7 @@ module Lennarb
|
|
43
55
|
# @param http_method [String] The HTTP method.
|
44
56
|
# @param params [Hash] The parameters of the route.
|
45
57
|
#
|
46
|
-
# @
|
58
|
+
# @retrn [Array<Proc, Hash>]
|
47
59
|
#
|
48
60
|
def match_route(parts, http_method, params: {})
|
49
61
|
if parts.empty?
|
@@ -73,12 +85,12 @@ module Lennarb
|
|
73
85
|
#
|
74
86
|
# @param other [RouteNode] The other route node.
|
75
87
|
#
|
76
|
-
# @
|
88
|
+
# @retrn [void|DuplicateRouteError]
|
77
89
|
#
|
78
90
|
def merge!(other)
|
79
91
|
other.blocks.each do |http_method, block|
|
80
92
|
if @blocks[http_method]
|
81
|
-
raise DuplicateRouteError, "Duplicate route for HTTP method: #{http_method}"
|
93
|
+
raise Lennarb::DuplicateRouteError, "Duplicate route for HTTP method: #{http_method}"
|
82
94
|
end
|
83
95
|
@blocks[http_method] = block
|
84
96
|
end
|
data/lib/lennarb/routes.rb
CHANGED
@@ -1,71 +1,67 @@
|
|
1
1
|
module Lennarb
|
2
|
+
# Routes class for managing application routes
|
3
|
+
#
|
2
4
|
class Routes
|
3
|
-
|
4
|
-
# RouteNode is a trie data structure that stores routes.
|
5
|
-
# see {Lennarb::RouteNode} for more details.
|
5
|
+
# Initialize a new Routes instance
|
6
6
|
#
|
7
|
-
# @
|
8
|
-
|
9
|
-
# node.add_route(["foo", "bar"], :GET, -> {})
|
10
|
-
#
|
11
|
-
def initialize(&)
|
7
|
+
# @return [Routes] The initialized routes instance
|
8
|
+
def initialize
|
12
9
|
@store = RouteNode.new
|
13
|
-
|
10
|
+
@frozen = false
|
14
11
|
end
|
15
12
|
|
16
|
-
# Define
|
17
|
-
#
|
18
|
-
# get, post, put, delete, patch, options, head
|
19
|
-
#
|
13
|
+
# Define a route for each HTTP method
|
20
14
|
HTTP_METHODS.each do |http_method|
|
21
15
|
define_method(http_method.downcase) do |path, &block|
|
16
|
+
fail RoutesFrozenError, "Routes are frozen and cannot be modified" if @frozen
|
22
17
|
register_route(http_method, path, &block)
|
23
18
|
end
|
24
19
|
end
|
25
20
|
|
26
|
-
# Define the root route
|
27
|
-
#
|
28
|
-
# @param [String] path
|
29
|
-
#
|
30
|
-
# @param [Proc] block
|
31
|
-
#
|
32
|
-
# @returns [void]
|
21
|
+
# Define the root route (GET /)
|
33
22
|
#
|
34
|
-
|
23
|
+
# @param block [Proc] Block to execute when route matches
|
24
|
+
# @return [void]
|
25
|
+
def root(&block)
|
26
|
+
get("/", &block)
|
27
|
+
end
|
35
28
|
|
36
|
-
# Match the
|
37
|
-
#
|
38
|
-
# @param [Array<String>] parts
|
39
|
-
#
|
40
|
-
# @param [Symbol] http_method
|
29
|
+
# Match a route with the given path parts and HTTP method
|
41
30
|
#
|
42
|
-
|
31
|
+
# @param parts [Array<String>] Path parts
|
32
|
+
# @param http_method [Symbol] HTTP method
|
33
|
+
# @return [Array(Proc, Hash), nil] Route handler and params, or nil if no match
|
34
|
+
def match_route(parts, http_method)
|
35
|
+
@store.match_route(parts, http_method)
|
36
|
+
end
|
43
37
|
|
44
|
-
# Freeze
|
45
|
-
#
|
46
|
-
# @returns [void]
|
38
|
+
# Freeze the routes to prevent further modification
|
47
39
|
#
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
40
|
+
# @return [self] The frozen routes
|
41
|
+
def freeze
|
42
|
+
@frozen = true
|
43
|
+
@store.freeze
|
44
|
+
self
|
53
45
|
end
|
54
46
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
47
|
+
# Check if the routes are frozen
|
48
|
+
#
|
49
|
+
# @return [Boolean] True if frozen
|
50
|
+
def frozen?
|
51
|
+
@frozen
|
52
|
+
end
|
61
53
|
|
62
|
-
|
63
|
-
define_method(http_method.downcase) do |path, &block|
|
64
|
-
routes.send(http_method.downcase, path, &block)
|
65
|
-
end
|
66
|
-
end
|
54
|
+
private
|
67
55
|
|
68
|
-
|
56
|
+
# Register a route with the specified HTTP method and path
|
57
|
+
#
|
58
|
+
# @param http_method [Symbol] HTTP method (:GET, :POST, etc.)
|
59
|
+
# @param path [String] Route path pattern
|
60
|
+
# @param block [Proc] Block to execute when route matches
|
61
|
+
# @return [void]
|
62
|
+
def register_route(http_method, path, &block)
|
63
|
+
parts = path.split("/").reject(&:empty?)
|
64
|
+
@store.add_route(parts, http_method, block)
|
69
65
|
end
|
70
66
|
end
|
71
67
|
end
|
data/lib/lennarb/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
module Lennarb
|
2
|
-
VERSION = "1.
|
1
|
+
module Lennarb # :nodoc:
|
2
|
+
VERSION = "1.5.0" # :nodoc:
|
3
3
|
end
|
data/lib/lennarb.rb
CHANGED
@@ -4,17 +4,37 @@ require "bundler"
|
|
4
4
|
require "rack"
|
5
5
|
require "json"
|
6
6
|
require "pathname"
|
7
|
+
require "logger"
|
8
|
+
require "securerandom"
|
9
|
+
require "colorize"
|
7
10
|
require "superconfig"
|
8
11
|
|
12
|
+
# Lennarb is a lightweight Ruby web framework based on Rack that offers a high-performance solution for web development. Focused on simplicity, Lennarb delivers essential functionality without unnecessary complexity.
|
13
|
+
# Available in two versions:
|
14
|
+
#
|
15
|
+
# Lennarb::App: Minimal version. Includes only the core components, such as request, response, and route handling.
|
16
|
+
#
|
17
|
+
# Lennarb::Application: Standard version. Include common features like middleware, request handler, and more.
|
18
|
+
#
|
9
19
|
module Lennarb
|
10
|
-
require_relative "lennarb/
|
20
|
+
require_relative "lennarb/constants"
|
11
21
|
require_relative "lennarb/environment"
|
12
22
|
require_relative "lennarb/version"
|
13
|
-
require_relative "lennarb/request_handler"
|
14
23
|
require_relative "lennarb/request"
|
15
24
|
require_relative "lennarb/response"
|
16
25
|
require_relative "lennarb/route_node"
|
17
26
|
require_relative "lennarb/routes"
|
18
27
|
require_relative "lennarb/config"
|
28
|
+
require_relative "lennarb/errors"
|
29
|
+
require_relative "lennarb/middleware_stack"
|
30
|
+
require_relative "lennarb/helpers"
|
31
|
+
require_relative "lennarb/hooks"
|
32
|
+
require_relative "lennarb/request_handler"
|
33
|
+
require_relative "lennarb/base"
|
19
34
|
require_relative "lennarb/app"
|
35
|
+
|
36
|
+
# Middlewares
|
37
|
+
require_relative "lennarb/logger"
|
38
|
+
require_relative "lennarb/parameter_filter"
|
39
|
+
require_relative "lennarb/middleware/request_logger"
|
20
40
|
end
|
data/logo/lennarb.svg
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
<svg width="192" height="56" viewBox="0 0 192 56" fill="none" xmlns="http://www.w3.org/2000/svg">
|
2
|
+
<rect x="142" y="30.9185" width="35.2401" height="35.2401" rx="5" transform="rotate(-45 142 30.9185)" fill="#E8E8E8"/>
|
3
|
+
<path d="M3.1075 3.4H14.3395V27.4H30.1315V37H3.1075V3.4ZM48.6719 21.64C48.5439 20.392 48.1439 19.432 47.4719 18.76C46.7999 18.056 45.9839 17.704 45.0239 17.704C44.0959 17.704 43.3279 18.056 42.7199 18.76C42.1119 19.464 41.7279 20.424 41.5679 21.64H48.6719ZM45.8879 37.624C43.7439 37.624 41.7759 37.304 39.9839 36.664C38.2239 35.992 36.7039 35.064 35.4239 33.88C34.1759 32.696 33.1999 31.272 32.4959 29.608C31.8239 27.944 31.4879 26.088 31.4879 24.04V23.944C31.4879 21.992 31.8239 20.184 32.4959 18.52C33.1679 16.824 34.0959 15.368 35.2799 14.152C36.4639 12.904 37.8719 11.928 39.5039 11.224C41.1679 10.52 42.9919 10.168 44.9759 10.168C47.3119 10.168 49.3279 10.552 51.0239 11.32C52.7519 12.056 54.1759 13.08 55.2959 14.392C56.4159 15.704 57.2479 17.24 57.7919 19C58.3359 20.76 58.6079 22.632 58.6079 24.616C58.6079 24.904 58.6079 25.208 58.6079 25.528C58.6079 25.848 58.5919 26.152 58.5599 26.44H41.7119C42.0959 27.592 42.7199 28.472 43.5839 29.08C44.4479 29.656 45.4719 29.944 46.6559 29.944C47.6479 29.944 48.5599 29.72 49.3919 29.272C50.2559 28.824 51.1199 28.152 51.9839 27.256L57.8399 31.912C56.5279 33.608 54.9119 34.984 52.9919 36.04C51.1039 37.096 48.7359 37.624 45.8879 37.624ZM60.9914 10.792H71.8874V14.44C72.3034 13.896 72.7834 13.368 73.3274 12.856C73.8714 12.344 74.4794 11.896 75.1514 11.512C75.8234 11.096 76.5434 10.776 77.3114 10.552C78.1114 10.296 78.9754 10.168 79.9034 10.168C82.6874 10.168 84.8794 11.016 86.4794 12.712C88.0794 14.408 88.8794 16.744 88.8794 19.72V37H77.9834V23.224C77.9834 22.104 77.6954 21.24 77.1194 20.632C76.5434 19.992 75.8394 19.672 75.0074 19.672C74.1754 19.672 73.4394 19.992 72.7994 20.632C72.1914 21.24 71.8874 22.104 71.8874 23.224V37H60.9914V10.792ZM91.9289 10.792H102.825V14.44C103.241 13.896 103.721 13.368 104.265 12.856C104.809 12.344 105.417 11.896 106.089 11.512C106.761 11.096 107.481 10.776 108.249 10.552C109.049 10.296 109.913 10.168 110.841 10.168C113.625 10.168 115.817 11.016 117.417 12.712C119.017 14.408 119.817 16.744 119.817 19.72V37H108.921V23.224C108.921 22.104 108.633 21.24 108.057 20.632C107.481 19.992 106.777 19.672 105.945 19.672C105.113 19.672 104.377 19.992 103.737 20.632C103.129 21.24 102.825 22.104 102.825 23.224V37H91.9289V10.792ZM134.77 31.336C135.73 31.336 136.53 30.984 137.17 30.28C137.81 29.544 138.13 28.552 138.13 27.304V26.2C137.81 26.072 137.426 25.976 136.978 25.912C136.53 25.816 136.082 25.768 135.634 25.768C134.546 25.768 133.714 26.056 133.138 26.632C132.562 27.176 132.274 27.864 132.274 28.696V28.792C132.274 29.56 132.514 30.184 132.994 30.664C133.474 31.112 134.066 31.336 134.77 31.336ZM130.45 37.624C129.202 37.624 128.05 37.448 126.994 37.096C125.938 36.744 125.026 36.232 124.258 35.56C123.49 34.856 122.898 34.008 122.482 33.016C122.066 32.024 121.858 30.872 121.858 29.56V29.464C121.858 26.84 122.754 24.824 124.546 23.416C126.338 22.008 128.77 21.304 131.842 21.304C132.386 21.304 132.962 21.336 133.57 21.4C134.178 21.432 134.754 21.496 135.298 21.592C135.874 21.688 136.402 21.8 136.882 21.928C137.362 22.024 137.746 22.136 138.034 22.264V21.832C138.034 20.616 137.65 19.688 136.882 19.048C136.114 18.376 134.882 18.04 133.186 18.04C131.842 18.04 130.578 18.184 129.394 18.472C128.242 18.728 127.09 19.08 125.938 19.528L124.018 12.28C125.554 11.704 127.202 11.24 128.962 10.888C130.722 10.536 132.754 10.36 135.058 10.36C137.746 10.36 139.97 10.648 141.73 11.224C143.522 11.768 144.994 12.616 146.146 13.768C147.138 14.76 147.842 15.912 148.258 17.224C148.674 18.536 148.882 20.152 148.882 22.072V37H137.986V34.36C137.058 35.352 135.97 36.152 134.722 36.76C133.506 37.336 132.082 37.624 130.45 37.624ZM150.944 31.48H156.512V37H150.944V31.48ZM157.933 23.896H163.381V26.536C163.749 25.656 164.253 24.952 164.893 24.424C165.533 23.896 166.397 23.656 167.485 23.704V29.488H166.909C165.757 29.488 164.877 29.824 164.269 30.496C163.677 31.152 163.381 32.208 163.381 33.664V37H157.933V23.896ZM175.922 32.824C176.546 32.824 177.066 32.6 177.482 32.152C177.898 31.704 178.106 31.144 178.106 30.472V30.424C178.106 29.752 177.898 29.192 177.482 28.744C177.066 28.296 176.546 28.072 175.922 28.072C175.298 28.072 174.778 28.296 174.362 28.744C173.946 29.192 173.738 29.752 173.738 30.424V30.472C173.738 30.792 173.794 31.096 173.906 31.384C174.018 31.672 174.17 31.928 174.362 32.152C174.554 32.36 174.778 32.528 175.034 32.656C175.306 32.768 175.602 32.824 175.922 32.824ZM177.794 37.312C176.802 37.312 176.002 37.128 175.394 36.76C174.786 36.392 174.274 35.976 173.858 35.512V37H168.41V19.48H173.858V25.504C174.082 25.264 174.314 25.032 174.554 24.808C174.81 24.568 175.09 24.36 175.394 24.184C175.698 24.008 176.042 23.864 176.426 23.752C176.81 23.64 177.25 23.584 177.746 23.584C178.53 23.584 179.266 23.752 179.954 24.088C180.642 24.408 181.242 24.872 181.754 25.48C182.266 26.072 182.666 26.784 182.954 27.616C183.242 28.432 183.386 29.344 183.386 30.352V30.4C183.386 31.44 183.234 32.384 182.93 33.232C182.642 34.08 182.242 34.808 181.73 35.416C181.234 36.024 180.642 36.496 179.954 36.832C179.282 37.152 178.562 37.312 177.794 37.312Z" fill="url(#paint0_linear_4_61)"/>
|
4
|
+
<defs>
|
5
|
+
<linearGradient id="paint0_linear_4_61" x1="0" y1="23" x2="185" y2="23" gradientUnits="userSpaceOnUse">
|
6
|
+
<stop stop-color="#FF793B"/>
|
7
|
+
<stop offset="1" stop-color="#FF3BF2"/>
|
8
|
+
</linearGradient>
|
9
|
+
</defs>
|
10
|
+
</svg>
|
11
|
+
|
data/readme.md
CHANGED
@@ -1,73 +1,214 @@
|
|
1
1
|
<div align="center">
|
2
2
|
<picture>
|
3
|
-
<img alt="Lennarb" src="logo/lennarb.
|
3
|
+
<img alt="Lennarb" src="https://raw.githubusercontent.com/aristotelesbr/lennarb/refs/heads/main/logo/lennarb.svg" width="250">
|
4
4
|
</picture>
|
5
5
|
|
6
|
-
|
6
|
+
<hr>
|
7
|
+
|
8
|
+
<p>A lightweight, fast, and modular web framework for Ruby based on Rack. <strong>Lennarb</strong> supports Ruby (MRI) 3.4+</p>
|
9
|
+
|
10
|
+
<a href="https://github.com/aristotelesbr/lennarb/actions/workflows/test.yaml">
|
11
|
+
<img src="https://github.com/aristotelesbr/lennarb/actions/workflows/test.yaml/badge.svg" alt="Test">
|
12
|
+
</a>
|
13
|
+
<a href="https://rubygems.org/gems/lennarb">
|
14
|
+
<img src="https://img.shields.io/gem/v/lennarb.svg" alt="Gem">
|
15
|
+
</a>
|
16
|
+
<a href="https://rubygems.org/gems/lennarb">
|
17
|
+
<img src="https://img.shields.io/gem/dt/lennarb.svg" alt="Gem">
|
18
|
+
</a>
|
19
|
+
<a href="https://tldrlegal.com/license/mit-license">
|
20
|
+
<img src="https://img.shields.io/:License-MIT-blue.svg" alt="MIT License">
|
21
|
+
</a>
|
22
|
+
</div>
|
7
23
|
|
8
|
-
|
24
|
+
## Table of Contents
|
9
25
|
|
10
|
-
[
|
11
|
-
[
|
12
|
-
[
|
13
|
-
[
|
26
|
+
- [Features](#features)
|
27
|
+
- [Installation](#installation)
|
28
|
+
- [Quick Start](#quick-start)
|
29
|
+
- [Basic Usage](#basic-usage)
|
30
|
+
- [Documentation](#documentation)
|
31
|
+
- [Contributing](#contributing)
|
32
|
+
- [License](#license)
|
14
33
|
|
15
|
-
|
34
|
+
## Features
|
35
|
+
|
36
|
+
- Lightweight and modular architecture
|
37
|
+
- High-performance routing system
|
38
|
+
- Simple and intuitive API
|
39
|
+
- Support for middleware
|
40
|
+
- Flexible configuration options
|
41
|
+
- Two implementation options:
|
42
|
+
- `Lennarb::App`: Minimalist approach for single applications
|
43
|
+
- `Lennarb::Base`: Extended version for mounting multiple applications
|
44
|
+
|
45
|
+
## Installation
|
46
|
+
|
47
|
+
Add this line to your application's Gemfile:
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
gem 'lennarb'
|
51
|
+
```
|
52
|
+
|
53
|
+
Or install it directly:
|
54
|
+
|
55
|
+
```bash
|
56
|
+
gem install lennarb
|
57
|
+
```
|
58
|
+
|
59
|
+
## Quick Start
|
60
|
+
|
61
|
+
Create a simple application with routes:
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
require "lennarb"
|
65
|
+
|
66
|
+
app = Lennarb::App.new do
|
67
|
+
routes do
|
68
|
+
get("/") do |req, res|
|
69
|
+
res.html("<h1>Welcome to Lennarb!</h1>")
|
70
|
+
end
|
71
|
+
|
72
|
+
get("/hello/:name") do |req, res|
|
73
|
+
name = req.params[:name]
|
74
|
+
res.html("Hello, #{name}!")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
app.initialize!
|
80
|
+
run app # In config.ru
|
81
|
+
```
|
82
|
+
|
83
|
+
Start with: `rackup`
|
16
84
|
|
17
85
|
## Basic Usage
|
18
86
|
|
87
|
+
### Creating a Simple Application
|
88
|
+
|
89
|
+
The `Lennarb::App` class is the core of the framework:
|
90
|
+
|
19
91
|
```ruby
|
20
92
|
require "lennarb"
|
21
93
|
|
22
|
-
Lennarb::App
|
94
|
+
class MyApp < Lennarb::App
|
95
|
+
# Define configuration
|
23
96
|
config do
|
24
|
-
|
97
|
+
mandatory :database_url, string
|
25
98
|
optional :port, int, 9292
|
26
99
|
end
|
27
100
|
|
101
|
+
# Define routes
|
28
102
|
routes do
|
29
|
-
get("/
|
30
|
-
|
31
|
-
|
103
|
+
get("/") do |req, res|
|
104
|
+
res.html("<h1>Welcome!</h1>")
|
105
|
+
end
|
106
|
+
|
107
|
+
post("/users") do |req, res|
|
108
|
+
# Access request data
|
109
|
+
data = req.body
|
110
|
+
res.json({status: "created", data: data})
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Define hooks
|
115
|
+
before do |req, res|
|
116
|
+
# Run before every request
|
117
|
+
puts "Processing request: #{req.path}"
|
118
|
+
end
|
119
|
+
|
120
|
+
after do |req, res|
|
121
|
+
# Run after every request
|
122
|
+
puts "Completed request: #{req.path}"
|
123
|
+
end
|
124
|
+
|
125
|
+
# Define helper methods
|
126
|
+
helpers do
|
127
|
+
def format_date(date)
|
128
|
+
date.strftime("%Y-%m-%d")
|
32
129
|
end
|
33
130
|
end
|
34
131
|
end
|
132
|
+
|
133
|
+
run MyApp.new.initialize!
|
35
134
|
```
|
36
135
|
|
37
|
-
|
136
|
+
### Response Types
|
137
|
+
|
138
|
+
Lennarb provides various response methods:
|
139
|
+
|
140
|
+
```ruby
|
141
|
+
# HTML response
|
142
|
+
res.html("<h1>Hello World</h1>")
|
143
|
+
|
144
|
+
# JSON response
|
145
|
+
res.json({message: "Hello World"})
|
38
146
|
|
39
|
-
|
147
|
+
# Plain text response
|
148
|
+
res.text("Plain text response")
|
40
149
|
|
41
|
-
|
150
|
+
# Redirect
|
151
|
+
res.redirect("/new-location")
|
42
152
|
|
43
|
-
|
153
|
+
# Custom status code
|
154
|
+
res.json({error: "Not found"}, status: 404)
|
155
|
+
```
|
156
|
+
|
157
|
+
### Mounting Applications
|
158
|
+
|
159
|
+
For larger applications, use `Lennarb::Base` to mount multiple apps:
|
160
|
+
|
161
|
+
```ruby
|
162
|
+
class API < Lennarb::App
|
163
|
+
routes do
|
164
|
+
get("/users") do |req, res|
|
165
|
+
res.json([{id: 1, name: "Alice"}, {id: 2, name: "Bob"}])
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
44
169
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
170
|
+
class Admin < Lennarb::App
|
171
|
+
routes do
|
172
|
+
get("/dashboard") do |req, res|
|
173
|
+
res.html("<h1>Admin Dashboard</h1>")
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
51
177
|
|
52
|
-
|
178
|
+
class Application < Lennarb::Base
|
179
|
+
# Add common middleware
|
180
|
+
middleware do
|
181
|
+
use Rack::Session::Cookie, secret: "your_secret"
|
182
|
+
end
|
53
183
|
|
54
|
-
|
184
|
+
# Mount applications at specific paths
|
185
|
+
mount(API, at: "/api")
|
186
|
+
mount(Admin, at: "/admin")
|
187
|
+
end
|
55
188
|
|
56
|
-
|
189
|
+
run Application.new.initialize!
|
190
|
+
```
|
57
191
|
|
58
|
-
|
192
|
+
## Documentation
|
59
193
|
|
60
|
-
|
194
|
+
For more detailed information, please see:
|
61
195
|
|
62
|
-
- [
|
196
|
+
- [Getting Started](https://aristotelesbr.github.io/lennarb/guides/getting-started/index) - Setup and first steps
|
197
|
+
- [Response](https://aristotelesbr.github.io/lennarb/guides/response/index.html) - Response handling
|
198
|
+
- [Request](https://aristotelesbr.github.io/lennarb/guides/request/index.html) - Request handling
|
199
|
+
- [Mounting Applications](https://aristotelesbr.github.io/lennarb/guides/mounting-applications/index.html) - Working with multiple apps
|
200
|
+
- [Performance](https://aristotelesbr.github.io/lennarb/guides/performance/index.html) - Benchmarks showing Lennarb's routing algorithm efficiency
|
63
201
|
|
64
|
-
|
65
|
-
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`.
|
202
|
+
## Contributing
|
66
203
|
|
67
|
-
|
204
|
+
1. Fork the repository
|
205
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
206
|
+
3. Commit your changes (`git commit -am 'Add amazing feature'`)
|
207
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
208
|
+
5. Open a Pull Request
|
68
209
|
|
69
|
-
This project uses the [Developer Certificate of Origin](https://developercertificate.org/)
|
210
|
+
This project uses the [Developer Certificate of Origin](https://developercertificate.org/) and is governed by the [Contributor Covenant](https://www.contributor-covenant.org/).
|
70
211
|
|
71
|
-
|
212
|
+
## License
|
72
213
|
|
73
|
-
|
214
|
+
MIT License - see the [LICENSE](LICENSE) file for details.
|