lennarb 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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