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.
@@ -1,22 +1,24 @@
1
1
  module Lennarb
2
+ # Response object
3
+ #
2
4
  class Response
3
5
  # @!attribute [rw] status
4
- # @returns [Integer]
6
+ # @return [Integer]
5
7
  #
6
8
  attr_accessor :status
7
9
 
8
10
  # @!attribute [r] body
9
- # @returns [Array]
11
+ # @retrn [Array]
10
12
  #
11
13
  attr_reader :body
12
14
 
13
15
  # @!attribute [r] headers
14
- # @returns [Hash]
16
+ # @retrn [Hash]
15
17
  #
16
18
  attr_reader :headers
17
19
 
18
20
  # @!attribute [r] length
19
- # @returns [Integer]
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
- # @returns [Response]
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
- # @parameter [String] key
49
+ # @param [String] key
48
50
  #
49
- # @returns [String] value
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
- # @parameter [String] key
58
- # @parameter [String] value
59
+ # @param [String] key
60
+ # @param [String] value
59
61
  #
60
- # @returns [String] value
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
- # @parameter [String] str
70
+ # @param [String] str
69
71
  #
70
- # @returns [String] str
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
- # @parameter [String] str
83
+ # @param [String] str
82
84
  #
83
- # @returns [String] str
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
- # @parameter [String] str
94
+ # @param [String] str
93
95
  #
94
- # @returns [String] str
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
- # @parameter [String] str
105
+ # @param [String] str
104
106
  #
105
- # @returns [String] str
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
- # @parameter [String] path
120
- # @parameter [Integer] status, default: 302
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
- # @returns [Array] response
133
+ # @retrn [Array] response
132
134
  #
133
135
  def finish
134
136
  [@status, @headers, @body]
@@ -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
- # @returns [void]
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
- # @returns [Array<Proc, Hash>]
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
- # @returns [void|DuplicateRouteError]
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
@@ -1,71 +1,67 @@
1
1
  module Lennarb
2
+ # Routes class for managing application routes
3
+ #
2
4
  class Routes
3
- attr_reader :store
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
- # @example
8
- # node = RouteNode.new
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
- instance_eval(&) if block_given?
10
+ @frozen = false
14
11
  end
15
12
 
16
- # Define the HTTP methods.
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
- def root(&block) = register_route(:GET, "/", &block)
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 route.
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
- def match_route(...) = @store.match_route(...)
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 store object.
45
- #
46
- # @returns [void]
38
+ # Freeze the routes to prevent further modification
47
39
  #
48
- def freeze = @store.freeze
49
-
50
- private def register_route(http_method, path, &block)
51
- parts = path.split("/").reject(&:empty?)
52
- @store.add_route(parts, http_method, block)
40
+ # @return [self] The frozen routes
41
+ def freeze
42
+ @frozen = true
43
+ @store.freeze
44
+ self
53
45
  end
54
46
 
55
- module Mixin
56
- extend self
57
-
58
- def routes(&block)
59
- @routes ||= Routes.new(&block)
60
- end
47
+ # Check if the routes are frozen
48
+ #
49
+ # @return [Boolean] True if frozen
50
+ def frozen?
51
+ @frozen
52
+ end
61
53
 
62
- HTTP_METHODS.each do |http_method|
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
- def root(&) = routes.root(&)
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
@@ -1,3 +1,3 @@
1
- module Lennarb
2
- VERSION = "1.4.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/constansts"
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.png" width="250">
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
- A lightweight, fast, and modular web framework for Ruby based on Rack. The **Lennarb** supports Ruby (MRI) 3.4+
24
+ ## Table of Contents
9
25
 
10
- [![Test](https://github.com/aristotelesbr/lennarb/actions/workflows/test.yaml/badge.svg)](https://github.com/aristotelesbr/lennarb/actions/workflows/test.yaml)
11
- [![Gem](https://img.shields.io/gem/v/lennarb.svg)](https://rubygems.org/gems/lennarb)
12
- [![Gem](https://img.shields.io/gem/dt/lennarb.svg)](https://rubygems.org/gems/lennarb)
13
- [![MIT License](https://img.shields.io/:License-MIT-blue.svg)](https://tldrlegal.com/license/mit-license)
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
- </div>
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.new do
94
+ class MyApp < Lennarb::App
95
+ # Define configuration
23
96
  config do
24
- optional :env, string, "prodcution"
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("/hello/:name") do |req, res|
30
- name = req.params[:name]
31
- res.html("Hello, #{name}!")
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
- ## Performance
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
- ### 1. Requests per Second (RPS)
147
+ # Plain text response
148
+ res.text("Plain text response")
40
149
 
41
- ![RPS](https://raw.githubusercontent.com/aristotelesbr/lennarb/main/benchmark/rps.png)
150
+ # Redirect
151
+ res.redirect("/new-location")
42
152
 
43
- See all [graphs](https://github.com/aristotelesbr/lennarb/blob/main/benchmark)
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
- | Position | Application | 10 RPS | 100 RPS | 1.000 RPS | 10.000 RPS |
46
- | -------- | ----------- | ---------- | ---------- | --------- | ---------- |
47
- | 1 | Lenna | 126.252,36 | 108.086,55 | 87.111,91 | 68.460,64 |
48
- | 2 | Roda | 123.360,37 | 88.380,56 | 66.990,77 | 48.108,29 |
49
- | 3 | Syro | 114.105,38 | 80.909,39 | 61.415,86 | 46.639,81 |
50
- | 4 | Hanami-API | 68.089,18 | 52.851,88 | 40.801,78 | 27.996,00 |
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
- This table ranks the routers by the number of requests they can process per second. Higher numbers indicate better performance.
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
- Please see [Performance](https://aristotelesbr.github.io/lennarb/guides/performance/index.html) for more information.
184
+ # Mount applications at specific paths
185
+ mount(API, at: "/api")
186
+ mount(Admin, at: "/admin")
187
+ end
55
188
 
56
- ## Usage
189
+ run Application.new.initialize!
190
+ ```
57
191
 
58
- - [Getting Started](https://aristotelesbr.github.io/lennarb/guides/getting-started/index) - This guide covers getting up and running with **Lennarb**.
192
+ ## Documentation
59
193
 
60
- - [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).
194
+ For more detailed information, please see:
61
195
 
62
- - [Request]() - TODO
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
- - [Response](https://aristotelesbr.github.io/lennarb/guides/response/index.html) - This is the response guide.
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
- ### Developer Certificate of Origin
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/). All contributors to this project must agree to this document to have their contributions accepted.
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
- ### Contributor Covenant
212
+ ## License
72
213
 
73
- This project is governed by the [Contributor Covenant](https://www.contributor-covenant.org/). All contributors and participants agree to abide by its terms.
214
+ MIT License - see the [LICENSE](LICENSE) file for details.