hanami 2.0.0.alpha4 → 2.0.0.alpha7
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 +256 -0
- data/README.md +3 -7
- data/hanami.gemspec +5 -4
- data/lib/hanami/application/container/{boot → providers}/inflector.rb +1 -1
- data/lib/hanami/application/container/{boot → providers}/logger.rb +1 -1
- data/lib/hanami/application/container/providers/rack_logger.rb +15 -0
- data/lib/hanami/application/container/{boot → providers}/rack_monitor.rb +2 -2
- data/lib/hanami/application/container/{boot → providers}/routes_helper.rb +1 -1
- data/lib/hanami/application/container/{boot → providers}/settings.rb +1 -1
- data/lib/hanami/application/router.rb +7 -7
- data/lib/hanami/application/routing/router.rb +36 -0
- data/lib/hanami/application/slice_registrar.rb +107 -0
- data/lib/hanami/application.rb +124 -202
- data/lib/hanami/boot/source_dirs.rb +44 -0
- data/lib/hanami/cli/application/cli.rb +1 -1
- data/lib/hanami/configuration/actions.rb +90 -0
- data/lib/hanami/configuration/logger.rb +49 -5
- data/lib/hanami/configuration/source_dirs.rb +42 -0
- data/lib/hanami/configuration.rb +19 -24
- data/lib/hanami/constants.rb +23 -0
- data/lib/hanami/errors.rb +12 -0
- data/lib/hanami/{init.rb → prepare.rb} +1 -1
- data/lib/hanami/slice.rb +198 -112
- data/lib/hanami/version.rb +1 -1
- data/lib/hanami/web/rack_logger.rb +27 -51
- data/lib/hanami.rb +19 -29
- metadata +23 -16
- data/lib/hanami/application/autoloader/inflector_adapter.rb +0 -22
- data/lib/hanami/application/container/boot/rack_logger.rb +0 -19
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "dry/configurable"
|
4
|
+
require "dry/system/config/component_dirs"
|
5
|
+
|
6
|
+
module Hanami
|
7
|
+
class Configuration
|
8
|
+
# Configuration for slice source dirs
|
9
|
+
#
|
10
|
+
# @since 2.0.0
|
11
|
+
class SourceDirs
|
12
|
+
DEFAULT_COMPONENT_DIR_PATHS = %w[lib actions repositories views].freeze
|
13
|
+
private_constant :DEFAULT_COMPONENT_DIR_PATHS
|
14
|
+
|
15
|
+
include Dry::Configurable
|
16
|
+
|
17
|
+
setting :component_dirs,
|
18
|
+
default: Dry::System::Config::ComponentDirs.new.tap { |dirs|
|
19
|
+
DEFAULT_COMPONENT_DIR_PATHS.each do |path|
|
20
|
+
dirs.add path
|
21
|
+
end
|
22
|
+
},
|
23
|
+
cloneable: true
|
24
|
+
|
25
|
+
setting :autoload_paths, default: %w[entities]
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def method_missing(name, *args, &block)
|
30
|
+
if config.respond_to?(name)
|
31
|
+
config.public_send(name, *args, &block)
|
32
|
+
else
|
33
|
+
super
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def respond_to_missing?(name, _include_all = false)
|
38
|
+
config.respond_to?(name) || super
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/hanami/configuration.rb
CHANGED
@@ -12,6 +12,8 @@ require_relative "configuration/logger"
|
|
12
12
|
require_relative "configuration/middleware"
|
13
13
|
require_relative "configuration/router"
|
14
14
|
require_relative "configuration/sessions"
|
15
|
+
require_relative "configuration/source_dirs"
|
16
|
+
require_relative "constants"
|
15
17
|
|
16
18
|
module Hanami
|
17
19
|
# Hanami application configuration
|
@@ -25,6 +27,8 @@ module Hanami
|
|
25
27
|
DEFAULT_ENVIRONMENTS = Concurrent::Hash.new { |h, k| h[k] = Concurrent::Array.new }
|
26
28
|
private_constant :DEFAULT_ENVIRONMENTS
|
27
29
|
|
30
|
+
attr_reader :env
|
31
|
+
|
28
32
|
attr_reader :actions
|
29
33
|
attr_reader :middleware
|
30
34
|
attr_reader :router
|
@@ -33,15 +37,19 @@ module Hanami
|
|
33
37
|
attr_reader :environments
|
34
38
|
private :environments
|
35
39
|
|
36
|
-
def initialize(env:)
|
40
|
+
def initialize(application_name:, env:)
|
41
|
+
@namespace = application_name.split(MODULE_DELIMITER)[0..-2].join(MODULE_DELIMITER)
|
42
|
+
|
37
43
|
@environments = DEFAULT_ENVIRONMENTS.clone
|
38
|
-
|
44
|
+
@env = env
|
39
45
|
|
40
46
|
# Some default setting values must be assigned at initialize-time to ensure they
|
41
47
|
# have appropriate values for the current application
|
42
48
|
self.root = Dir.pwd
|
43
49
|
self.settings_store = Application::Settings::DotenvStore.new.with_dotenv_loaded
|
44
50
|
|
51
|
+
config.logger = Configuration::Logger.new(env: env, application_name: method(:application_name))
|
52
|
+
|
45
53
|
@assets = begin
|
46
54
|
require_path = "hanami/assets/application_configuration"
|
47
55
|
require require_path
|
@@ -101,29 +109,30 @@ module Hanami
|
|
101
109
|
super
|
102
110
|
end
|
103
111
|
|
104
|
-
|
112
|
+
def namespace
|
113
|
+
inflector.constantize(@namespace)
|
114
|
+
end
|
105
115
|
|
106
|
-
def
|
107
|
-
|
108
|
-
apply_env_config(new_env)
|
116
|
+
def application_name
|
117
|
+
inflector.underscore(@namespace).to_sym
|
109
118
|
end
|
110
119
|
|
111
120
|
setting :root, constructor: -> path { Pathname(path) }
|
112
121
|
|
113
|
-
setting :inflector, default: Dry::Inflector.new
|
122
|
+
setting :inflector, default: Dry::Inflector.new
|
114
123
|
|
115
124
|
def inflections(&block)
|
116
125
|
self.inflector = Dry::Inflector.new(&block)
|
117
126
|
end
|
118
127
|
|
119
|
-
setting :logger,
|
128
|
+
setting :logger, cloneable: true
|
120
129
|
|
121
130
|
def logger=(logger_instance)
|
122
131
|
@logger_instance = logger_instance
|
123
132
|
end
|
124
133
|
|
125
134
|
def logger_instance
|
126
|
-
@logger_instance || logger.
|
135
|
+
@logger_instance || logger.instance
|
127
136
|
end
|
128
137
|
|
129
138
|
setting :settings_path, default: File.join("config", "settings")
|
@@ -132,21 +141,7 @@ module Hanami
|
|
132
141
|
|
133
142
|
setting :settings_store, default: Application::Settings::DotenvStore
|
134
143
|
|
135
|
-
setting :
|
136
|
-
|
137
|
-
setting :slices_namespace, default: Object
|
138
|
-
|
139
|
-
# TODO: convert into a dedicated object with explicit behaviour around blocks per
|
140
|
-
# slice, etc.
|
141
|
-
setting :slices, default: {}, constructor: :dup.to_proc
|
142
|
-
|
143
|
-
# TODO: turn this into a richer "source dirs" setting that can support enabling
|
144
|
-
# of container component loading as an opt in behvior
|
145
|
-
setting :component_dir_paths, default: %w[actions repositories views]
|
146
|
-
|
147
|
-
def slice(slice_name, &block)
|
148
|
-
slices[slice_name] = block
|
149
|
-
end
|
144
|
+
setting :source_dirs, default: Configuration::SourceDirs.new, cloneable: true
|
150
145
|
|
151
146
|
setting :base_url, default: "http://0.0.0.0:2300", constructor: -> url { URI(url) }
|
152
147
|
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Hanami
|
4
|
+
# @api private
|
5
|
+
MODULE_DELIMITER = "::"
|
6
|
+
private_constant :MODULE_DELIMITER
|
7
|
+
|
8
|
+
# @api private
|
9
|
+
CONFIG_DIR = "config"
|
10
|
+
private_constant :CONFIG_DIR
|
11
|
+
|
12
|
+
# @api private
|
13
|
+
SLICES_DIR = "slices"
|
14
|
+
private_constant :SLICES_DIR
|
15
|
+
|
16
|
+
# @api private
|
17
|
+
LIB_DIR = "lib"
|
18
|
+
private_constant :LIB_DIR
|
19
|
+
|
20
|
+
# @api private
|
21
|
+
RB_EXT = ".rb"
|
22
|
+
private_constant :RB_EXT
|
23
|
+
end
|
data/lib/hanami/slice.rb
CHANGED
@@ -1,167 +1,253 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "dry/system/container"
|
4
|
-
require "
|
4
|
+
require "hanami/errors"
|
5
5
|
require "pathname"
|
6
|
+
require_relative "constants"
|
6
7
|
|
7
8
|
module Hanami
|
8
9
|
# Distinct area of concern within an Hanami application
|
9
10
|
#
|
10
11
|
# @since 2.0.0
|
11
12
|
class Slice
|
12
|
-
|
13
|
-
|
14
|
-
def initialize(application, name:, namespace: nil, root: nil, container: nil)
|
15
|
-
@application = application
|
16
|
-
@name = name.to_sym
|
17
|
-
@namespace = namespace
|
18
|
-
@root = root ? Pathname(root) : root
|
19
|
-
@container = container || define_container
|
20
|
-
end
|
13
|
+
def self.inherited(klass)
|
14
|
+
super
|
21
15
|
|
22
|
-
|
23
|
-
application.inflector
|
24
|
-
end
|
16
|
+
klass.extend(ClassMethods)
|
25
17
|
|
26
|
-
|
27
|
-
|
18
|
+
# Eagerly initialize any variables that may be accessed inside the subclass body
|
19
|
+
klass.instance_variable_set(:@application, Hanami.application)
|
20
|
+
klass.instance_variable_set(:@container, Class.new(Dry::System::Container))
|
28
21
|
end
|
29
22
|
|
30
|
-
|
31
|
-
|
23
|
+
# rubocop:disable Metrics/ModuleLength
|
24
|
+
module ClassMethods
|
25
|
+
attr_reader :application, :container
|
32
26
|
|
33
|
-
|
34
|
-
|
35
|
-
|
27
|
+
def slice_name
|
28
|
+
inflector.underscore(name.split(MODULE_DELIMITER)[-2]).to_sym
|
29
|
+
end
|
36
30
|
|
37
|
-
|
38
|
-
|
39
|
-
container.config.env = application.container.config.env
|
31
|
+
def namespace
|
32
|
+
inflector.constantize(name.split(MODULE_DELIMITER)[0..-2].join(MODULE_DELIMITER))
|
40
33
|
end
|
41
34
|
|
42
|
-
|
43
|
-
|
44
|
-
|
35
|
+
def namespace_path
|
36
|
+
inflector.underscore(namespace)
|
37
|
+
end
|
45
38
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
end
|
50
|
-
# rubocop:enable Style/DoubleNegation
|
39
|
+
def root
|
40
|
+
application.root.join(SLICES_DIR, slice_name.to_s)
|
41
|
+
end
|
51
42
|
|
52
|
-
|
53
|
-
|
54
|
-
|
43
|
+
def inflector
|
44
|
+
application.inflector
|
45
|
+
end
|
46
|
+
|
47
|
+
def prepare(provider_name = nil)
|
48
|
+
container.prepare(provider_name) and return self if provider_name
|
49
|
+
|
50
|
+
return self if prepared?
|
51
|
+
|
52
|
+
ensure_slice_name
|
53
|
+
ensure_slice_consts
|
55
54
|
|
56
|
-
|
57
|
-
raise "Cannot import after booting" if booted?
|
55
|
+
prepare_all
|
58
56
|
|
59
|
-
|
60
|
-
|
57
|
+
@prepared = true
|
58
|
+
self
|
61
59
|
end
|
62
|
-
end
|
63
60
|
|
64
|
-
|
65
|
-
|
66
|
-
|
61
|
+
def prepare_container(&block)
|
62
|
+
@prepare_container_block = block
|
63
|
+
end
|
67
64
|
|
68
|
-
|
69
|
-
|
70
|
-
end
|
65
|
+
def boot
|
66
|
+
return self if booted?
|
71
67
|
|
72
|
-
|
73
|
-
container.init(*args)
|
74
|
-
end
|
68
|
+
container.finalize!
|
75
69
|
|
76
|
-
|
77
|
-
container.start(*args)
|
78
|
-
end
|
70
|
+
@booted = true
|
79
71
|
|
80
|
-
|
81
|
-
|
82
|
-
end
|
72
|
+
self
|
73
|
+
end
|
83
74
|
|
84
|
-
|
85
|
-
|
86
|
-
|
75
|
+
def shutdown
|
76
|
+
container.shutdown!
|
77
|
+
self
|
78
|
+
end
|
87
79
|
|
88
|
-
|
89
|
-
|
90
|
-
|
80
|
+
def prepared?
|
81
|
+
!!@prepared
|
82
|
+
end
|
91
83
|
|
92
|
-
|
93
|
-
|
94
|
-
|
84
|
+
def booted?
|
85
|
+
!!@booted
|
86
|
+
end
|
95
87
|
|
96
|
-
|
88
|
+
def register(...)
|
89
|
+
container.register(...)
|
90
|
+
end
|
97
91
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
container.use :env
|
92
|
+
def register_provider(...)
|
93
|
+
container.register_provider(...)
|
94
|
+
end
|
102
95
|
|
103
|
-
|
104
|
-
|
105
|
-
|
96
|
+
def start(...)
|
97
|
+
container.start(...)
|
98
|
+
end
|
106
99
|
|
107
|
-
|
108
|
-
|
100
|
+
def key?(...)
|
101
|
+
container.key?(...)
|
102
|
+
end
|
109
103
|
|
110
|
-
|
111
|
-
|
112
|
-
|
104
|
+
def keys
|
105
|
+
container.keys
|
106
|
+
end
|
113
107
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
# Expect component files in the root of the lib
|
118
|
-
# component dir to define classes inside the slice's namespace.
|
119
|
-
#
|
120
|
-
# e.g. "lib/foo.rb" should define SliceNamespace::Foo, and will be
|
121
|
-
# registered as "foo"
|
122
|
-
component_dir.namespaces.root(key: nil, const: namespace_path)
|
108
|
+
def [](...)
|
109
|
+
container.[](...)
|
110
|
+
end
|
123
111
|
|
124
|
-
|
125
|
-
|
112
|
+
def resolve(...)
|
113
|
+
container.resolve(...)
|
114
|
+
end
|
115
|
+
|
116
|
+
def export(keys)
|
117
|
+
container.config.exports = keys
|
118
|
+
end
|
119
|
+
|
120
|
+
def import(from:, **kwargs)
|
121
|
+
# TODO: This should be handled via dry-system (see dry-rb/dry-system#228)
|
122
|
+
raise "Cannot import after booting" if booted?
|
123
|
+
|
124
|
+
application = self.application
|
125
|
+
|
126
|
+
container.after(:configure) do
|
127
|
+
if from.is_a?(Symbol) || from.is_a?(String)
|
128
|
+
slice_name = from
|
129
|
+
from = application.slices[from.to_sym].container
|
126
130
|
end
|
127
131
|
|
128
|
-
|
129
|
-
|
130
|
-
|
132
|
+
as = kwargs[:as] || slice_name
|
133
|
+
|
134
|
+
import(from: from, as: as, **kwargs)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
private
|
139
|
+
|
140
|
+
def ensure_slice_name
|
141
|
+
unless name
|
142
|
+
raise SliceLoadError, "Slice must have a class name before it can be prepared"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def ensure_slice_consts
|
147
|
+
if namespace.const_defined?(:Container) || namespace.const_defined?(:Deps)
|
148
|
+
raise(
|
149
|
+
SliceLoadError,
|
150
|
+
"#{namespace}::Container and #{namespace}::Deps constants must not already be defined"
|
151
|
+
)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def prepare_all
|
156
|
+
prepare_container_plugins
|
157
|
+
prepare_container_base_config
|
158
|
+
prepare_container_component_dirs
|
159
|
+
prepare_autoloader
|
160
|
+
prepare_container_imports
|
161
|
+
prepare_container_consts
|
162
|
+
instance_exec(container, &@prepare_container_block) if @prepare_container_block
|
163
|
+
container.configured!
|
164
|
+
end
|
165
|
+
|
166
|
+
def prepare_container_plugins
|
167
|
+
container.use(:env, inferrer: -> { Hanami.env })
|
168
|
+
|
169
|
+
container.use(
|
170
|
+
:zeitwerk,
|
171
|
+
loader: application.autoloader,
|
172
|
+
run_setup: false,
|
173
|
+
eager_load: false
|
174
|
+
)
|
175
|
+
end
|
176
|
+
|
177
|
+
def prepare_container_base_config
|
178
|
+
container.config.name = slice_name
|
179
|
+
container.config.root = root
|
180
|
+
container.config.provider_dirs = [File.join("config", "providers")]
|
181
|
+
|
182
|
+
container.config.env = application.configuration.env
|
183
|
+
container.config.inflector = application.configuration.inflector
|
184
|
+
end
|
185
|
+
|
186
|
+
def prepare_container_component_dirs # rubocop:disable Metrics/AbcSize
|
187
|
+
return unless root&.directory?
|
188
|
+
|
189
|
+
# Add component dirs for each configured component path
|
190
|
+
application.configuration.source_dirs.component_dirs.each do |component_dir|
|
191
|
+
next unless root.join(component_dir.path).directory?
|
192
|
+
|
193
|
+
component_dir = component_dir.dup
|
194
|
+
|
195
|
+
if component_dir.path == LIB_DIR
|
196
|
+
# Expect component files in the root of the lib/ component dir to define
|
197
|
+
# classes inside the slice's namespace.
|
198
|
+
#
|
199
|
+
# e.g. "lib/foo.rb" should define SliceNamespace::Foo, to be registered as
|
200
|
+
# "foo"
|
201
|
+
component_dir.namespaces.delete_root
|
202
|
+
component_dir.namespaces.add_root(key: nil, const: namespace_path)
|
203
|
+
else
|
204
|
+
# Expect component files in the root of non-lib/ component dirs to define
|
205
|
+
# classes inside a namespace matching that dir.
|
206
|
+
#
|
207
|
+
# e.g. "actions/foo.rb" should define SliceNamespace::Actions::Foo, to be
|
208
|
+
# registered as "actions.foo"
|
209
|
+
|
210
|
+
dir_namespace_path = File.join(namespace_path, component_dir.path)
|
211
|
+
|
212
|
+
component_dir.namespaces.delete_root
|
213
|
+
component_dir.namespaces.add_root(const: dir_namespace_path, key: component_dir.path)
|
214
|
+
end
|
131
215
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
#
|
136
|
-
# e.g. "actions/foo.rb" should define SliceNamespace::Actions::Foo, and
|
137
|
-
# will be registered as "actions.foo"
|
216
|
+
container.config.component_dirs.add(component_dir)
|
217
|
+
end
|
218
|
+
end
|
138
219
|
|
139
|
-
|
220
|
+
def prepare_autoloader # rubocop:disable Metrics/AbcSize
|
221
|
+
return unless root&.directory?
|
140
222
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
namespace.const_set(inflector.camelize(slice_dir), Module.new)
|
145
|
-
end
|
223
|
+
# Pass configured autoload dirs to the autoloader
|
224
|
+
application.configuration.source_dirs.autoload_paths.each do |autoload_path|
|
225
|
+
next unless root.join(autoload_path).directory?
|
146
226
|
|
147
|
-
|
227
|
+
dir_namespace_path = File.join(namespace_path, autoload_path)
|
148
228
|
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
end
|
229
|
+
autoloader_namespace = begin
|
230
|
+
inflector.constantize(inflector.camelize(dir_namespace_path))
|
231
|
+
rescue NameError
|
232
|
+
namespace.const_set(inflector.camelize(autoload_path), Module.new)
|
154
233
|
end
|
234
|
+
|
235
|
+
container.config.autoloader.push_dir(
|
236
|
+
container.root.join(autoload_path),
|
237
|
+
namespace: autoloader_namespace
|
238
|
+
)
|
155
239
|
end
|
156
240
|
end
|
157
241
|
|
158
|
-
|
242
|
+
def prepare_container_imports
|
243
|
+
container.import from: application.container, as: :application
|
244
|
+
end
|
245
|
+
|
246
|
+
def prepare_container_consts
|
159
247
|
namespace.const_set :Container, container
|
160
248
|
namespace.const_set :Deps, container.injector
|
161
249
|
end
|
162
|
-
|
163
|
-
container
|
164
250
|
end
|
165
|
-
# rubocop:enable Metrics/
|
251
|
+
# rubocop:enable Metrics/ModuleLength
|
166
252
|
end
|
167
253
|
end
|
data/lib/hanami/version.rb
CHANGED
@@ -1,19 +1,32 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "json"
|
4
|
-
require "rack/request"
|
5
|
-
require "hanami/utils/hash"
|
6
|
-
|
7
3
|
module Hanami
|
8
4
|
module Web
|
9
5
|
# Rack logger for Hanami applications
|
10
6
|
class RackLogger
|
11
|
-
|
12
|
-
|
7
|
+
REQUEST_METHOD = "REQUEST_METHOD"
|
8
|
+
private_constant :REQUEST_METHOD
|
9
|
+
|
10
|
+
HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR"
|
11
|
+
private_constant :HTTP_X_FORWARDED_FOR
|
12
|
+
|
13
|
+
REMOTE_ADDR = "REMOTE_ADDR"
|
14
|
+
private_constant :REMOTE_ADDR
|
15
|
+
|
16
|
+
SCRIPT_NAME = "SCRIPT_NAME"
|
17
|
+
private_constant :SCRIPT_NAME
|
18
|
+
|
19
|
+
PATH_INFO = "PATH_INFO"
|
20
|
+
private_constant :PATH_INFO
|
21
|
+
|
22
|
+
ROUTER_PARAMS = "router.params"
|
23
|
+
private_constant :ROUTER_PARAMS
|
24
|
+
|
25
|
+
CONTENT_LENGTH = "Content-Length"
|
26
|
+
private_constant :CONTENT_LENGTH
|
13
27
|
|
14
|
-
def initialize(logger
|
28
|
+
def initialize(logger)
|
15
29
|
@logger = logger
|
16
|
-
@filter_params = filter_params
|
17
30
|
end
|
18
31
|
|
19
32
|
def attach(rack_monitor)
|
@@ -26,22 +39,20 @@ module Hanami
|
|
26
39
|
end
|
27
40
|
end
|
28
41
|
|
29
|
-
|
30
|
-
def log_request(env, status, time)
|
42
|
+
def log_request(env, status, elapsed)
|
31
43
|
data = {
|
32
|
-
http: env[HTTP_VERSION],
|
33
44
|
verb: env[REQUEST_METHOD],
|
34
45
|
status: status,
|
46
|
+
elapsed: "#{elapsed}ms",
|
35
47
|
ip: env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR],
|
36
48
|
path: env[SCRIPT_NAME] + env[PATH_INFO].to_s,
|
37
49
|
length: extract_content_length(env),
|
38
|
-
params:
|
39
|
-
|
50
|
+
params: env[ROUTER_PARAMS],
|
51
|
+
time: Time.now,
|
40
52
|
}
|
41
53
|
|
42
|
-
logger.info
|
54
|
+
logger.info(data)
|
43
55
|
end
|
44
|
-
# rubocop:enable Metrics/MethodLength
|
45
56
|
|
46
57
|
def log_exception(exception)
|
47
58
|
logger.error exception.message
|
@@ -50,47 +61,12 @@ module Hanami
|
|
50
61
|
|
51
62
|
private
|
52
63
|
|
53
|
-
|
54
|
-
REQUEST_METHOD = "REQUEST_METHOD"
|
55
|
-
HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR"
|
56
|
-
REMOTE_ADDR = "REMOTE_ADDR"
|
57
|
-
SCRIPT_NAME = "SCRIPT_NAME"
|
58
|
-
PATH_INFO = "PATH_INFO"
|
59
|
-
RACK_ERRORS = "rack.errors"
|
60
|
-
QUERY_HASH = "rack.request.query_hash"
|
61
|
-
FORM_HASH = "rack.request.form_hash"
|
62
|
-
ROUTER_PARAMS = "router.params"
|
63
|
-
CONTENT_LENGTH = "Content-Length"
|
64
|
+
attr_reader :logger
|
64
65
|
|
65
66
|
def extract_content_length(env)
|
66
67
|
value = env[CONTENT_LENGTH]
|
67
68
|
!value || value.to_s == "0" ? "-" : value
|
68
69
|
end
|
69
|
-
|
70
|
-
def extract_params(env)
|
71
|
-
result = env.fetch(QUERY_HASH, {})
|
72
|
-
result.merge!(env.fetch(FORM_HASH, {}))
|
73
|
-
result.merge!(Hanami::Utils::Hash.deep_stringify(env.fetch(ROUTER_PARAMS, {})))
|
74
|
-
result
|
75
|
-
end
|
76
|
-
|
77
|
-
FILTERED = "[FILTERED]"
|
78
|
-
|
79
|
-
# rubocop:disable Metrics/MethodLength
|
80
|
-
def filter(params)
|
81
|
-
params.each_with_object({}) do |(k, v), h|
|
82
|
-
if filter_params.include?(k)
|
83
|
-
h.update(k => FILTERED)
|
84
|
-
elsif v.is_a?(Hash)
|
85
|
-
h.update(k => filter(v))
|
86
|
-
elsif v.is_a?(Array)
|
87
|
-
h.update(k => v.map { |m| m.is_a?(Hash) ? filter(m) : m })
|
88
|
-
else
|
89
|
-
h[k] = v
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
# rubocop:enable Metrics/MethodLength
|
94
70
|
end
|
95
71
|
end
|
96
72
|
end
|