macaw_framework 0.1.5 → 0.2.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +8 -2
- data/CHANGELOG.md +10 -0
- data/Gemfile +2 -0
- data/README.md +24 -7
- data/lib/macaw_framework/aspects/cache_aspect.rb +14 -0
- data/lib/macaw_framework/aspects/logging_aspect.rb +11 -3
- data/lib/macaw_framework/aspects/prometheus_aspect.rb +28 -0
- data/lib/macaw_framework/{middlewares → core}/server.rb +19 -5
- data/lib/macaw_framework/middlewares/caching_middleware.rb +21 -0
- data/lib/macaw_framework/middlewares/prometheus_middleware.rb +48 -0
- data/lib/macaw_framework/version.rb +1 -1
- data/lib/macaw_framework.rb +31 -16
- data/sig/caching_middleware.rbs +5 -0
- data/sig/macaw_framework/macaw.rbs +3 -0
- data/sig/server.rbs +4 -0
- metadata +23 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b2191d627ee06b38338eeef5d88e16791ad96c9ac94fd3b4f8a917cb7a4fd1d6
|
4
|
+
data.tar.gz: 8572db3e03300d28013c29f2bc5238d2f2a4907b087cfc1fe60ff6a8b2369026
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 58cc6a8c9fe40d4f2fead09cf8188ac440dce1444b387a737283285ba1d823b9604ada962305d7c9279bfe0195215b891ecf417715dc755f1b027f75ffa07c13
|
7
|
+
data.tar.gz: 6e8b48c28f83a5eb33f5166c37dc1bbacc2831a3fd31f494e75a5ded27410d006475f12b684da06051b4a6ffe27a3067b1c8dfd5ab0acdaf12ecaba8b444ca60
|
data/.rubocop.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -24,3 +24,13 @@
|
|
24
24
|
- Adding log by aspect on endpoint calls to improve observability
|
25
25
|
- Moving the server for a new separate class to respect single responsibility
|
26
26
|
- Improved the data filtering middleware to sanitize inputs
|
27
|
+
|
28
|
+
## [0.1.5] - 2023-04-16
|
29
|
+
|
30
|
+
- Adding support to path variables
|
31
|
+
|
32
|
+
## [0.2.0] - 2023-04-22
|
33
|
+
|
34
|
+
- Adding middleware for integration with Prometheus to collect metrics
|
35
|
+
- Adding a simple caching mechanism that can be enabled separately for each endpoint
|
36
|
+
- Performance and functional optimizations
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
<img src="macaw_logo.png" alt= “” style="width: 30%;height: 30%;margin-left: 35%">
|
4
4
|
|
5
5
|
This is a framework for developing web applications. Please have in mind that this is still a work in progress and
|
6
|
-
it is strongly advised to not use it for production purposes for now.
|
6
|
+
it is strongly advised to not use it for production purposes for now. Actually it supports only HTTP. and HTTPS/SSL
|
7
7
|
support will be implemented soon. Anyone who wishes to contribute is welcome.
|
8
8
|
|
9
9
|
## Installation
|
@@ -19,7 +19,6 @@ If bundler is not being used to manage dependencies, install the gem by executin
|
|
19
19
|
## Usage
|
20
20
|
|
21
21
|
The usage of the framework still very simple. Actually it support 5 HTTP verbs: GET, POST, PUT, PATCH and DELETE.
|
22
|
-
For now, the framework can't resolve client request body and headers. The support for this will be included soon.
|
23
22
|
|
24
23
|
The default server port is 8080. To choose a different port, create a file with the name `application.json`
|
25
24
|
in the same directory of the script that will start the application with the following content:
|
@@ -29,11 +28,17 @@ in the same directory of the script that will start the application with the fol
|
|
29
28
|
"macaw": {
|
30
29
|
"port": 8080,
|
31
30
|
"bind": "localhost",
|
32
|
-
"threads": 10
|
31
|
+
"threads": 10,
|
32
|
+
"cache": {
|
33
|
+
"cache_invalidation": 3600
|
34
|
+
}
|
33
35
|
}
|
34
36
|
}
|
35
37
|
```
|
36
38
|
|
39
|
+
Cache invalidation time should be specified in seconds. In order to enable caching, The application.json file
|
40
|
+
should exist in the app main directory and it need the `cache_invalidation` config set.
|
41
|
+
|
37
42
|
Example of usage:
|
38
43
|
|
39
44
|
```ruby
|
@@ -42,20 +47,32 @@ require 'json'
|
|
42
47
|
|
43
48
|
m = MacawFramework::Macaw.new
|
44
49
|
|
45
|
-
m.get('/hello_world') do |context|
|
50
|
+
m.get('/hello_world', cache: true) do |context|
|
51
|
+
context[:body] # Returns the request body as string
|
52
|
+
context[:params] # Returns query parameters and path variables as a hash
|
53
|
+
context[:headers] # Returns headers as a hash
|
54
|
+
return JSON.pretty_generate({ hello_message: 'Hello World!' }), 200
|
55
|
+
end
|
56
|
+
|
57
|
+
m.post('/hello_world/:path_variable') do |context|
|
46
58
|
context[:body] # Returns the request body as string
|
47
59
|
context[:params] # Returns query parameters and path variables as a hash
|
48
60
|
context[:headers] # Returns headers as a hash
|
61
|
+
context[:params][:path_variable] # The defined path variable can be found in :params
|
49
62
|
return JSON.pretty_generate({ hello_message: 'Hello World!' }), 200
|
50
63
|
end
|
51
64
|
|
52
65
|
m.start!
|
53
66
|
```
|
54
67
|
|
55
|
-
The
|
68
|
+
The example above starts a server and creates a GET endpoint at localhost/hello_world.
|
69
|
+
|
70
|
+
If prometheus is enabled, a get endpoint will be defined at path `/metrics` to collect prometheus metrics. This path
|
71
|
+
is configurable via the `application.json` file.
|
56
72
|
|
57
|
-
The verb methods must always return a
|
58
|
-
|
73
|
+
The verb methods must always return a string or nil (used as the response) and a number corresponding to the HTTP status
|
74
|
+
code to be returned to the client. If an endpoint doesn't return a value or returns nil for both the string and the
|
75
|
+
code, a default 200 OK status will be sent as the response.
|
59
76
|
|
60
77
|
## Contributing
|
61
78
|
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
##
|
4
|
+
# Aspect that provide cache for the endpoints.
|
5
|
+
module CacheAspect
|
6
|
+
def call_endpoint(cache, endpoints_to_cache, *args)
|
7
|
+
return super(*args) unless endpoints_to_cache.include?(args[0]) && !cache.nil?
|
8
|
+
return cache.cache[args[2..].to_s.to_sym][0] unless cache.cache[args[2..].to_s.to_sym].nil?
|
9
|
+
|
10
|
+
response = super(*args)
|
11
|
+
cache.cache[args[2..].to_s.to_sym] = [response, Time.now]
|
12
|
+
response
|
13
|
+
end
|
14
|
+
end
|
@@ -8,9 +8,17 @@ require "logger"
|
|
8
8
|
# in the framework.
|
9
9
|
module LoggingAspect
|
10
10
|
def call_endpoint(logger, *args)
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
endpoint_name = args[2].split(".")[1..].join("/")
|
12
|
+
logger.info("Request received for #{endpoint_name} with arguments: #{args[3..]}")
|
13
|
+
|
14
|
+
begin
|
15
|
+
response = super(*args)
|
16
|
+
logger.info("Response for #{endpoint_name}: #{response}")
|
17
|
+
rescue StandardError => e
|
18
|
+
logger.error("Error processing #{endpoint_name}: #{e.message}\n#{e.backtrace.join("\n")}")
|
19
|
+
raise e
|
20
|
+
end
|
21
|
+
|
14
22
|
response
|
15
23
|
end
|
16
24
|
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
##
|
4
|
+
# Aspect that provides application metrics using prometheus.
|
5
|
+
module PrometheusAspect
|
6
|
+
def call_endpoint(prometheus_middleware, *args)
|
7
|
+
return super(*args) if prometheus_middleware.nil?
|
8
|
+
|
9
|
+
start_time = Time.now
|
10
|
+
|
11
|
+
begin
|
12
|
+
response = super(*args)
|
13
|
+
ensure
|
14
|
+
duration = (Time.now - start_time) * 1_000
|
15
|
+
|
16
|
+
endpoint_name = args[3].split(".").join("/")
|
17
|
+
|
18
|
+
prometheus_middleware.request_duration_milliseconds.with_labels(endpoint: endpoint_name).observe(duration)
|
19
|
+
prometheus_middleware.request_count.with_labels(endpoint: endpoint_name).increment
|
20
|
+
if response
|
21
|
+
prometheus_middleware.response_count.with_labels(endpoint: endpoint_name,
|
22
|
+
status: response[1]).increment
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
response
|
27
|
+
end
|
28
|
+
end
|
@@ -1,14 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative "../aspects/prometheus_aspect"
|
3
4
|
require_relative "../aspects/logging_aspect"
|
4
5
|
require_relative "../utils/http_status_code"
|
6
|
+
require_relative "../aspects/cache_aspect"
|
5
7
|
|
6
8
|
##
|
7
9
|
# Class responsible for providing a default
|
8
10
|
# webserver.
|
9
11
|
class Server
|
12
|
+
prepend CacheAspect
|
10
13
|
prepend LoggingAspect
|
14
|
+
prepend PrometheusAspect
|
11
15
|
include HttpStatusCode
|
16
|
+
# rubocop:disable Metrics/ParameterLists
|
12
17
|
|
13
18
|
##
|
14
19
|
# Create a new instance of Server.
|
@@ -17,17 +22,26 @@ class Server
|
|
17
22
|
# @param {Integer} port
|
18
23
|
# @param {String} bind
|
19
24
|
# @param {Integer} num_threads
|
25
|
+
# @param {CachingMiddleware} cache
|
26
|
+
# @param {Prometheus::Client:Registry} prometheus
|
20
27
|
# @return {Server}
|
21
|
-
def initialize(macaw, logger, port, bind, num_threads
|
28
|
+
def initialize(macaw, logger, port, bind, num_threads, endpoints_to_cache = nil, cache = nil, prometheus = nil,
|
29
|
+
prometheus_middleware = nil)
|
22
30
|
@port = port
|
23
31
|
@bind = bind
|
24
32
|
@macaw = macaw
|
25
33
|
@macaw_log = logger
|
26
34
|
@num_threads = num_threads
|
27
35
|
@work_queue = Queue.new
|
36
|
+
@endpoints_to_cache = endpoints_to_cache || []
|
37
|
+
@cache = cache
|
38
|
+
@prometheus = prometheus
|
39
|
+
@prometheus_middleware = prometheus_middleware
|
28
40
|
@workers = []
|
29
41
|
end
|
30
42
|
|
43
|
+
# rubocop:enable Metrics/ParameterLists
|
44
|
+
|
31
45
|
##
|
32
46
|
# Start running the webserver.
|
33
47
|
def run
|
@@ -65,17 +79,17 @@ class Server
|
|
65
79
|
raise EndpointNotMappedError unless @macaw.respond_to?(method_name)
|
66
80
|
|
67
81
|
@macaw_log.info("Running #{path.gsub("\n", "").gsub("\r", "")}")
|
68
|
-
message, status = call_endpoint(@
|
82
|
+
message, status = call_endpoint(@prometheus_middleware, @macaw_log, @cache, @endpoints_to_cache,
|
83
|
+
method_name, headers, body, parameters)
|
69
84
|
status ||= 200
|
70
|
-
message ||=
|
85
|
+
message ||= nil
|
71
86
|
client.puts "HTTP/1.1 #{status} #{HTTP_STATUS_CODE_MAP[status]} \r\n\r\n#{message}"
|
72
|
-
client.close
|
73
87
|
rescue EndpointNotMappedError
|
74
88
|
client.print "HTTP/1.1 404 Not Found\r\n\r\n"
|
75
|
-
client.close
|
76
89
|
rescue StandardError => e
|
77
90
|
client.print "HTTP/1.1 500 Internal Server Error\r\n\r\n"
|
78
91
|
@macaw_log.info("Error: #{e}")
|
92
|
+
ensure
|
79
93
|
client.close
|
80
94
|
end
|
81
95
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
##
|
4
|
+
# Middleware responsible for storing and
|
5
|
+
# invalidating cache.
|
6
|
+
class CachingMiddleware
|
7
|
+
attr_accessor :cache
|
8
|
+
|
9
|
+
def initialize(inv_time_seconds = 3_600)
|
10
|
+
@cache = {}
|
11
|
+
Thread.new do
|
12
|
+
loop do
|
13
|
+
sleep(1)
|
14
|
+
@cache.each_pair do |key, value|
|
15
|
+
@cache.delete(key) if Time.now - value[1] >= inv_time_seconds
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
sleep(2)
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "prometheus/client"
|
4
|
+
require "prometheus/client/formats/text"
|
5
|
+
|
6
|
+
##
|
7
|
+
# Middleware responsible to configure prometheus
|
8
|
+
# defining metrics and an endpoint to access them.
|
9
|
+
class PrometheusMiddleware
|
10
|
+
attr_accessor :request_duration_milliseconds, :request_count, :response_count
|
11
|
+
|
12
|
+
def configure_prometheus(prometheus_registry, configurations, macaw)
|
13
|
+
return nil unless prometheus_registry
|
14
|
+
|
15
|
+
@request_duration_milliseconds = Prometheus::Client::Histogram.new(
|
16
|
+
:request_duration_milliseconds,
|
17
|
+
docstring: "The duration of each request in milliseconds",
|
18
|
+
labels: [:endpoint],
|
19
|
+
buckets: (100..1000).step(100).to_a + (2000..10_000).step(1000).to_a
|
20
|
+
)
|
21
|
+
|
22
|
+
@request_count = Prometheus::Client::Counter.new(
|
23
|
+
:request_count,
|
24
|
+
docstring: "The total number of requests received",
|
25
|
+
labels: [:endpoint]
|
26
|
+
)
|
27
|
+
|
28
|
+
@response_count = Prometheus::Client::Counter.new(
|
29
|
+
:response_count,
|
30
|
+
docstring: "The total number of responses sent",
|
31
|
+
labels: %i[endpoint status]
|
32
|
+
)
|
33
|
+
|
34
|
+
prometheus_registry.register(@request_duration_milliseconds)
|
35
|
+
prometheus_registry.register(@request_count)
|
36
|
+
prometheus_registry.register(@response_count)
|
37
|
+
prometheus_endpoint(prometheus_registry, configurations, macaw)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def prometheus_endpoint(prometheus_registry, configurations, macaw)
|
43
|
+
endpoint = configurations["macaw"]["prometheus"]["endpoint"] || "/metrics"
|
44
|
+
macaw.get(endpoint) do |_context|
|
45
|
+
[Prometheus::Client::Formats::Text.marshal(prometheus_registry), 200]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/macaw_framework.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative "macaw_framework/errors/endpoint_not_mapped_error"
|
4
|
+
require_relative "macaw_framework/middlewares/prometheus_middleware"
|
4
5
|
require_relative "macaw_framework/middlewares/request_data_filtering"
|
5
|
-
require_relative "macaw_framework/middlewares/
|
6
|
+
require_relative "macaw_framework/middlewares/caching_middleware"
|
7
|
+
require_relative "macaw_framework/core/server"
|
6
8
|
require_relative "macaw_framework/version"
|
9
|
+
require "prometheus/client"
|
7
10
|
require "logger"
|
8
11
|
require "socket"
|
9
12
|
require "json"
|
@@ -24,16 +27,26 @@ module MacawFramework
|
|
24
27
|
@routes = []
|
25
28
|
@macaw_log ||= custom_log.nil? ? Logger.new($stdout) : custom_log
|
26
29
|
config = JSON.parse(File.read("application.json"))
|
27
|
-
@port = config["macaw"]["port"]
|
28
|
-
@bind = config["macaw"]["bind"]
|
29
|
-
@threads = config["macaw"]["threads"]
|
30
|
+
@port = config["macaw"]["port"] || 8080
|
31
|
+
@bind = config["macaw"]["bind"] || "localhost"
|
32
|
+
@threads = config["macaw"]["threads"] || 5
|
33
|
+
unless config["macaw"]["cache"].nil?
|
34
|
+
@cache = CachingMiddleware.new(config["macaw"]["cache"]["cache_invalidation"].to_i || 3_600)
|
35
|
+
end
|
36
|
+
@prometheus = Prometheus::Client::Registry.new if config["macaw"]["prometheus"]
|
37
|
+
@prometheus_middleware = PrometheusMiddleware.new if config["macaw"]["prometheus"]
|
38
|
+
@prometheus_middleware.configure_prometheus(@prometheus, config, self) if config["macaw"]["prometheus"]
|
30
39
|
rescue StandardError => e
|
31
40
|
@macaw_log.error(e.message)
|
32
41
|
end
|
33
42
|
@port ||= 8080
|
34
43
|
@bind ||= "localhost"
|
35
44
|
@threads ||= 5
|
36
|
-
@
|
45
|
+
@endpoints_to_cache = []
|
46
|
+
@prometheus ||= nil
|
47
|
+
@prometheus_middleware ||= nil
|
48
|
+
@server = server.new(self, @macaw_log, @port, @bind, @threads, @endpoints_to_cache, @cache, @prometheus,
|
49
|
+
@prometheus_middleware)
|
37
50
|
end
|
38
51
|
|
39
52
|
##
|
@@ -42,18 +55,19 @@ module MacawFramework
|
|
42
55
|
# @param {String} path
|
43
56
|
# @param {Proc} block
|
44
57
|
# @return {Integer, String}
|
45
|
-
def get(path, &block)
|
46
|
-
map_new_endpoint("get", path, &block)
|
58
|
+
def get(path, cache: false, &block)
|
59
|
+
map_new_endpoint("get", cache, path, &block)
|
47
60
|
end
|
48
61
|
|
49
62
|
##
|
50
63
|
# Creates a POST endpoint associated
|
51
64
|
# with the respective path.
|
52
65
|
# @param {String} path
|
66
|
+
# @param {Boolean} cache
|
53
67
|
# @param {Proc} block
|
54
68
|
# @return {String, Integer}
|
55
|
-
def post(path, &block)
|
56
|
-
map_new_endpoint("post", path, &block)
|
69
|
+
def post(path, cache: false, &block)
|
70
|
+
map_new_endpoint("post", cache, path, &block)
|
57
71
|
end
|
58
72
|
|
59
73
|
##
|
@@ -62,8 +76,8 @@ module MacawFramework
|
|
62
76
|
# @param {String} path
|
63
77
|
# @param {Proc} block
|
64
78
|
# @return {String, Integer}
|
65
|
-
def put(path, &block)
|
66
|
-
map_new_endpoint("put", path, &block)
|
79
|
+
def put(path, cache: false, &block)
|
80
|
+
map_new_endpoint("put", cache, path, &block)
|
67
81
|
end
|
68
82
|
|
69
83
|
##
|
@@ -72,8 +86,8 @@ module MacawFramework
|
|
72
86
|
# @param {String} path
|
73
87
|
# @param {Proc} block
|
74
88
|
# @return {String, Integer}
|
75
|
-
def patch(path, &block)
|
76
|
-
map_new_endpoint("patch", path, &block)
|
89
|
+
def patch(path, cache: false, &block)
|
90
|
+
map_new_endpoint("patch", cache, path, &block)
|
77
91
|
end
|
78
92
|
|
79
93
|
##
|
@@ -82,8 +96,8 @@ module MacawFramework
|
|
82
96
|
# @param {String} path
|
83
97
|
# @param {Proc} block
|
84
98
|
# @return {String, Integer}
|
85
|
-
def delete(path, &block)
|
86
|
-
map_new_endpoint("delete", path, &block)
|
99
|
+
def delete(path, cache: false, &block)
|
100
|
+
map_new_endpoint("delete", cache, path, &block)
|
87
101
|
end
|
88
102
|
|
89
103
|
##
|
@@ -106,7 +120,8 @@ module MacawFramework
|
|
106
120
|
server.run
|
107
121
|
end
|
108
122
|
|
109
|
-
def map_new_endpoint(prefix, path, &block)
|
123
|
+
def map_new_endpoint(prefix, cache, path, &block)
|
124
|
+
@endpoints_to_cache << "#{prefix}.#{RequestDataFiltering.sanitize_method_name(path)}" if cache
|
110
125
|
path_clean = RequestDataFiltering.extract_path(path)
|
111
126
|
@macaw_log.info("Defining #{prefix.upcase} endpoint at /#{path}")
|
112
127
|
define_singleton_method("#{prefix}.#{path_clean}", block || lambda {
|
data/sig/server.rbs
CHANGED
@@ -1,10 +1,14 @@
|
|
1
1
|
class Server
|
2
2
|
@bind: String
|
3
|
+
@cache: CachingMiddleware
|
4
|
+
@endpoints_to_cache: Array[String]
|
3
5
|
@macaw: MacawFramework::Macaw
|
4
6
|
@macaw_log: Logger
|
5
7
|
@num_threads: Integer
|
6
8
|
@port: Integer
|
7
9
|
|
10
|
+
@prometheus: untyped
|
11
|
+
@prometheus_middleware: untyped
|
8
12
|
@server: TCPServer
|
9
13
|
|
10
14
|
@threads: Integer
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: macaw_framework
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aria Diniz
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-04-
|
12
|
-
dependencies:
|
11
|
+
date: 2023-04-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: prometheus-client
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.1'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.1'
|
13
27
|
description: A project started for study purpose that I intend to keep working on.
|
14
28
|
email:
|
15
29
|
- aria.diniz.dev@gmail.com
|
@@ -25,13 +39,18 @@ files:
|
|
25
39
|
- README.md
|
26
40
|
- Rakefile
|
27
41
|
- lib/macaw_framework.rb
|
42
|
+
- lib/macaw_framework/aspects/cache_aspect.rb
|
28
43
|
- lib/macaw_framework/aspects/logging_aspect.rb
|
44
|
+
- lib/macaw_framework/aspects/prometheus_aspect.rb
|
45
|
+
- lib/macaw_framework/core/server.rb
|
29
46
|
- lib/macaw_framework/errors/endpoint_not_mapped_error.rb
|
47
|
+
- lib/macaw_framework/middlewares/caching_middleware.rb
|
48
|
+
- lib/macaw_framework/middlewares/prometheus_middleware.rb
|
30
49
|
- lib/macaw_framework/middlewares/request_data_filtering.rb
|
31
|
-
- lib/macaw_framework/middlewares/server.rb
|
32
50
|
- lib/macaw_framework/utils/http_status_code.rb
|
33
51
|
- lib/macaw_framework/version.rb
|
34
52
|
- macaw_logo.png
|
53
|
+
- sig/caching_middleware.rbs
|
35
54
|
- sig/http_status_code.rbs
|
36
55
|
- sig/logging_aspect.rbs
|
37
56
|
- sig/macaw_framework.rbs
|