hanami 1.3.1 → 2.0.0.alpha2

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.
Files changed (168) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +110 -6
  3. data/FEATURES.md +9 -1
  4. data/LICENSE.md +1 -1
  5. data/README.md +4 -5
  6. data/hanami.gemspec +26 -30
  7. data/lib/hanami.rb +40 -243
  8. data/lib/hanami/application.rb +338 -174
  9. data/lib/hanami/application/autoloader/inflector_adapter.rb +22 -0
  10. data/lib/hanami/application/container/boot/inflector.rb +7 -0
  11. data/lib/hanami/application/container/boot/logger.rb +8 -0
  12. data/lib/hanami/application/container/boot/rack_logger.rb +19 -0
  13. data/lib/hanami/application/container/boot/rack_monitor.rb +12 -0
  14. data/lib/hanami/application/container/boot/settings.rb +7 -0
  15. data/lib/hanami/application/router.rb +59 -0
  16. data/lib/hanami/application/routing/middleware/stack.rb +89 -0
  17. data/lib/hanami/application/routing/resolver.rb +82 -0
  18. data/lib/hanami/application/routing/resolver/node.rb +50 -0
  19. data/lib/hanami/application/routing/resolver/trie.rb +59 -0
  20. data/lib/hanami/application/settings.rb +23 -0
  21. data/lib/hanami/application/settings/definition.rb +26 -0
  22. data/lib/hanami/application/settings/loader.rb +97 -0
  23. data/lib/hanami/application/settings/struct.rb +65 -0
  24. data/lib/hanami/boot.rb +5 -0
  25. data/lib/hanami/cli/application/cli.rb +40 -0
  26. data/lib/hanami/cli/application/command.rb +47 -0
  27. data/lib/hanami/cli/application/commands.rb +16 -0
  28. data/lib/hanami/cli/application/commands/console.rb +81 -0
  29. data/lib/hanami/cli/base_command.rb +48 -0
  30. data/lib/hanami/cli/commands.rb +6 -42
  31. data/lib/hanami/cli/commands/command.rb +20 -30
  32. data/lib/hanami/cli/commands/server.rb +63 -14
  33. data/lib/hanami/configuration.rb +248 -190
  34. data/lib/hanami/configuration/middleware.rb +8 -28
  35. data/lib/hanami/configuration/router.rb +50 -0
  36. data/lib/hanami/configuration/sessions.rb +50 -0
  37. data/lib/hanami/init.rb +5 -0
  38. data/lib/hanami/server.rb +5 -69
  39. data/lib/hanami/setup.rb +8 -2
  40. data/lib/hanami/slice.rb +138 -0
  41. data/lib/hanami/version.rb +3 -1
  42. data/lib/hanami/web/rack_logger.rb +96 -0
  43. metadata +84 -228
  44. data/bin/hanami +0 -6
  45. data/lib/hanami/action/csrf_protection.rb +0 -211
  46. data/lib/hanami/action/routing_helpers.rb +0 -40
  47. data/lib/hanami/app.rb +0 -96
  48. data/lib/hanami/application_configuration.rb +0 -1495
  49. data/lib/hanami/application_name.rb +0 -108
  50. data/lib/hanami/application_namespace.rb +0 -14
  51. data/lib/hanami/assets/asset.rb +0 -72
  52. data/lib/hanami/assets/static.rb +0 -102
  53. data/lib/hanami/cli/commands/assets.rb +0 -16
  54. data/lib/hanami/cli/commands/assets/precompile.rb +0 -42
  55. data/lib/hanami/cli/commands/console.rb +0 -95
  56. data/lib/hanami/cli/commands/db.rb +0 -32
  57. data/lib/hanami/cli/commands/db/apply.rb +0 -32
  58. data/lib/hanami/cli/commands/db/console.rb +0 -44
  59. data/lib/hanami/cli/commands/db/create.rb +0 -32
  60. data/lib/hanami/cli/commands/db/drop.rb +0 -32
  61. data/lib/hanami/cli/commands/db/migrate.rb +0 -39
  62. data/lib/hanami/cli/commands/db/prepare.rb +0 -32
  63. data/lib/hanami/cli/commands/db/rollback.rb +0 -59
  64. data/lib/hanami/cli/commands/db/version.rb +0 -32
  65. data/lib/hanami/cli/commands/destroy.rb +0 -26
  66. data/lib/hanami/cli/commands/destroy/action.rb +0 -137
  67. data/lib/hanami/cli/commands/destroy/app.rb +0 -159
  68. data/lib/hanami/cli/commands/destroy/mailer.rb +0 -74
  69. data/lib/hanami/cli/commands/destroy/migration.rb +0 -51
  70. data/lib/hanami/cli/commands/destroy/model.rb +0 -84
  71. data/lib/hanami/cli/commands/generate.rb +0 -28
  72. data/lib/hanami/cli/commands/generate/action.rb +0 -321
  73. data/lib/hanami/cli/commands/generate/action/action.erb +0 -7
  74. data/lib/hanami/cli/commands/generate/action/action_spec.minitest.erb +0 -11
  75. data/lib/hanami/cli/commands/generate/action/action_spec.rspec.erb +0 -9
  76. data/lib/hanami/cli/commands/generate/action/action_without_view.erb +0 -7
  77. data/lib/hanami/cli/commands/generate/action/view.erb +0 -7
  78. data/lib/hanami/cli/commands/generate/action/view_spec.minitest.erb +0 -12
  79. data/lib/hanami/cli/commands/generate/action/view_spec.rspec.erb +0 -10
  80. data/lib/hanami/cli/commands/generate/app.rb +0 -243
  81. data/lib/hanami/cli/commands/generate/app/application.erb +0 -313
  82. data/lib/hanami/cli/commands/generate/app/favicon.ico +0 -0
  83. data/lib/hanami/cli/commands/generate/app/gitkeep.erb +0 -0
  84. data/lib/hanami/cli/commands/generate/app/layout.erb +0 -7
  85. data/lib/hanami/cli/commands/generate/app/layout_spec.minitest.erb +0 -10
  86. data/lib/hanami/cli/commands/generate/app/layout_spec.rspec.erb +0 -10
  87. data/lib/hanami/cli/commands/generate/app/routes.erb +0 -5
  88. data/lib/hanami/cli/commands/generate/app/template.erb.erb +0 -10
  89. data/lib/hanami/cli/commands/generate/app/template.haml.erb +0 -7
  90. data/lib/hanami/cli/commands/generate/app/template.slim.erb +0 -8
  91. data/lib/hanami/cli/commands/generate/mailer.rb +0 -104
  92. data/lib/hanami/cli/commands/generate/mailer/mailer.erb +0 -9
  93. data/lib/hanami/cli/commands/generate/mailer/mailer_spec.minitest.erb +0 -7
  94. data/lib/hanami/cli/commands/generate/mailer/mailer_spec.rspec.erb +0 -5
  95. data/lib/hanami/cli/commands/generate/migration.rb +0 -41
  96. data/lib/hanami/cli/commands/generate/migration/migration.erb +0 -4
  97. data/lib/hanami/cli/commands/generate/model.rb +0 -125
  98. data/lib/hanami/cli/commands/generate/model/entity.erb +0 -2
  99. data/lib/hanami/cli/commands/generate/model/entity_spec.minitest.erb +0 -5
  100. data/lib/hanami/cli/commands/generate/model/entity_spec.rspec.erb +0 -3
  101. data/lib/hanami/cli/commands/generate/model/migration.erb +0 -10
  102. data/lib/hanami/cli/commands/generate/model/repository.erb +0 -5
  103. data/lib/hanami/cli/commands/generate/model/repository_spec.minitest.erb +0 -5
  104. data/lib/hanami/cli/commands/generate/model/repository_spec.rspec.erb +0 -3
  105. data/lib/hanami/cli/commands/generate/secret.rb +0 -48
  106. data/lib/hanami/cli/commands/new.rb +0 -578
  107. data/lib/hanami/cli/commands/new/.env.development.erb +0 -3
  108. data/lib/hanami/cli/commands/new/.env.test.erb +0 -3
  109. data/lib/hanami/cli/commands/new/.gitkeep.erb +0 -0
  110. data/lib/hanami/cli/commands/new/Gemfile.erb +0 -58
  111. data/lib/hanami/cli/commands/new/README.md.erb +0 -33
  112. data/lib/hanami/cli/commands/new/config.ru.erb +0 -3
  113. data/lib/hanami/cli/commands/new/config/boot.erb +0 -2
  114. data/lib/hanami/cli/commands/new/config/environment.erb +0 -49
  115. data/lib/hanami/cli/commands/new/gitignore.erb +0 -2
  116. data/lib/hanami/cli/commands/new/gitignore_with_sqlite.erb +0 -3
  117. data/lib/hanami/cli/commands/new/hanamirc.erb +0 -3
  118. data/lib/hanami/cli/commands/new/lib/project.erb +0 -2
  119. data/lib/hanami/cli/commands/new/minitest/Rakefile.erb +0 -12
  120. data/lib/hanami/cli/commands/new/minitest/features_helper.erb +0 -11
  121. data/lib/hanami/cli/commands/new/minitest/spec_helper.erb +0 -7
  122. data/lib/hanami/cli/commands/new/rspec/Rakefile.erb +0 -9
  123. data/lib/hanami/cli/commands/new/rspec/capybara.erb +0 -8
  124. data/lib/hanami/cli/commands/new/rspec/features_helper.erb +0 -12
  125. data/lib/hanami/cli/commands/new/rspec/rspec.erb +0 -2
  126. data/lib/hanami/cli/commands/new/rspec/spec_helper.erb +0 -103
  127. data/lib/hanami/cli/commands/new/schema.sql.erb +0 -0
  128. data/lib/hanami/cli/commands/project.rb +0 -421
  129. data/lib/hanami/cli/commands/routes.rb +0 -21
  130. data/lib/hanami/cli/commands/templates.rb +0 -31
  131. data/lib/hanami/cli/commands/version.rb +0 -19
  132. data/lib/hanami/common_logger.rb +0 -93
  133. data/lib/hanami/components.rb +0 -156
  134. data/lib/hanami/components/app/assets.rb +0 -59
  135. data/lib/hanami/components/app/controller.rb +0 -74
  136. data/lib/hanami/components/app/routes.rb +0 -59
  137. data/lib/hanami/components/app/view.rb +0 -44
  138. data/lib/hanami/components/component.rb +0 -182
  139. data/lib/hanami/components/components.rb +0 -479
  140. data/lib/hanami/components/routes_inspector.rb +0 -72
  141. data/lib/hanami/config/cookies.rb +0 -69
  142. data/lib/hanami/config/framework_configuration.rb +0 -43
  143. data/lib/hanami/config/load_paths.rb +0 -46
  144. data/lib/hanami/config/mapper.rb +0 -47
  145. data/lib/hanami/config/routes.rb +0 -20
  146. data/lib/hanami/config/security.rb +0 -110
  147. data/lib/hanami/config/sessions.rb +0 -103
  148. data/lib/hanami/configuration/app.rb +0 -18
  149. data/lib/hanami/early_hints.rb +0 -129
  150. data/lib/hanami/env.rb +0 -69
  151. data/lib/hanami/environment.rb +0 -513
  152. data/lib/hanami/environment_application_configurations.rb +0 -37
  153. data/lib/hanami/frameworks.rb +0 -22
  154. data/lib/hanami/hanamirc.rb +0 -169
  155. data/lib/hanami/mailer/glue.rb +0 -27
  156. data/lib/hanami/middleware_stack.rb +0 -172
  157. data/lib/hanami/rake_helper.rb +0 -78
  158. data/lib/hanami/rake_tasks.rb +0 -2
  159. data/lib/hanami/rendering_policy.rb +0 -95
  160. data/lib/hanami/routes.rb +0 -219
  161. data/lib/hanami/routing/default.rb +0 -32
  162. data/lib/hanami/static.rb +0 -63
  163. data/lib/hanami/templates/default.html.erb +0 -30
  164. data/lib/hanami/templates/welcome.html.erb +0 -52
  165. data/lib/hanami/views/default.rb +0 -37
  166. data/lib/hanami/views/default_template_finder.rb +0 -22
  167. data/lib/hanami/views/null_view.rb +0 -15
  168. data/lib/hanami/welcome.rb +0 -36
@@ -1,40 +1,20 @@
1
- require "concurrent"
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Hanami
4
- # @api private
5
4
  class Configuration
6
- # Middleware configuration
7
- # @since 1.2.0
5
+ # Hanami application configured Rack middleware
6
+ #
7
+ # @since 2.0.0
8
8
  class Middleware
9
- # @api private
10
- # @since 1.2.0
11
9
  def initialize
12
- @middleware = Concurrent::Array.new
10
+ @stack = []
13
11
  end
14
12
 
15
- # Use a Rack middleware
16
- #
17
- # @param middleware [#call] a Rack middleware
18
- # @param args [Array<Object>] an optional set of options
19
- # @param blk [Proc] an optional block to pass to the middleware
20
- #
21
- # @since 1.2.0
22
- #
23
- # @example
24
- # # config/environment.rb
25
- # # ...
26
- # Hanami.configure do
27
- # middleware.use MyRackMiddleware
28
- # end
29
- def use(middleware, *args, &blk)
30
- @middleware.push([middleware, args, blk])
13
+ def use(middleware, *args, &block)
14
+ stack.push([middleware, *args, block].compact)
31
15
  end
32
16
 
33
- # @api private
34
- # @since 1.2.0
35
- def each(&blk)
36
- @middleware.each(&blk)
37
- end
17
+ attr_reader :stack
38
18
  end
39
19
  end
40
20
  end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hanami
4
+ class Configuration
5
+ # Hanami router configuration
6
+ #
7
+ # @since 2.0.0
8
+ # @api private
9
+ class Router
10
+ # @api private
11
+ # @since 2.0.0
12
+ attr_writer :routes
13
+
14
+ # @api private
15
+ # @since 2.0.0
16
+ attr_reader :routes
17
+
18
+ # @api private
19
+ # @since 2.0.0
20
+ attr_writer :resolver
21
+
22
+ # @api private
23
+ # @since 2.0.0
24
+ def initialize(base_url, routes: DEFAULT_ROUTES)
25
+ @base_url = base_url
26
+ @routes = routes
27
+ end
28
+
29
+ # @api private
30
+ # @since 2.0.0
31
+ def resolver
32
+ @resolver ||= begin
33
+ require_relative "../application/routing/resolver"
34
+ Application::Routing::Resolver
35
+ end
36
+ end
37
+
38
+ # @api private
39
+ # @since 2.0.0
40
+ def options
41
+ { base_url: @base_url }
42
+ end
43
+
44
+ # @api private
45
+ # @since 2.0.0
46
+ DEFAULT_ROUTES = File.join("config", "routes")
47
+ private_constant :DEFAULT_ROUTES
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami/utils/string"
4
+ require "hanami/utils/class"
5
+
6
+ module Hanami
7
+ class Configuration
8
+ # Hanami configuration for HTTP sessions
9
+ #
10
+ # @since 2.0.0
11
+ class Sessions
12
+ def self.null
13
+ NULL_STORAGE
14
+ end
15
+
16
+ attr_reader :storage, :options
17
+
18
+ def initialize(*args)
19
+ storage, options, = Array(args.dup).flatten
20
+
21
+ @storage = storage
22
+ @options = options || {}
23
+ end
24
+
25
+ def enabled?
26
+ storage != NULL_STORAGE
27
+ end
28
+
29
+ def middleware
30
+ [[storage_middleware, options]]
31
+ end
32
+
33
+ private
34
+
35
+ NULL_STORAGE = :null
36
+ private_constant :NULL_STORAGE
37
+
38
+ def storage_middleware
39
+ require_storage
40
+
41
+ name = Utils::String.classify(storage)
42
+ Utils::Class.load!(name, Rack::Session)
43
+ end
44
+
45
+ def require_storage
46
+ require "rack/session/#{storage}"
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "setup"
4
+
5
+ Hanami.init
data/lib/hanami/server.rb CHANGED
@@ -1,4 +1,7 @@
1
- require 'rack'
1
+ # frozen_string_literal: true
2
+
3
+ require "hanami"
4
+ require "rack"
2
5
 
3
6
  module Hanami
4
7
  # Rack compatible server.
@@ -13,81 +16,14 @@ module Hanami
13
16
  # @since 0.8.0
14
17
  # @api private
15
18
  class Server < ::Rack::Server
16
- # @api private
17
- attr_reader :options
18
-
19
- # @since 0.8.0
20
- # @api private
21
- #
22
- # @see Hanami::Environment#initialize
23
- def initialize
24
- @options = _extract_options
25
- setup
26
- end
27
-
28
19
  # Primarily this removes the ::Rack::Chunked middleware
29
20
  # which is the cause of Safari content-length bugs.
30
21
  #
31
22
  # @since 0.8.0
32
23
  def middleware
33
- mw = Hash.new { |e, m| e[m] = [] }
24
+ mw = ::Hash.new { |e, m| e[m] = [] }
34
25
  mw["development"].concat([::Rack::ShowExceptions, ::Rack::Lint])
35
- require 'hanami/assets/static'
36
- mw["development"].push(::Hanami::Assets::Static)
37
26
  mw
38
27
  end
39
-
40
- # @api private
41
- def start
42
- preload
43
- super
44
- end
45
-
46
- private
47
-
48
- # @api private
49
- def setup
50
- return unless code_reloading?
51
- @app = Shotgun::Loader.new(rackup)
52
- end
53
-
54
- # @api private
55
- def environment
56
- Components['environment']
57
- end
58
-
59
- # @since 0.8.0
60
- # @api private
61
- def code_reloading?
62
- Hanami.code_reloading?
63
- end
64
-
65
- # @api private
66
- def rackup
67
- environment.rackup.to_s
68
- end
69
-
70
- # @api private
71
- def preload
72
- if code_reloading?
73
- Shotgun.enable_copy_on_write
74
- Shotgun.preload
75
- else
76
- Hanami.boot
77
- end
78
- end
79
-
80
- # Options for Rack::Server superclass
81
- #
82
- # @since 0.8.0
83
- # @api private
84
- def _extract_options
85
- environment.to_options.merge(
86
- config: rackup,
87
- Host: environment.host,
88
- Port: environment.port,
89
- AccessLog: []
90
- )
91
- end
92
28
  end
93
29
  end
data/lib/hanami/setup.rb CHANGED
@@ -1,3 +1,9 @@
1
- require 'hanami'
1
+ # frozen_string_literal: true
2
2
 
3
- Bundler.require(*Hanami::Environment.new.bundler_groups)
3
+ require "bundler/setup"
4
+ require "hanami"
5
+
6
+ begin
7
+ require File.join(Dir.pwd, "config/application")
8
+ rescue LoadError # rubocop:disable Lint/SuppressedException
9
+ end
@@ -0,0 +1,138 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "dry/system/container"
4
+ require "pathname"
5
+
6
+ module Hanami
7
+ # Distinct area of concern within an Hanami application
8
+ #
9
+ # @since 2.0.0
10
+ class Slice
11
+ attr_reader :application, :name, :namespace, :root
12
+
13
+ def initialize(application, name:, namespace: nil, root: nil, container: nil)
14
+ @application = application
15
+ @name = name.to_sym
16
+ @namespace = namespace
17
+ @root = root ? Pathname(root) : root
18
+ @container = container || define_container
19
+ end
20
+
21
+ def inflector
22
+ application.inflector
23
+ end
24
+
25
+ def namespace_path
26
+ @namespace_path ||= inflector.underscore(namespace.to_s)
27
+ end
28
+
29
+ def init
30
+ container.import application: application.container
31
+
32
+ slice_block = application.configuration.slices[name]
33
+ instance_eval(&slice_block) if slice_block
34
+ end
35
+
36
+ def boot
37
+ container.finalize! do
38
+ container.config.env = application.container.config.env
39
+ end
40
+
41
+ @booted = true
42
+ self
43
+ end
44
+
45
+ # rubocop:disable Style/DoubleNegation
46
+ def booted?
47
+ !!@booted
48
+ end
49
+ # rubocop:enable Style/DoubleNegation
50
+
51
+ def container
52
+ @container ||= define_container
53
+ end
54
+
55
+ def import(*slice_names)
56
+ raise "Cannot import after booting" if booted?
57
+
58
+ slice_names.each do |slice_name|
59
+ container.import slice_name.to_sym => application.slices.fetch(slice_name.to_sym).container
60
+ end
61
+ end
62
+
63
+ def register(*args, &block)
64
+ container.register(*args, &block)
65
+ end
66
+
67
+ def register_bootable(*args, &block)
68
+ container.boot(*args, &block)
69
+ end
70
+
71
+ def init_bootable(*args)
72
+ container.init(*args)
73
+ end
74
+
75
+ def start_bootable(*args)
76
+ container.start(*args)
77
+ end
78
+
79
+ def key?(*args)
80
+ container.key?(*args)
81
+ end
82
+
83
+ def keys
84
+ container.keys
85
+ end
86
+
87
+ def [](*args)
88
+ container[*args]
89
+ end
90
+
91
+ def resolve(*args)
92
+ container.resolve(*args)
93
+ end
94
+
95
+ private
96
+
97
+ # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
98
+ def define_container
99
+ container = Class.new(Dry::System::Container)
100
+ container.use :env
101
+
102
+ container.configure do |config|
103
+ config.name = name
104
+ config.inflector = application.configuration.inflector
105
+
106
+ if application.configuration.autoloader
107
+ require "dry/system/loader/autoloading"
108
+ config.component_dirs.loader = Dry::System::Loader::Autoloading
109
+ config.component_dirs.add_to_load_path = false
110
+ end
111
+
112
+ if root&.directory?
113
+ config.root = root
114
+ config.bootable_dirs = ["config/boot"]
115
+
116
+ if root.join("lib").directory?
117
+ config.component_dirs.add "lib" do |dir|
118
+ dir.default_namespace = namespace_path.tr(File::SEPARATOR, config.namespace_separator)
119
+ end
120
+
121
+ application.configuration.autoloader&.push_dir(root.join("lib"))
122
+ end
123
+ end
124
+ end
125
+
126
+ # Force after configure hook to run
127
+ container.configure do; end
128
+
129
+ if namespace
130
+ namespace.const_set :Container, container
131
+ namespace.const_set :Deps, container.injector
132
+ end
133
+
134
+ container
135
+ end
136
+ # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
137
+ end
138
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Hanami
2
4
  # Hanami version
3
5
  #
@@ -6,7 +8,7 @@ module Hanami
6
8
  module Version
7
9
  # @since 0.9.0
8
10
  # @api private
9
- VERSION = '1.3.1'.freeze
11
+ VERSION = "2.0.0.alpha2"
10
12
 
11
13
  # @since 0.9.0
12
14
  # @api private
@@ -0,0 +1,96 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "json"
4
+ require "rack/request"
5
+ require "hanami/utils/hash"
6
+
7
+ module Hanami
8
+ module Web
9
+ # Rack logger for Hanami applications
10
+ class RackLogger
11
+ attr_reader :logger
12
+ attr_reader :filter_params
13
+
14
+ def initialize(logger, filter_params: [])
15
+ @logger = logger
16
+ @filter_params = filter_params
17
+ end
18
+
19
+ def attach(rack_monitor)
20
+ rack_monitor.on :stop do |event|
21
+ log_request event[:env], event[:status], event[:time]
22
+ end
23
+
24
+ rack_monitor.on :error do |event|
25
+ log_exception event[:exception]
26
+ end
27
+ end
28
+
29
+ # rubocop:disable Metrics/MethodLength
30
+ def log_request(env, status, time)
31
+ data = {
32
+ http: env[HTTP_VERSION],
33
+ verb: env[REQUEST_METHOD],
34
+ status: status,
35
+ ip: env[HTTP_X_FORWARDED_FOR] || env[REMOTE_ADDR],
36
+ path: env[SCRIPT_NAME] + env[PATH_INFO].to_s,
37
+ length: extract_content_length(env),
38
+ params: extract_params(env),
39
+ elapsed: time,
40
+ }
41
+
42
+ logger.info JSON.generate(data)
43
+ end
44
+ # rubocop:enable Metrics/MethodLength
45
+
46
+ def log_exception(exception)
47
+ logger.error exception.message
48
+ logger.error exception.backtrace.join("\n")
49
+ end
50
+
51
+ private
52
+
53
+ HTTP_VERSION = "HTTP_VERSION"
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
+
65
+ def extract_content_length(env)
66
+ value = env[CONTENT_LENGTH]
67
+ !value || value.to_s == "0" ? "-" : value
68
+ 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
+ end
95
+ end
96
+ end