macaw_framework 1.3.1 → 1.3.22

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: faee0746cfa34d7020272e9c6a3d24f12bff1c88ef3a5f8bf1f65be5dc7de8b2
4
- data.tar.gz: f3dfa0a71a12df9d0fdf07fcedcf9fe8cc29db81c20aa003482f5a465a330648
3
+ metadata.gz: 6884907c34b2719e0166f6a3c7fc5992e277126ec738a6a08e3fbaa71c427b0a
4
+ data.tar.gz: 554b0671565902d395fa289ae970cb7b149f0b61f9dcebdfdd9947bc277807fa
5
5
  SHA512:
6
- metadata.gz: 92b61e93524104407eba6c9d2621990a7cc6b68e0733a78fedc75cff6fc248601410344aa421dec9e79f77a52b391d7f2e102cb54f639a127ebeaf4b00c5f2fb
7
- data.tar.gz: 3eb62e30474e588dd0200f981aaa847ddf2725d7092d9c4387a0a5c63c2870f2ae87bd7f7998d0149dd00c592d144d0d6188464de6a473334ec94733967aef3d
6
+ metadata.gz: bde5aa848d982a6cd112c9f8eb57b84c39aaf30463f0a21e8ce79dfee2b54bc6711598da4abd3c0287a32f502123a48715700c68f937118fe0cdbb2c045733cd
7
+ data.tar.gz: 2248a9ea06a53f7602d366fdc2524a7c40866042102ec84fb6b1a724e9617175f2278bf2075fd6b9b7f9bc36626b64824f6cd0baee25ce6346f554bba9e76fd1
data/CHANGELOG.md CHANGED
@@ -147,3 +147,10 @@
147
147
  - Fixing bug where missing session configuration on `application.json` break the application
148
148
  - Including a Cache module for manual caching.
149
149
 
150
+ ## [1.3.21]
151
+ - Refactoring shutdown method
152
+ - Fixing a bug where a HTTP call without client data broke the parser
153
+ - Removing logs registering new HTTP connections to reduce log bloat
154
+
155
+ ## [1.3.3]
156
+ - Fixing error with tests on Ruby 3.4.x due to splash operator
data/README.md CHANGED
@@ -2,8 +2,8 @@
2
2
  # MacawFramework
3
3
 
4
4
  MacawFramework is a lightweight, easy-to-use web framework for Ruby designed to simplify the development of small to
5
- medium-sized web applications. With support for various HTTP methods, caching, and session management, MacawFramework
6
- provides developers with the essential tools to quickly build and deploy their applications.
5
+ medium-sized web applications. Weighting less than 26Kb with support for various HTTP methods, caching, and session management,
6
+ MacawFramework provides developers with the essential tools to quickly build and deploy their applications.
7
7
 
8
8
  - [MacawFramework](#macawframework)
9
9
  * [Features](#features)
@@ -31,7 +31,8 @@ provides developers with the essential tools to quickly build and deploy their a
31
31
  - Session management with server-side in-memory storage
32
32
  - Basic rate limiting and SSL support
33
33
  - Prometheus integration for monitoring and metrics
34
- - Lightweight and easy to learn
34
+ - Less than 26Kb
35
+ - Easy to learn
35
36
 
36
37
  ## Installation
37
38
 
@@ -3,15 +3,15 @@
3
3
  ##
4
4
  # Aspect that provide cache for the endpoints.
5
5
  module CacheAspect
6
- def call_endpoint(cache, *args)
7
- return super(*args) unless !cache[:cache].nil? && cache[:endpoints_to_cache]&.include?(args[0])
6
+ def call_endpoint(cache, *args, **kwargs)
7
+ return super(*args, **kwargs) unless !cache[:cache].nil? && cache[:endpoints_to_cache]&.include?(args[0])
8
8
 
9
9
  cache_filtered_name = cache_name_filter(args[1], cache[:cached_methods][args[0]])
10
10
 
11
11
  cache[:cache].mutex.synchronize do
12
12
  return cache[:cache].cache[cache_filtered_name][0] unless cache[:cache].cache[cache_filtered_name].nil?
13
13
 
14
- response = super(*args)
14
+ response = super(*args, **kwargs)
15
15
  cache[:cache].cache[cache_filtered_name] = [response, Time.now] if should_cache_response?(response[1])
16
16
  response
17
17
  end
@@ -8,11 +8,8 @@ require_relative '../data_filters/log_data_filter'
8
8
  # the input and output of every endpoint called
9
9
  # in the framework.
10
10
  module LoggingAspect
11
- def call_endpoint(logger, *args)
12
- return super(*args) if logger.nil?
13
-
14
- endpoint_name = args[1].split('.')[1..].join('/')
15
- logger.info("Request received for [#{endpoint_name}] from [#{args[-1]}]")
11
+ def call_endpoint(logger, *args, **kwargs)
12
+ return super(*args, **kwargs) if logger.nil?
16
13
 
17
14
  begin
18
15
  response = super(*args)
@@ -3,8 +3,8 @@
3
3
  ##
4
4
  # Aspect that provides application metrics using prometheus.
5
5
  module PrometheusAspect
6
- def call_endpoint(prometheus_middleware, *args)
7
- return super(*args) if prometheus_middleware.nil?
6
+ def call_endpoint(prometheus_middleware, *args, **kwargs)
7
+ return super(*args, **kwargs) if prometheus_middleware.nil?
8
8
 
9
9
  start_time = Time.now
10
10
 
@@ -39,14 +39,13 @@ module ServerBase
39
39
  end
40
40
 
41
41
  def handle_client(client)
42
- path, method_name, headers, body, parameters = RequestDataFiltering.parse_request_data(client, @macaw.routes)
42
+ _path, method_name, headers, body, parameters = RequestDataFiltering.parse_request_data(client, @macaw.routes)
43
43
  raise EndpointNotMappedError unless @macaw.respond_to?(method_name)
44
44
  raise TooManyRequestsError unless @rate_limit.nil? || @rate_limit.allow?(client.peeraddr[3])
45
45
 
46
46
  client_data = get_client_data(body, headers, parameters)
47
47
  session_id = declare_client_session(client_data[:headers], @macaw.secure_header) if @macaw.session
48
48
 
49
- @macaw_log&.info("Running #{path.gsub("\n", '').gsub("\r", '')}")
50
49
  message, status, response_headers = call_endpoint(@prometheus_middleware, @macaw_log, @cache,
51
50
  method_name, client_data, session_id, client.peeraddr[3])
52
51
  response_headers ||= {}
@@ -74,8 +74,17 @@ class ThreadServer
74
74
 
75
75
  ##
76
76
  # Method Responsible for closing the TCP server.
77
- def close
78
- shutdown
77
+ def shutdown
78
+ @is_shutting_down = true
79
+ loop do
80
+ break if @work_queue.empty?
81
+
82
+ sleep 0.1
83
+ end
84
+
85
+ @num_threads.times { @work_queue << :shutdown }
86
+ @workers.each(&:join)
87
+ @server.close
79
88
  end
80
89
 
81
90
  private
@@ -107,17 +116,4 @@ class ThreadServer
107
116
  end
108
117
  end
109
118
  end
110
-
111
- def shutdown
112
- @is_shutting_down = true
113
- loop do
114
- break if @work_queue.empty?
115
-
116
- sleep 0.1
117
- end
118
-
119
- @num_threads.times { @work_queue << :shutdown }
120
- @workers.each(&:join)
121
- @server.close
122
- end
123
119
  end
@@ -11,7 +11,7 @@ module RequestDataFiltering
11
11
  # Method responsible for extracting information
12
12
  # provided by the client like Headers and Body
13
13
  def self.parse_request_data(client, routes)
14
- path, parameters = extract_url_parameters(client.gets.gsub('HTTP/1.1', ''))
14
+ path, parameters = extract_url_parameters(client.gets&.gsub('HTTP/1.1', ''))
15
15
  parameters = {} if parameters.nil?
16
16
 
17
17
  method_name = sanitize_method_name(path)
@@ -26,15 +26,15 @@ module RequestDataFiltering
26
26
 
27
27
  selected_route = nil
28
28
  routes.each do |route|
29
- split_route = route.split('.')
30
- split_name = method_name.split('.')
29
+ split_route = route&.split('.')
30
+ split_name = method_name&.split('.')
31
31
 
32
- next unless split_route.length == split_name.length
32
+ next unless split_route&.length == split_name&.length
33
33
  next unless match_path_with_route(split_name, split_route)
34
34
 
35
35
  selected_route = route
36
- split_route.each_with_index do |var, index|
37
- parameters[var[1..].to_sym] = split_name[index] if var =~ VARIABLE_PATTERN
36
+ split_route&.each_with_index do |var, index|
37
+ parameters[var[1..].to_sym] = split_name&.dig(index) if var =~ VARIABLE_PATTERN
38
38
  end
39
39
  break
40
40
  end
@@ -45,7 +45,7 @@ module RequestDataFiltering
45
45
  end
46
46
 
47
47
  def self.match_path_with_route(split_path, split_route)
48
- split_route.each_with_index do |var, index|
48
+ split_route&.each_with_index do |var, index|
49
49
  return false if var != split_path[index] && !var.match?(VARIABLE_PATTERN)
50
50
  end
51
51
 
@@ -56,26 +56,28 @@ module RequestDataFiltering
56
56
  # Method responsible for sanitizing the method name
57
57
  def self.sanitize_method_name(path)
58
58
  path = extract_path(path)
59
- method_name = path.gsub('/', '.').strip.downcase
60
- method_name.gsub!(' ', '')
59
+ method_name = path&.gsub('/', '.')&.strip&.downcase
60
+ method_name&.gsub!(' ', '')
61
61
  method_name
62
62
  end
63
63
 
64
64
  ##
65
65
  # Method responsible for extracting the path from URI
66
66
  def self.extract_path(path)
67
+ return path if path.nil?
68
+
67
69
  path[0] == '/' ? path[1..].gsub('/', '.') : path.gsub('/', '.')
68
70
  end
69
71
 
70
72
  ##
71
73
  # Method responsible for extracting the headers from request
72
74
  def self.extract_headers(client)
73
- header = client.gets.delete("\n").delete("\r")
75
+ header = client.gets&.delete("\n")&.delete("\r")
74
76
  headers = {}
75
- while header.match(%r{[a-zA-Z0-9\-/*]*: [a-zA-Z0-9\-/*]})
77
+ while header&.match(%r{[a-zA-Z0-9\-/*]*: [a-zA-Z0-9\-/*]})
76
78
  split_header = header.split(':')
77
79
  headers[split_header[0].strip] = split_header[1].strip
78
- header = client.gets.delete("\n").delete("\r")
80
+ header = client.gets&.delete("\n")&.delete("\r")
79
81
  end
80
82
  [header, headers]
81
83
  end
@@ -83,7 +85,7 @@ module RequestDataFiltering
83
85
  ##
84
86
  # Method responsible for extracting the body from request
85
87
  def self.extract_body(client, body_first_line, content_length)
86
- body = client.read(content_length)
88
+ body = client&.read(content_length)
87
89
  body_first_line << body.to_s
88
90
  end
89
91
 
@@ -107,13 +109,13 @@ module RequestDataFiltering
107
109
  ##
108
110
  # Method responsible for sanitizing the parameter name
109
111
  def self.sanitize_parameter_name(name)
110
- name.gsub(/[^\w\s]/, '')
112
+ name&.gsub(/[^\w\s]/, '')
111
113
  end
112
114
 
113
115
  ##
114
116
  # Method responsible for sanitizing the parameter value
115
117
  def self.sanitize_parameter_value(value)
116
- value.gsub(/[^\w\s]/, '')
117
- value.gsub(/\s/, '')
118
+ value&.gsub(/[^\w\s]/, '')
119
+ value&.gsub(/\s/, '')
118
120
  end
119
121
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MacawFramework
4
- VERSION = '1.3.1'
4
+ VERSION = '1.3.22'
5
5
  end
@@ -155,11 +155,11 @@ module MacawFramework
155
155
  rescue Interrupt
156
156
  if @macaw_log.nil?
157
157
  puts('Stopping server')
158
- @server.close
158
+ @server.shutdown
159
159
  puts('Macaw stop flying for some seeds...')
160
160
  else
161
161
  @macaw_log.info('Stopping server')
162
- @server.close
162
+ @server.shutdown
163
163
  @macaw_log.info('Macaw stop flying for some seeds...')
164
164
  end
165
165
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: macaw_framework
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.1
4
+ version: 1.3.22
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aria Diniz
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-09-07 00:00:00.000000000 Z
11
+ date: 2025-04-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: prometheus-client
@@ -76,7 +76,7 @@ metadata:
76
76
  documentation_uri: https://rubydoc.info/gems/macaw_framework
77
77
  homepage_uri: https://github.com/ariasdiniz/macaw_framework
78
78
  source_code_uri: https://github.com/ariasdiniz/macaw_framework
79
- post_install_message:
79
+ post_install_message:
80
80
  rdoc_options: []
81
81
  require_paths:
82
82
  - lib
@@ -92,7 +92,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
92
92
  version: '0'
93
93
  requirements: []
94
94
  rubygems_version: 3.4.10
95
- signing_key:
95
+ signing_key:
96
96
  specification_version: 4
97
97
  summary: A lightweight back-end web framework
98
98
  test_files: []