lennarb 0.1.0 → 0.1.1

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: 4c397642a693a43af01eac2929b1a43c4f6258f43b63f4dadb6c6bd2245eb54f
4
- data.tar.gz: eb65ddcc1896bd51e7f254e22698f8bc9d190c388e9dd892e35d6a348e9d5724
3
+ metadata.gz: b0e10a539894e1cf41bcebf4c01b086092d36779b1b8aebada8eabc717552348
4
+ data.tar.gz: 86afa28d62c0b532e08027df8a1847bc4a72b36347388b11f4c6f7aef8c2d345
5
5
  SHA512:
6
- metadata.gz: d36a2a07a847997c2b55cfb0c47aa894cd6d19ef1214721b3c4d1c8922e93077f0b47e5989b63a6f0fb555f5cee95a4b7938a232c7ddea56e11401a95074e971
7
- data.tar.gz: 8827458b308d68e874326b143670112af07e7b03f7945bfdd1db7f3d04c1e22daf196f59bf5c46e0ed741add8b52dc11d7447d545f869620b5efbfb4f50c5efe
6
+ metadata.gz: '0539b0de41e1de79c84a89204c67931dcf0b015a2401db8bece03ef66e8fc5b7e74c87527bb431d1ec447998b067738bb41127f68917d0dbcfd44ff973294935'
7
+ data.tar.gz: 88820bc3511a72fda57ef39fac259c69cc632dcb3ad0d9faa4b3514327603cc78cd6e5b6531b4c632a109901883e5ca642fa13904ab8e6445cecea466edde298
data/CHANGELOG.md CHANGED
@@ -4,26 +4,26 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
- ## [Unreleased]
7
+ ## [Released]
8
8
 
9
- ### Added
10
- - New feature for the next release.
9
+ ## [0.1.1] - 2023-23-11
11
10
 
12
11
  ### Added
13
- - Initial release of the project.
12
+ - 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.
14
13
 
15
14
  ### Changed
16
- - Example change to an existing feature.
15
+ - Refactored the `put_header` method to use the `Array.wrap` method for more predictable header value handling.
16
+ - Renamed methods to have a consistent `assign_` prefix to standardize the API interface:
17
+ - `put_header` to `assign_header`
18
+ - `write_body` to `assign_body`
19
+ - `set_params` to `assign_params`
20
+ - `update_status` to `assign_status`
17
21
 
18
22
  ### Deprecated
19
- - Example feature that will be removed in future releases.
20
23
 
21
24
  ### Removed
22
- - Example feature that was removed.
23
25
 
24
26
  ### Fixed
25
- - Example bug fix.
26
27
 
27
28
  ### Security
28
- - Example security fix.
29
29
 
@@ -12,7 +12,7 @@ module Lenna
12
12
  #
13
13
  # @return [Hash] the request params
14
14
  #
15
- # @public
15
+ # @api public
16
16
  def params = super.merge(parse_body_params)
17
17
 
18
18
  # This method rewinds the body
@@ -4,51 +4,41 @@ module Lenna
4
4
  class Router
5
5
  # The Response class is responsible for managing the response.
6
6
  #
7
- # @attr _headers [Hash] the response headers
8
- # @attr _body [Array(String)] the response body
9
- # @attr _status [Integer] the response status
10
- # @attr params [Hash] the response params
7
+ # @attr headers [Hash] the response headers
8
+ # @attr body [Array(String)] the response body
9
+ # @attr status [Integer] the response status
10
+ # @attr params [Hash] the response params
11
11
  class Response
12
- public attr_reader :params
13
- private attr_accessor :_headers, :_body, :_status
12
+ private attr_writer :body, :headers, :status, :params
13
+ public attr_reader :body, :headers, :status, :params
14
14
 
15
- # Initialize the Response
16
15
  def initialize(headers = {}, status = 200, body = [])
17
- self._headers = headers
18
- self._status = status
19
- self._body = body
20
- @params = {}
16
+ @params = {}
17
+ @body = body
18
+ @status = status
19
+ @headers = headers
21
20
  end
22
21
 
22
+ # This method will set the response status.
23
+ #
24
+ # @param value [Integer] the response status
25
+ #
26
+ # @return [void]
27
+ #
23
28
  # @api public
24
- # @return [Integer] the response status
25
- def status = fetch_status
26
-
27
- # @api public
28
- # @param status [Integer] the response status
29
- # @return [void]
30
- def put_status(value) = status!(value)
31
-
32
- # @api public
33
- # @return [Array(String)] the body value
34
- def body = fetch_body
29
+ def assign_status(value) = put_status(value)
35
30
 
36
- # @api public
31
+ # Thi method set the body value.
32
+ #
37
33
  # @param value [Array(String)] the body value
34
+ #
38
35
  # @return [void]
39
- def put_body(value) = body!(value)
40
-
41
- # @api public
42
- # @param header [String] the header name
43
- # @return [String] the header value
44
- # @note This method will get the header value.
45
- def header(key) = fetch_header(key)
46
-
36
+ #
47
37
  # @api public
48
- # @return [Hash] the response headers
49
- def headers = fetch_headers
38
+ def assign_body(value) = put_body(value)
50
39
 
51
- # @api public
40
+ # This method will set the header value.
41
+ #
52
42
  # @param header [String] the header name
53
43
  # @param value [String] the header value
54
44
  # @return [void]
@@ -56,18 +46,21 @@ module Lenna
56
46
  # If the header already exists, then the value will
57
47
  # be appended to the header.
58
48
  #
49
+ # @api public
50
+ #
59
51
  # @example
60
- # put_header('X-Request-Id', '123')
52
+ # assign_header('X-Request-Id', '123')
61
53
  # # => '123'
62
54
  #
63
- # put_header('X-Request-Id', '456')
55
+ # assign_header('X-Request-Id', '456')
64
56
  # # => ['123', '456']
65
57
  #
66
- # put_header('X-Request-Id', ['456', '789'])
58
+ # assign_header('X-Request-Id', ['456', '789'])
67
59
  # # => ['123', '456', '789']
68
- def put_header(key, value) = header!(key, value)
60
+ def assign_header(key, value) = put_header(key, value)
69
61
 
70
62
  # Add multiple headers.
63
+ #
71
64
  # @param headers [Hash] the headers
72
65
  # @return [void]
73
66
  # @note This method will add the headers.
@@ -80,49 +73,66 @@ module Lenna
80
73
  # 'X-Request-Id' => '123'
81
74
  # }
82
75
  #
83
- def put_headers(headers)
76
+ def assign_headers(headers)
84
77
  headers => ::Hash
85
78
 
86
79
  headers.each { |key, value| put_header(key, value) }
87
80
  end
88
81
 
82
+ # This method will get the content type.
83
+ #
84
+ # @return [String] the content type
85
+ #
89
86
  # @api public
87
+ def content_type = @headers['Content-Type']
88
+
89
+ # This method will delete the header.
90
90
  # @param header [String] the header name
91
+ #
91
92
  # @return [void]
92
- # @note This method will delete the header.
93
+ #
94
+ # @api public
93
95
  def remove_header(key) = delete_header(key)
94
96
 
95
- # @api public
97
+ # This method will get the redirect location.
98
+ #
96
99
  # @param value [String] the key of the cookie
100
+ #
97
101
  # @return [String] the cookie
98
- # @note This method will get the cookie.
102
+ #
103
+ # @api public
99
104
  def cookie(value)
100
105
  value => ::String
101
106
 
102
- fetch_header('Set-Cookie')
107
+ @headers['Set-Cookie']
103
108
  .then { |cookie| cookie.split('; ') }
104
109
  .then { |cookie| cookie.find { |c| c.start_with?("#{value}=") } }
105
110
  .then { |cookie| cookie.split('=').last }
106
111
  end
107
112
 
108
- # @api public
113
+ # This method will set the cookie.
114
+ #
109
115
  # @param key [String] the key of the cookie
110
116
  # @param value [String] the value of the cookie
117
+ #
111
118
  # @return [void]
112
- # @note This method will set the cookie.
113
- def put_cookie(key, value)
119
+ #
120
+ # @api public
121
+ def assign_cookie(key, value)
114
122
  key => ::String
115
123
  value => ::String
116
124
 
117
125
  cookie = "#{key}=#{value}"
118
126
 
119
- header!('Set-Cookie', cookie)
127
+ put_header('Set-Cookie', cookie)
120
128
  end
121
129
 
122
- # @api public
130
+ # This method will get all the cookies.
131
+ #
123
132
  # @return [Hash] the cookies
133
+ # @api public
124
134
  def cookies
125
- fetch_header('Set-Cookie')
135
+ @headers['Set-Cookie']
126
136
  .then { |cookie| cookie.split('; ') }
127
137
  .each_with_object({}) do |cookie, acc|
128
138
  key, value = cookie.split('=')
@@ -131,82 +141,93 @@ module Lenna
131
141
  end
132
142
  end
133
143
 
134
- # @api public
144
+ # This method will set redirect location. The status will be set to 302.
145
+ #
135
146
  # @param location [String] the redirect location
136
- # @param status [Integer] the redirect status
147
+ # @param status [Integer] the redirect status, default is 302.
148
+ #
137
149
  # @return [void]
138
- # @note This method will set the redirect location and
139
- # status and finish the response.
150
+ #
151
+ # @api public
140
152
  def redirect(location, status: 302)
141
153
  location => ::String
142
154
 
143
- header!('Location', location)
144
- status!(status)
155
+ put_header('Location', location)
156
+ put_status(status)
145
157
 
146
158
  finish!
147
159
  rescue ::NoMatchingPatternError
148
160
  raise ::ArgumentError, 'location must be a string'
149
161
  end
150
162
 
151
- # @api public
163
+ # This method will finish the response.
164
+ #
152
165
  # @return [void]
153
- # @note This method will finish the response.
154
- def finish = finish!
155
-
166
+ #
156
167
  # @api public
157
- # @return [String] the response content type
158
- # @note This method will set
159
- # the response content type.
160
- def content_type = header('Content-Type')
168
+ def finish = finish!
161
169
 
162
- # @api public
170
+ # This method will set the response content type.
171
+ #
163
172
  # @param type [String] the response content type
164
173
  # @param charset [Hash] the response charset
174
+ #
165
175
  # @return [void]
166
- def put_content_type(type, charset: nil)
176
+ #
177
+ # @api public
178
+ def assign_content_type(type, charset: nil)
167
179
  type => ::String
168
180
 
169
181
  case charset
170
- in ::String then header!('Content-Type', "#{type}; charset=#{charset}")
171
- else header!('Content-Type', type)
182
+ in ::String then put_header(
183
+ 'Content-Type',
184
+ "#{type}; charset=#{charset}"
185
+ )
186
+ else put_header('Content-Type', type)
172
187
  end
173
188
  rescue ::NoMatchingPatternError
174
189
  raise ::ArgumentError, 'type must be a string'
175
190
  end
176
191
 
177
- # @api public
192
+ # This method will set the response data and finish the response.
193
+ #
178
194
  # @param data [Hash, Array] the response data
195
+ #
179
196
  # @return [void]
180
- # @note This method will set the response data and
181
- # finish the response.
197
+ #
198
+ # @api public
182
199
  def json(data:, status: 200)
183
200
  data => ::Array | ::Hash
184
201
 
185
- status!(status)
186
- header!('Content-Type', 'application/json')
187
- body!(data.to_json)
202
+ put_status(status)
203
+ put_header('Content-Type', 'application/json')
204
+ put_body(data.to_json)
188
205
 
189
206
  finish!
190
207
  end
191
208
 
192
209
  # Set the response content type to text/html.
210
+ #
193
211
  # @param str [String] the response body
212
+ #
194
213
  # @return [void]
214
+ #
215
+ # @api public
195
216
  def html(str = nil, status: 200)
196
- status!(status)
197
- header!('Content-Type', 'text/html')
198
- body!(str)
217
+ put_status(status)
218
+ put_header('Content-Type', 'text/html')
219
+ put_body(str)
199
220
 
200
221
  finish!
201
222
  end
202
223
 
224
+ # This method will render the template.
225
+ #
203
226
  # @param template_nam [String] the template name
204
227
  # @param path [String] the template path, default is 'views'
205
228
  # @param locals [Hash] the template locals
229
+ #
206
230
  # @return [void | Exception]
207
- # @note This method will render the template.
208
- # The template engine is determined by the
209
- # file extension.
210
231
  #
211
232
  # @example
212
233
  # render('index')
@@ -245,112 +266,113 @@ module Lenna
245
266
  end
246
267
 
247
268
  # Helper methods for the response.
248
- # @api public
269
+ #
249
270
  # @return [void]
250
- # @note This method will finish the response with a 404 status.
271
+ #
272
+ # @api public
273
+ #
274
+ # @see #render
275
+ # @see #finish!
251
276
  def not_found
252
- body!(['Not Found'])
253
- status!(404)
277
+ put_body(['Not Found'])
278
+ put_status(404)
279
+
254
280
  finish!
255
281
  end
256
282
 
257
283
  private
258
284
 
259
- # @api private
285
+ # This method will get the response status.
286
+ #
260
287
  # @return [Integer] the response status
261
- # @note This method will get the response status.
262
- def fetch_status = _status
263
-
288
+ #
264
289
  # @api private
265
- # @return [Integer] the response status
266
- # @note This method will get the response status.
267
- def status!(value)
290
+ def put_status(value)
268
291
  value => ::Integer
269
292
 
270
- self._status = value
293
+ self.status = value
271
294
  rescue ::NoMatchingPatternError
272
295
  raise ::ArgumentError, 'status must be an integer'
273
296
  end
274
297
 
275
- # @api private
276
- # @return [Array(String)] the body value
277
- def fetch_body = _body
278
-
279
- # @api private
298
+ # This method will set the body.
299
+ #
280
300
  # @param body [Array(String)] the body to be used
281
301
  # @return [void]
282
- # @note This method will set the body.
283
- def body!(value)
284
- body => ::String | ::Array
302
+ def put_body(value)
303
+ value => ::String | ::Array
285
304
 
286
305
  case value
287
- in ::String then self._body = [value]
288
- in ::Array then self._body = value
306
+ in ::String then @body = [value]
307
+ in ::Array then @body = value
289
308
  end
290
309
  rescue ::NoMatchingPatternError
291
310
  raise ::ArgumentError, 'body must be a string or an array'
292
311
  end
293
312
 
294
- # @api private
295
- # @param header [String] the header name
296
- # @return [String] the header value
297
- # @note This method will get the header value.
298
- def fetch_header(header) = _headers[header]
299
-
300
- # @api private
301
- # @return [Hash] the response headers
302
- def fetch_headers = _headers
303
-
304
- # @api private
305
313
  # @param key [String] the header name
306
314
  # @param value [String] the value to be used
315
+ #
307
316
  # @return [void]
308
- # @note This method will set the header value.
309
- # If the header already exists, then the value will
310
- # be appended to the header.
311
- def header!(key, value)
312
- key => ::String
313
- value => ::String | ::Array
317
+ def put_header(key, value)
318
+ raise ::ArgumentError, 'key must be a string' unless key.is_a?(::String)
314
319
 
315
- header_value = fetch_header(key)
316
-
317
- case value
318
- in ::String then _headers[key] = [*header_value, value].uniq.join(', ')
319
- in ::Array then _headers[key] = [*header_value, *value].uniq.join(', ')
320
+ unless value.is_a?(::String) || value.is_a?(::Array)
321
+ raise ::ArgumentError, 'value must be a string or an array'
320
322
  end
321
- rescue ::NoMatchingPatternError
322
- raise ::ArgumentError, 'header must be a string or an array'
323
+
324
+ header_value = @headers[key]
325
+
326
+ new_values = ::Array.wrap(value)
327
+ existing_values = ::Array.wrap(header_value)
328
+
329
+ @headers[key] = (existing_values + new_values).uniq.join(', ')
323
330
  end
324
331
 
325
- # @api private
326
332
  # @param key [String] the header name
333
+ #
327
334
  # @return [void]
328
- # @note This method will delete the header.
329
- def delete_header(key) = _headers.delete(key)
335
+ def delete_header(key) = @headers.delete(key)
330
336
 
331
- # @api private
332
337
  # @param value [String] the redirect location
338
+ #
333
339
  # @return [void]
334
340
  def location!(value)
335
341
  value => ::String
336
342
 
337
- header!('Location', value)
343
+ put_header('Location', value)
338
344
  end
339
345
 
340
- # @api private
341
- # @param value [String] the content value
342
- # @return [String] the size of the content
343
- # @note This method will get the size of the content.
344
- def content_length!(value) = header!('Content-Length', value)
345
-
346
- # @api private
346
+ # This method will finish the response.
347
+ #
347
348
  # @return [void]
348
- # @note This method will finish the response.
349
349
  def finish!
350
- put_content_type('text/html') unless header('Content-Type')
351
- content_length!(body.join.size.to_s) unless header('Content-Length')
350
+ default_router_header!
351
+ default_content_length! unless @headers['Content-Length']
352
+ default_html_content_type! unless @headers['Content-Type']
353
+
354
+ [@status, @headers, @body]
355
+ end
352
356
 
353
- [_status, _headers, _body]
357
+ # This method will set the response default html content type.
358
+ #
359
+ # @return [void]
360
+ def default_html_content_type!
361
+ put_header('Content-Type', 'text/html')
362
+ end
363
+
364
+ # This method will set the response default content length.
365
+ #
366
+ # @return [void]
367
+ def default_content_length!
368
+ put_header('Content-Length', @body.join.size.to_s)
369
+ end
370
+
371
+ # This method will set the response default router header.
372
+ #
373
+ # @return [void]
374
+ def default_router_header!
375
+ put_header('Server', "Lennarb VERSION #{::Lennarb::VERSION}")
354
376
  end
355
377
  end
356
378
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lennarb
4
+ module ArrayExtensions
5
+ def wrap(object)
6
+ if object.nil?
7
+ []
8
+ elsif object.respond_to?(:to_ary)
9
+ object.to_ary || [object]
10
+ else
11
+ [object]
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ Array.extend(Lennarb::ArrayExtensions)
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Lennarb
4
+ VERSION = '0.1.1'
5
+
6
+ public_constant :VERSION
7
+ end
data/lib/lennarb.rb CHANGED
@@ -1,3 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Extension for Array class
4
+ require 'lennarb/array_extensions'
5
+
6
+ # Base class for Lennarb
3
7
  require 'lenna/base'
8
+ require 'lennarb/version'
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.0
4
+ version: 0.1.1
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: 2023-11-16 00:00:00.000000000 Z
11
+ date: 2023-11-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colorize
@@ -141,6 +141,8 @@ files:
141
141
  - lib/lenna/router/response.rb
142
142
  - lib/lenna/router/route_matcher.rb
143
143
  - lib/lennarb.rb
144
+ - lib/lennarb/array_extensions.rb
145
+ - lib/lennarb/version.rb
144
146
  homepage: https://rubygems.org/gems/lennarb
145
147
  licenses:
146
148
  - MIT