macaw_framework 1.2.4 → 1.2.6
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/CHANGELOG.md +8 -0
 - data/README.md +15 -8
 - data/lib/macaw_framework/aspects/cache_aspect.rb +5 -4
 - data/lib/macaw_framework/core/common/server_base.rb +14 -15
 - data/lib/macaw_framework/core/thread_server.rb +5 -3
 - data/lib/macaw_framework/version.rb +1 -1
 - data/lib/macaw_framework.rb +35 -25
 - data/sig/macaw_framework/macaw.rbs +4 -0
 - metadata +2 -2
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 2353cd5ffe4a264a2eacab71fc2de65c5c4a6b2cd925666529e36b8bdde0ada6
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 4855cf3e106380f6c6718058001cd6cbd888a6c0f1927f833da3bc97cf648785
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 85f5262044b8b3029ad507d501655f72ccd022630b34fc72a5606fe993d223a7e83b245b2ee858adbedf1723717d2d050e1276badf2a353d89612d2c544253a4
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 31b67715e3f2b2c792262d53f6488ae0b8df38c2c1f700fd5590b45927f49dc47fa8c84db884d2ec560b0e981582091b3f38a0f8af06bbddb26efd26f33e2e58
         
     | 
    
        data/CHANGELOG.md
    CHANGED
    
    | 
         @@ -128,3 +128,11 @@ 
     | 
|
| 
       128 
128 
     | 
    
         | 
| 
       129 
129 
     | 
    
         
             
            - Fixing small bug on lof during endpoint declaration
         
     | 
| 
       130 
130 
     | 
    
         
             
            - Disclosing security issue on session storage
         
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
      
 132 
     | 
    
         
            +
            ## [1.2.5]
         
     | 
| 
      
 133 
     | 
    
         
            +
             
     | 
| 
      
 134 
     | 
    
         
            +
            - Improvements to cache usability
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
            ## [1.2.6]
         
     | 
| 
      
 137 
     | 
    
         
            +
             
     | 
| 
      
 138 
     | 
    
         
            +
            - Improving session strategy and fixing vulnerabilities on it.
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -104,7 +104,7 @@ m.start! 
     | 
|
| 
       104 
104 
     | 
    
         
             
            ### Caching: Improve performance by caching responses and configuring cache invalidation
         
     | 
| 
       105 
105 
     | 
    
         | 
| 
       106 
106 
     | 
    
         
             
            ```ruby
         
     | 
| 
       107 
     | 
    
         
            -
            m.get('/cached_data', cache:  
     | 
| 
      
 107 
     | 
    
         
            +
            m.get('/cached_data', cache: ["header_to_cache", "query_param_to_cache"]) do |context|
         
     | 
| 
       108 
108 
     | 
    
         
             
              # Retrieve data
         
     | 
| 
       109 
109 
     | 
    
         
             
            end
         
     | 
| 
       110 
110 
     | 
    
         
             
            ```
         
     | 
| 
         @@ -113,6 +113,15 @@ end 
     | 
|
| 
       113 
113 
     | 
    
         | 
| 
       114 
114 
     | 
    
         
             
            ### Session management: Handle user sessions with server-side in-memory storage
         
     | 
| 
       115 
115 
     | 
    
         | 
| 
      
 116 
     | 
    
         
            +
            Session will only be enabled if it's configurations exists in the `application.json` file.
         
     | 
| 
      
 117 
     | 
    
         
            +
            The session mechanism works by recovering the Session ID from a client sent header. The default
         
     | 
| 
      
 118 
     | 
    
         
            +
            header is `X-Session-ID`, but it can be changed in the `application.json` file.
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
      
 120 
     | 
    
         
            +
            This header will be sent back to the user on every response if Session is enabled. Also, the
         
     | 
| 
      
 121 
     | 
    
         
            +
            session ID will be automatically generated and sent to a client if this client does not provide
         
     | 
| 
      
 122 
     | 
    
         
            +
            a session id in the HTTP request. In the case of the client sending an ID of an expired session
         
     | 
| 
      
 123 
     | 
    
         
            +
            the framework will return a new session with a new ID.
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
       116 
125 
     | 
    
         
             
            ```ruby
         
     | 
| 
       117 
126 
     | 
    
         
             
            m.get('/login') do |context|
         
     | 
| 
       118 
127 
     | 
    
         
             
              # Authenticate user
         
     | 
| 
         @@ -129,8 +138,6 @@ m.get('/dashboard') do |context| 
     | 
|
| 
       129 
138 
     | 
    
         
             
            end
         
     | 
| 
       130 
139 
     | 
    
         
             
            ```
         
     | 
| 
       131 
140 
     | 
    
         | 
| 
       132 
     | 
    
         
            -
            **Caution: This feature is vulnerable to IP spoofing and may disrupt sessions on devices sharing the same network (e.g., Wi-Fi).**
         
     | 
| 
       133 
     | 
    
         
            -
             
     | 
| 
       134 
141 
     | 
    
         
             
            ### Configuration: Customize various aspects of the framework through the application.json configuration file, such as rate limiting, SSL support, and Prometheus integration
         
     | 
| 
       135 
142 
     | 
    
         | 
| 
       136 
143 
     | 
    
         
             
            ```json
         
     | 
| 
         @@ -140,11 +147,7 @@ end 
     | 
|
| 
       140 
147 
     | 
    
         
             
                "bind": "localhost",
         
     | 
| 
       141 
148 
     | 
    
         
             
                "threads": 200,
         
     | 
| 
       142 
149 
     | 
    
         
             
                "cache": {
         
     | 
| 
       143 
     | 
    
         
            -
                  "cache_invalidation": 3600 
     | 
| 
       144 
     | 
    
         
            -
                  "ignore_headers": [
         
     | 
| 
       145 
     | 
    
         
            -
                    "header-to-be-ignored-from-caching-strategy",
         
     | 
| 
       146 
     | 
    
         
            -
                    "another-header-to-be-ignored-from-caching-strategy"
         
     | 
| 
       147 
     | 
    
         
            -
                  ]
         
     | 
| 
      
 150 
     | 
    
         
            +
                  "cache_invalidation": 3600
         
     | 
| 
       148 
151 
     | 
    
         
             
                },
         
     | 
| 
       149 
152 
     | 
    
         
             
                "prometheus": {
         
     | 
| 
       150 
153 
     | 
    
         
             
                  "endpoint": "/metrics"
         
     | 
| 
         @@ -159,6 +162,10 @@ end 
     | 
|
| 
       159 
162 
     | 
    
         
             
                  "key_type": "EC",
         
     | 
| 
       160 
163 
     | 
    
         
             
                  "cert_file_name": "path/to/cert/file/file.crt",
         
     | 
| 
       161 
164 
     | 
    
         
             
                  "key_file_name": "path/to/cert/key/file.key"
         
     | 
| 
      
 165 
     | 
    
         
            +
                },
         
     | 
| 
      
 166 
     | 
    
         
            +
                "session": {
         
     | 
| 
      
 167 
     | 
    
         
            +
                  "secure_header": "X-Session-ID",
         
     | 
| 
      
 168 
     | 
    
         
            +
                  "invalidation_time": 3600
         
     | 
| 
       162 
169 
     | 
    
         
             
                }
         
     | 
| 
       163 
170 
     | 
    
         
             
              }
         
     | 
| 
       164 
171 
     | 
    
         
             
            }
         
     | 
| 
         @@ -6,7 +6,7 @@ module CacheAspect 
     | 
|
| 
       6 
6 
     | 
    
         
             
              def call_endpoint(cache, *args)
         
     | 
| 
       7 
7 
     | 
    
         
             
                return super(*args) unless !cache[:cache].nil? && cache[:endpoints_to_cache]&.include?(args[0])
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
                cache_filtered_name = cache_name_filter(args[1], cache[: 
     | 
| 
      
 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?
         
     | 
| 
         @@ -19,9 +19,10 @@ module CacheAspect 
     | 
|
| 
       19 
19 
     | 
    
         | 
| 
       20 
20 
     | 
    
         
             
              private
         
     | 
| 
       21 
21 
     | 
    
         | 
| 
       22 
     | 
    
         
            -
              def cache_name_filter(client_data,  
     | 
| 
       23 
     | 
    
         
            -
                filtered_headers = client_data[:headers] 
     | 
| 
       24 
     | 
    
         
            -
                 
     | 
| 
      
 22 
     | 
    
         
            +
              def cache_name_filter(client_data, cached_methods_params)
         
     | 
| 
      
 23 
     | 
    
         
            +
                filtered_headers = client_data[:headers]&.filter { |key, _value| cached_methods_params&.include?(key) }
         
     | 
| 
      
 24 
     | 
    
         
            +
                filtered_params = client_data[:params]&.filter { |key, _value| cached_methods_params&.include?(key) }
         
     | 
| 
      
 25 
     | 
    
         
            +
                [{ params: filtered_params, headers: filtered_headers }].to_s.to_sym
         
     | 
| 
       25 
26 
     | 
    
         
             
              end
         
     | 
| 
       26 
27 
     | 
    
         | 
| 
       27 
28 
     | 
    
         
             
              def should_cache_response?(status)
         
     | 
| 
         @@ -8,6 +8,7 @@ require_relative "../../utils/supported_ssl_versions" 
     | 
|
| 
       8 
8 
     | 
    
         
             
            require_relative "../../aspects/prometheus_aspect"
         
     | 
| 
       9 
9 
     | 
    
         
             
            require_relative "../../aspects/logging_aspect"
         
     | 
| 
       10 
10 
     | 
    
         
             
            require_relative "../../aspects/cache_aspect"
         
     | 
| 
      
 11 
     | 
    
         
            +
            require "securerandom"
         
     | 
| 
       11 
12 
     | 
    
         | 
| 
       12 
13 
     | 
    
         
             
            ##
         
     | 
| 
       13 
14 
     | 
    
         
             
            # Base module for Server classes. It contains
         
     | 
| 
         @@ -21,14 +22,14 @@ module ServerBase 
     | 
|
| 
       21 
22 
     | 
    
         | 
| 
       22 
23 
     | 
    
         
             
              private
         
     | 
| 
       23 
24 
     | 
    
         | 
| 
       24 
     | 
    
         
            -
              def call_endpoint(name, client_data,  
     | 
| 
      
 25 
     | 
    
         
            +
              def call_endpoint(name, client_data, session_id, _client_ip)
         
     | 
| 
       25 
26 
     | 
    
         
             
                @macaw.send(
         
     | 
| 
       26 
27 
     | 
    
         
             
                  name.to_sym,
         
     | 
| 
       27 
28 
     | 
    
         
             
                  {
         
     | 
| 
       28 
29 
     | 
    
         
             
                    headers: client_data[:headers],
         
     | 
| 
       29 
30 
     | 
    
         
             
                    body: client_data[:body],
         
     | 
| 
       30 
31 
     | 
    
         
             
                    params: client_data[:params],
         
     | 
| 
       31 
     | 
    
         
            -
                    client: @session[ 
     | 
| 
      
 32 
     | 
    
         
            +
                    client: @session[session_id][0]
         
     | 
| 
       32 
33 
     | 
    
         
             
                  }
         
     | 
| 
       33 
34 
     | 
    
         
             
                )
         
     | 
| 
       34 
35 
     | 
    
         
             
              end
         
     | 
| 
         @@ -42,12 +43,14 @@ module ServerBase 
     | 
|
| 
       42 
43 
     | 
    
         
             
                raise EndpointNotMappedError unless @macaw.respond_to?(method_name)
         
     | 
| 
       43 
44 
     | 
    
         
             
                raise TooManyRequestsError unless @rate_limit.nil? || @rate_limit.allow?(client.peeraddr[3])
         
     | 
| 
       44 
45 
     | 
    
         | 
| 
       45 
     | 
    
         
            -
                declare_client_session(client)
         
     | 
| 
       46 
46 
     | 
    
         
             
                client_data = get_client_data(body, headers, parameters)
         
     | 
| 
      
 47 
     | 
    
         
            +
                session_id = declare_client_session(client_data[:headers], @macaw.secure_header) if @macaw.session
         
     | 
| 
       47 
48 
     | 
    
         | 
| 
       48 
49 
     | 
    
         
             
                @macaw_log&.info("Running #{path.gsub("\n", "").gsub("\r", "")}")
         
     | 
| 
       49 
50 
     | 
    
         
             
                message, status, response_headers = call_endpoint(@prometheus_middleware, @macaw_log, @cache,
         
     | 
| 
       50 
     | 
    
         
            -
                                                                  method_name, client_data, client.peeraddr[3])
         
     | 
| 
      
 51 
     | 
    
         
            +
                                                                  method_name, client_data, session_id, client.peeraddr[3])
         
     | 
| 
      
 52 
     | 
    
         
            +
                response_headers ||= {}
         
     | 
| 
      
 53 
     | 
    
         
            +
                response_headers[@macaw.secure_header] = session_id if @macaw.session
         
     | 
| 
       51 
54 
     | 
    
         
             
                status ||= 200
         
     | 
| 
       52 
55 
     | 
    
         
             
                message ||= nil
         
     | 
| 
       53 
56 
     | 
    
         
             
                response_headers ||= nil
         
     | 
| 
         @@ -69,9 +72,11 @@ module ServerBase 
     | 
|
| 
       69 
72 
     | 
    
         
             
                end
         
     | 
| 
       70 
73 
     | 
    
         
             
              end
         
     | 
| 
       71 
74 
     | 
    
         | 
| 
       72 
     | 
    
         
            -
              def declare_client_session( 
     | 
| 
       73 
     | 
    
         
            -
                 
     | 
| 
       74 
     | 
    
         
            -
                 
     | 
| 
      
 75 
     | 
    
         
            +
              def declare_client_session(headers, secure_header_name)
         
     | 
| 
      
 76 
     | 
    
         
            +
                session_id = headers[secure_header_name] || SecureRandom.uuid
         
     | 
| 
      
 77 
     | 
    
         
            +
                session_id = SecureRandom.uuid if @session[session_id].nil?
         
     | 
| 
      
 78 
     | 
    
         
            +
                @session[session_id] ||= [{}, Time.now]
         
     | 
| 
      
 79 
     | 
    
         
            +
                session_id
         
     | 
| 
       75 
80 
     | 
    
         
             
              end
         
     | 
| 
       76 
81 
     | 
    
         | 
| 
       77 
82 
     | 
    
         
             
              def set_rate_limiting
         
     | 
| 
         @@ -83,12 +88,6 @@ module ServerBase 
     | 
|
| 
       83 
88 
     | 
    
         
             
                )
         
     | 
| 
       84 
89 
     | 
    
         
             
              end
         
     | 
| 
       85 
90 
     | 
    
         | 
| 
       86 
     | 
    
         
            -
              def set_cache_ignored_h
         
     | 
| 
       87 
     | 
    
         
            -
                return unless @macaw.config&.dig("macaw", "cache", "ignore_headers")
         
     | 
| 
       88 
     | 
    
         
            -
             
     | 
| 
       89 
     | 
    
         
            -
                @macaw.config["macaw"]["cache"]["ignore_headers"] || []
         
     | 
| 
       90 
     | 
    
         
            -
              end
         
     | 
| 
       91 
     | 
    
         
            -
             
     | 
| 
       92 
91 
     | 
    
         
             
              def set_ssl
         
     | 
| 
       93 
92 
     | 
    
         
             
                ssl_config = @macaw.config["macaw"]["ssl"] if @macaw.config&.dig("macaw", "ssl")
         
     | 
| 
       94 
93 
     | 
    
         
             
                ssl_config ||= nil
         
     | 
| 
         @@ -116,7 +115,7 @@ module ServerBase 
     | 
|
| 
       116 
115 
     | 
    
         
             
              end
         
     | 
| 
       117 
116 
     | 
    
         | 
| 
       118 
117 
     | 
    
         
             
              def set_session
         
     | 
| 
       119 
     | 
    
         
            -
                @session  
     | 
| 
      
 118 
     | 
    
         
            +
                @session ||= {}
         
     | 
| 
       120 
119 
     | 
    
         
             
                inv = if @macaw.config&.dig("macaw", "session", "invalidation_time")
         
     | 
| 
       121 
120 
     | 
    
         
             
                        MemoryInvalidationMiddleware.new(@macaw.config["macaw"]["session"]["invalidation_time"])
         
     | 
| 
       122 
121 
     | 
    
         
             
                      else
         
     | 
| 
         @@ -128,7 +127,7 @@ module ServerBase 
     | 
|
| 
       128 
127 
     | 
    
         
             
              def set_features
         
     | 
| 
       129 
128 
     | 
    
         
             
                @is_shutting_down = false
         
     | 
| 
       130 
129 
     | 
    
         
             
                set_rate_limiting
         
     | 
| 
       131 
     | 
    
         
            -
                set_session
         
     | 
| 
      
 130 
     | 
    
         
            +
                set_session if @macaw.session
         
     | 
| 
       132 
131 
     | 
    
         
             
                set_ssl
         
     | 
| 
       133 
132 
     | 
    
         
             
              end
         
     | 
| 
       134 
133 
     | 
    
         
             
            end
         
     | 
| 
         @@ -32,11 +32,13 @@ class ThreadServer 
     | 
|
| 
       32 
32 
     | 
    
         
             
                @macaw_log = macaw.macaw_log
         
     | 
| 
       33 
33 
     | 
    
         
             
                @num_threads = macaw.threads
         
     | 
| 
       34 
34 
     | 
    
         
             
                @work_queue = Queue.new
         
     | 
| 
       35 
     | 
    
         
            -
                ignored_headers = set_cache_ignored_h
         
     | 
| 
       36 
35 
     | 
    
         
             
                set_features
         
     | 
| 
       37 
36 
     | 
    
         
             
                @rate_limit ||= nil
         
     | 
| 
       38 
     | 
    
         
            -
                 
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
      
 37 
     | 
    
         
            +
                @cache = {
         
     | 
| 
      
 38 
     | 
    
         
            +
                  cache: cache,
         
     | 
| 
      
 39 
     | 
    
         
            +
                  endpoints_to_cache: endpoints_to_cache || [],
         
     | 
| 
      
 40 
     | 
    
         
            +
                  cached_methods: macaw.cached_methods
         
     | 
| 
      
 41 
     | 
    
         
            +
                }
         
     | 
| 
       40 
42 
     | 
    
         
             
                @prometheus = prometheus
         
     | 
| 
       41 
43 
     | 
    
         
             
                @prometheus_middleware = prometheus_mw
         
     | 
| 
       42 
44 
     | 
    
         
             
                @workers = []
         
     | 
    
        data/lib/macaw_framework.rb
    CHANGED
    
    | 
         @@ -19,30 +19,16 @@ module MacawFramework 
     | 
|
| 
       19 
19 
     | 
    
         
             
              # Class responsible for creating endpoints and
         
     | 
| 
       20 
20 
     | 
    
         
             
              # starting the web server.
         
     | 
| 
       21 
21 
     | 
    
         
             
              class Macaw
         
     | 
| 
       22 
     | 
    
         
            -
                 
     | 
| 
       23 
     | 
    
         
            -
                # Array containing the routes defined in the application
         
     | 
| 
       24 
     | 
    
         
            -
                attr_reader :routes, :macaw_log, :config, :jobs
         
     | 
| 
      
 22 
     | 
    
         
            +
                attr_reader :routes, :macaw_log, :config, :jobs, :cached_methods, :secure_header, :session
         
     | 
| 
       25 
23 
     | 
    
         
             
                attr_accessor :port, :bind, :threads
         
     | 
| 
       26 
24 
     | 
    
         | 
| 
       27 
25 
     | 
    
         
             
                ##
         
     | 
| 
      
 26 
     | 
    
         
            +
                # Initialize Macaw Class
         
     | 
| 
       28 
27 
     | 
    
         
             
                # @param {Logger} custom_log
         
     | 
| 
      
 28 
     | 
    
         
            +
                # @param {ThreadServer} server
         
     | 
| 
      
 29 
     | 
    
         
            +
                # @param {String?} dir
         
     | 
| 
       29 
30 
     | 
    
         
             
                def initialize(custom_log: Logger.new($stdout), server: ThreadServer, dir: nil)
         
     | 
| 
       30 
     | 
    
         
            -
                   
     | 
| 
       31 
     | 
    
         
            -
                    @routes = []
         
     | 
| 
       32 
     | 
    
         
            -
                    @macaw_log ||= custom_log
         
     | 
| 
       33 
     | 
    
         
            -
                    @config = JSON.parse(File.read("application.json"))
         
     | 
| 
       34 
     | 
    
         
            -
                    @port = @config["macaw"]["port"] || 8080
         
     | 
| 
       35 
     | 
    
         
            -
                    @bind = @config["macaw"]["bind"] || "localhost"
         
     | 
| 
       36 
     | 
    
         
            -
                    @threads = @config["macaw"]["threads"] || 200
         
     | 
| 
       37 
     | 
    
         
            -
                    unless @config["macaw"]["cache"].nil?
         
     | 
| 
       38 
     | 
    
         
            -
                      @cache = MemoryInvalidationMiddleware.new(@config["macaw"]["cache"]["cache_invalidation"].to_i || 3_600)
         
     | 
| 
       39 
     | 
    
         
            -
                    end
         
     | 
| 
       40 
     | 
    
         
            -
                    @prometheus = Prometheus::Client::Registry.new if @config["macaw"]["prometheus"]
         
     | 
| 
       41 
     | 
    
         
            -
                    @prometheus_middleware = PrometheusMiddleware.new if @config["macaw"]["prometheus"]
         
     | 
| 
       42 
     | 
    
         
            -
                    @prometheus_middleware.configure_prometheus(@prometheus, @config, self) if @config["macaw"]["prometheus"]
         
     | 
| 
       43 
     | 
    
         
            -
                  rescue StandardError => e
         
     | 
| 
       44 
     | 
    
         
            -
                    @macaw_log&.warn(e.message)
         
     | 
| 
       45 
     | 
    
         
            -
                  end
         
     | 
| 
      
 31 
     | 
    
         
            +
                  apply_options(custom_log)
         
     | 
| 
       46 
32 
     | 
    
         
             
                  create_endpoint_public_files(dir)
         
     | 
| 
       47 
33 
     | 
    
         
             
                  @port ||= 8080
         
     | 
| 
       48 
34 
     | 
    
         
             
                  @bind ||= "localhost"
         
     | 
| 
         @@ -65,7 +51,7 @@ module MacawFramework 
     | 
|
| 
       65 
51 
     | 
    
         
             
                # macaw.get("/hello") do |context|
         
     | 
| 
       66 
52 
     | 
    
         
             
                #   return "Hello World!", 200, { "Content-Type" => "text/plain" }
         
     | 
| 
       67 
53 
     | 
    
         
             
                # end
         
     | 
| 
       68 
     | 
    
         
            -
                def get(path, cache:  
     | 
| 
      
 54 
     | 
    
         
            +
                def get(path, cache: [], &block)
         
     | 
| 
       69 
55 
     | 
    
         
             
                  map_new_endpoint("get", cache, path, &block)
         
     | 
| 
       70 
56 
     | 
    
         
             
                end
         
     | 
| 
       71 
57 
     | 
    
         | 
| 
         @@ -81,7 +67,7 @@ module MacawFramework 
     | 
|
| 
       81 
67 
     | 
    
         
             
                # macaw.post("/hello") do |context|
         
     | 
| 
       82 
68 
     | 
    
         
             
                #   return "Hello World!", 200, { "Content-Type" => "text/plain" }
         
     | 
| 
       83 
69 
     | 
    
         
             
                # end
         
     | 
| 
       84 
     | 
    
         
            -
                def post(path, cache:  
     | 
| 
      
 70 
     | 
    
         
            +
                def post(path, cache: [], &block)
         
     | 
| 
       85 
71 
     | 
    
         
             
                  map_new_endpoint("post", cache, path, &block)
         
     | 
| 
       86 
72 
     | 
    
         
             
                end
         
     | 
| 
       87 
73 
     | 
    
         | 
| 
         @@ -96,7 +82,7 @@ module MacawFramework 
     | 
|
| 
       96 
82 
     | 
    
         
             
                # macaw.put("/hello") do |context|
         
     | 
| 
       97 
83 
     | 
    
         
             
                #   return "Hello World!", 200, { "Content-Type" => "text/plain" }
         
     | 
| 
       98 
84 
     | 
    
         
             
                # end
         
     | 
| 
       99 
     | 
    
         
            -
                def put(path, cache:  
     | 
| 
      
 85 
     | 
    
         
            +
                def put(path, cache: [], &block)
         
     | 
| 
       100 
86 
     | 
    
         
             
                  map_new_endpoint("put", cache, path, &block)
         
     | 
| 
       101 
87 
     | 
    
         
             
                end
         
     | 
| 
       102 
88 
     | 
    
         | 
| 
         @@ -111,7 +97,7 @@ module MacawFramework 
     | 
|
| 
       111 
97 
     | 
    
         
             
                # macaw.patch("/hello") do |context|
         
     | 
| 
       112 
98 
     | 
    
         
             
                #   return "Hello World!", 200, { "Content-Type" => "text/plain" }
         
     | 
| 
       113 
99 
     | 
    
         
             
                # end
         
     | 
| 
       114 
     | 
    
         
            -
                def patch(path, cache:  
     | 
| 
      
 100 
     | 
    
         
            +
                def patch(path, cache: [], &block)
         
     | 
| 
       115 
101 
     | 
    
         
             
                  map_new_endpoint("patch", cache, path, &block)
         
     | 
| 
       116 
102 
     | 
    
         
             
                end
         
     | 
| 
       117 
103 
     | 
    
         | 
| 
         @@ -126,7 +112,7 @@ module MacawFramework 
     | 
|
| 
       126 
112 
     | 
    
         
             
                # macaw.delete("/hello") do |context|
         
     | 
| 
       127 
113 
     | 
    
         
             
                #   return "Hello World!", 200, { "Content-Type" => "text/plain" }
         
     | 
| 
       128 
114 
     | 
    
         
             
                # end
         
     | 
| 
       129 
     | 
    
         
            -
                def delete(path, cache:  
     | 
| 
      
 115 
     | 
    
         
            +
                def delete(path, cache: [], &block)
         
     | 
| 
       130 
116 
     | 
    
         
             
                  map_new_endpoint("delete", cache, path, &block)
         
     | 
| 
       131 
117 
     | 
    
         
             
                end
         
     | 
| 
       132 
118 
     | 
    
         | 
| 
         @@ -191,12 +177,36 @@ module MacawFramework 
     | 
|
| 
       191 
177 
     | 
    
         | 
| 
       192 
178 
     | 
    
         
             
                private
         
     | 
| 
       193 
179 
     | 
    
         | 
| 
      
 180 
     | 
    
         
            +
                def apply_options(custom_log)
         
     | 
| 
      
 181 
     | 
    
         
            +
                  @routes = []
         
     | 
| 
      
 182 
     | 
    
         
            +
                  @cached_methods = {}
         
     | 
| 
      
 183 
     | 
    
         
            +
                  @macaw_log ||= custom_log
         
     | 
| 
      
 184 
     | 
    
         
            +
                  @config = JSON.parse(File.read("application.json"))
         
     | 
| 
      
 185 
     | 
    
         
            +
                  @port = @config["macaw"]["port"] || 8080
         
     | 
| 
      
 186 
     | 
    
         
            +
                  @bind = @config["macaw"]["bind"] || "localhost"
         
     | 
| 
      
 187 
     | 
    
         
            +
                  @session = false
         
     | 
| 
      
 188 
     | 
    
         
            +
                  unless @config["macaw"]["session"].nil?
         
     | 
| 
      
 189 
     | 
    
         
            +
                    @session = true
         
     | 
| 
      
 190 
     | 
    
         
            +
                    @secure_header = @config["macaw"]["session"]["secure_header"] || "X-Session-ID"
         
     | 
| 
      
 191 
     | 
    
         
            +
                  end
         
     | 
| 
      
 192 
     | 
    
         
            +
                  @threads = @config["macaw"]["threads"] || 200
         
     | 
| 
      
 193 
     | 
    
         
            +
                  unless @config["macaw"]["cache"].nil?
         
     | 
| 
      
 194 
     | 
    
         
            +
                    @cache = MemoryInvalidationMiddleware.new(@config["macaw"]["cache"]["cache_invalidation"].to_i || 3_600)
         
     | 
| 
      
 195 
     | 
    
         
            +
                  end
         
     | 
| 
      
 196 
     | 
    
         
            +
                  @prometheus = Prometheus::Client::Registry.new if @config["macaw"]["prometheus"]
         
     | 
| 
      
 197 
     | 
    
         
            +
                  @prometheus_middleware = PrometheusMiddleware.new if @config["macaw"]["prometheus"]
         
     | 
| 
      
 198 
     | 
    
         
            +
                  @prometheus_middleware.configure_prometheus(@prometheus, @config, self) if @config["macaw"]["prometheus"]
         
     | 
| 
      
 199 
     | 
    
         
            +
                rescue StandardError => e
         
     | 
| 
      
 200 
     | 
    
         
            +
                  @macaw_log&.warn(e.message)
         
     | 
| 
      
 201 
     | 
    
         
            +
                end
         
     | 
| 
      
 202 
     | 
    
         
            +
             
     | 
| 
       194 
203 
     | 
    
         
             
                def server_loop(server)
         
     | 
| 
       195 
204 
     | 
    
         
             
                  server.run
         
     | 
| 
       196 
205 
     | 
    
         
             
                end
         
     | 
| 
       197 
206 
     | 
    
         | 
| 
       198 
207 
     | 
    
         
             
                def map_new_endpoint(prefix, cache, path, &block)
         
     | 
| 
       199 
     | 
    
         
            -
                  @endpoints_to_cache << "#{prefix}.#{RequestDataFiltering.sanitize_method_name(path)}"  
     | 
| 
      
 208 
     | 
    
         
            +
                  @endpoints_to_cache << "#{prefix}.#{RequestDataFiltering.sanitize_method_name(path)}" unless cache.empty?
         
     | 
| 
      
 209 
     | 
    
         
            +
                  @cached_methods["#{prefix}.#{RequestDataFiltering.sanitize_method_name(path)}"] = cache unless cache.empty?
         
     | 
| 
       200 
210 
     | 
    
         
             
                  path_clean = RequestDataFiltering.extract_path(path)
         
     | 
| 
       201 
211 
     | 
    
         
             
                  slash = path[0] == "/" ? "" : "/"
         
     | 
| 
       202 
212 
     | 
    
         
             
                  @macaw_log&.info("Defining #{prefix.upcase} endpoint at #{slash}#{path}")
         
     | 
| 
         @@ -2,6 +2,7 @@ module MacawFramework 
     | 
|
| 
       2 
2 
     | 
    
         
             
              class Macaw
         
     | 
| 
       3 
3 
     | 
    
         
             
                @bind: String
         
     | 
| 
       4 
4 
     | 
    
         
             
                @cache: untyped
         
     | 
| 
      
 5 
     | 
    
         
            +
                @cached_methods: Hash[String, Array[String]]
         
     | 
| 
       5 
6 
     | 
    
         
             
                @config: Hash[String, untyped]
         
     | 
| 
       6 
7 
     | 
    
         
             
                @cron_runner: CronRunner
         
     | 
| 
       7 
8 
     | 
    
         
             
                @endpoints_to_cache: Array[String]
         
     | 
| 
         @@ -9,8 +10,11 @@ module MacawFramework 
     | 
|
| 
       9 
10 
     | 
    
         | 
| 
       10 
11 
     | 
    
         
             
                @prometheus: untyped
         
     | 
| 
       11 
12 
     | 
    
         
             
                @prometheus_middleware: untyped
         
     | 
| 
      
 13 
     | 
    
         
            +
                @secure_header: String
         
     | 
| 
       12 
14 
     | 
    
         
             
                @server: untyped
         
     | 
| 
       13 
15 
     | 
    
         | 
| 
      
 16 
     | 
    
         
            +
                @server_class: untyped
         
     | 
| 
      
 17 
     | 
    
         
            +
                @session: bool
         
     | 
| 
       14 
18 
     | 
    
         
             
                @threads: Integer
         
     | 
| 
       15 
19 
     | 
    
         | 
| 
       16 
20 
     | 
    
         
             
                attr_accessor bind: String
         
     | 
    
        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.2. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 1.2.6
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Aria Diniz
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: exe
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date: 2024- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2024-04-29 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: prometheus-client
         
     |