hanami 2.0.0.alpha1 → 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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +70 -5
  3. data/FEATURES.md +9 -1
  4. data/LICENSE.md +1 -1
  5. data/README.md +4 -5
  6. data/hanami.gemspec +11 -11
  7. data/lib/hanami.rb +19 -18
  8. data/lib/hanami/application.rb +322 -26
  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 +1 -2
  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 +3 -2
  31. data/lib/hanami/cli/commands/command.rb +4 -4
  32. data/lib/hanami/configuration.rb +129 -64
  33. data/lib/hanami/configuration/middleware.rb +2 -2
  34. data/lib/hanami/configuration/router.rb +50 -0
  35. data/lib/hanami/init.rb +5 -0
  36. data/lib/hanami/setup.rb +9 -0
  37. data/lib/hanami/slice.rb +138 -0
  38. data/lib/hanami/version.rb +1 -1
  39. data/lib/hanami/web/rack_logger.rb +96 -0
  40. metadata +92 -54
  41. data/bin/hanami +0 -8
  42. data/lib/hanami/configuration/cookies.rb +0 -24
  43. data/lib/hanami/configuration/security.rb +0 -141
  44. data/lib/hanami/container.rb +0 -107
  45. data/lib/hanami/frameworks.rb +0 -28
  46. data/lib/hanami/routes.rb +0 -31
@@ -8,7 +8,7 @@ module Hanami
8
8
  module Version
9
9
  # @since 0.9.0
10
10
  # @api private
11
- VERSION = "2.0.0.alpha1"
11
+ VERSION = "2.0.0.alpha2"
12
12
 
13
13
  # @since 0.9.0
14
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
metadata CHANGED
@@ -1,125 +1,145 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hanami
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0.alpha1
4
+ version: 2.0.0.alpha2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Luca Guidi
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-30 00:00:00.000000000 Z
11
+ date: 2021-05-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: hanami-utils
14
+ name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 2.0.alpha
19
+ version: '1.16'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '3'
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
- - - "~>"
27
+ - - ">="
25
28
  - !ruby/object:Gem::Version
26
- version: 2.0.alpha
29
+ version: '1.16'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '3'
27
33
  - !ruby/object:Gem::Dependency
28
- name: hanami-router
34
+ name: dry-core
29
35
  requirement: !ruby/object:Gem::Requirement
30
36
  requirements:
31
37
  - - "~>"
32
38
  - !ruby/object:Gem::Version
33
- version: 2.0.alpha
39
+ version: '0.4'
34
40
  type: :runtime
35
41
  prerelease: false
36
42
  version_requirements: !ruby/object:Gem::Requirement
37
43
  requirements:
38
44
  - - "~>"
39
45
  - !ruby/object:Gem::Version
40
- version: 2.0.alpha
46
+ version: '0.4'
41
47
  - !ruby/object:Gem::Dependency
42
- name: hanami-controller
48
+ name: dry-inflector
43
49
  requirement: !ruby/object:Gem::Requirement
44
50
  requirements:
45
51
  - - "~>"
46
52
  - !ruby/object:Gem::Version
47
- version: 2.0.alpha
53
+ version: '0.1'
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: 0.1.2
48
57
  type: :runtime
49
58
  prerelease: false
50
59
  version_requirements: !ruby/object:Gem::Requirement
51
60
  requirements:
52
61
  - - "~>"
53
62
  - !ruby/object:Gem::Version
54
- version: 2.0.alpha
63
+ version: '0.1'
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: 0.1.2
55
67
  - !ruby/object:Gem::Dependency
56
- name: hanami-cli
68
+ name: dry-monitor
57
69
  requirement: !ruby/object:Gem::Requirement
58
70
  requirements:
59
- - - "~>"
71
+ - - ">="
60
72
  - !ruby/object:Gem::Version
61
- version: 1.0.alpha
73
+ version: '0'
62
74
  type: :runtime
63
75
  prerelease: false
64
76
  version_requirements: !ruby/object:Gem::Requirement
65
77
  requirements:
66
- - - "~>"
78
+ - - ">="
67
79
  - !ruby/object:Gem::Version
68
- version: 1.0.alpha
80
+ version: '0'
69
81
  - !ruby/object:Gem::Dependency
70
82
  name: dry-system
71
83
  requirement: !ruby/object:Gem::Requirement
72
84
  requirements:
73
85
  - - "~>"
74
86
  - !ruby/object:Gem::Version
75
- version: '0.10'
87
+ version: '0.19'
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: 0.19.0
76
91
  type: :runtime
77
92
  prerelease: false
78
93
  version_requirements: !ruby/object:Gem::Requirement
79
94
  requirements:
80
95
  - - "~>"
81
96
  - !ruby/object:Gem::Version
82
- version: '0.10'
97
+ version: '0.19'
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: 0.19.0
83
101
  - !ruby/object:Gem::Dependency
84
- name: dry-inflector
102
+ name: hanami-cli
85
103
  requirement: !ruby/object:Gem::Requirement
86
104
  requirements:
87
105
  - - "~>"
88
106
  - !ruby/object:Gem::Version
89
- version: '0.1'
90
- - - ">="
91
- - !ruby/object:Gem::Version
92
- version: 0.1.2
107
+ version: 2.0.alpha
93
108
  type: :runtime
94
109
  prerelease: false
95
110
  version_requirements: !ruby/object:Gem::Requirement
96
111
  requirements:
97
112
  - - "~>"
98
113
  - !ruby/object:Gem::Version
99
- version: '0.1'
100
- - - ">="
101
- - !ruby/object:Gem::Version
102
- version: 0.1.2
114
+ version: 2.0.alpha
103
115
  - !ruby/object:Gem::Dependency
104
- name: bundler
116
+ name: hanami-utils
105
117
  requirement: !ruby/object:Gem::Requirement
106
118
  requirements:
107
- - - ">="
108
- - !ruby/object:Gem::Version
109
- version: '1.16'
110
- - - "<"
119
+ - - "~>"
111
120
  - !ruby/object:Gem::Version
112
- version: '3'
121
+ version: 2.0.alpha
113
122
  type: :runtime
114
123
  prerelease: false
115
124
  version_requirements: !ruby/object:Gem::Requirement
116
125
  requirements:
117
- - - ">="
126
+ - - "~>"
118
127
  - !ruby/object:Gem::Version
119
- version: '1.16'
120
- - - "<"
128
+ version: 2.0.alpha
129
+ - !ruby/object:Gem::Dependency
130
+ name: zeitwerk
131
+ requirement: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - "~>"
121
134
  - !ruby/object:Gem::Version
122
- version: '3'
135
+ version: '2.4'
136
+ type: :runtime
137
+ prerelease: false
138
+ version_requirements: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - "~>"
141
+ - !ruby/object:Gem::Version
142
+ version: '2.4'
123
143
  - !ruby/object:Gem::Dependency
124
144
  name: rspec
125
145
  requirement: !ruby/object:Gem::Requirement
@@ -154,19 +174,18 @@ dependencies:
154
174
  requirements:
155
175
  - - "~>"
156
176
  - !ruby/object:Gem::Version
157
- version: '12.0'
177
+ version: '13.0'
158
178
  type: :development
159
179
  prerelease: false
160
180
  version_requirements: !ruby/object:Gem::Requirement
161
181
  requirements:
162
182
  - - "~>"
163
183
  - !ruby/object:Gem::Version
164
- version: '12.0'
184
+ version: '13.0'
165
185
  description: Hanami is a web framework for Ruby
166
186
  email:
167
187
  - me@lucaguidi.com
168
- executables:
169
- - hanami
188
+ executables: []
170
189
  extensions: []
171
190
  extra_rdoc_files: []
172
191
  files:
@@ -175,30 +194,49 @@ files:
175
194
  - FEATURES.md
176
195
  - LICENSE.md
177
196
  - README.md
178
- - bin/hanami
179
197
  - hanami.gemspec
180
198
  - lib/hanami.rb
181
199
  - lib/hanami/application.rb
200
+ - lib/hanami/application/autoloader/inflector_adapter.rb
201
+ - lib/hanami/application/container/boot/inflector.rb
202
+ - lib/hanami/application/container/boot/logger.rb
203
+ - lib/hanami/application/container/boot/rack_logger.rb
204
+ - lib/hanami/application/container/boot/rack_monitor.rb
205
+ - lib/hanami/application/container/boot/settings.rb
206
+ - lib/hanami/application/router.rb
207
+ - lib/hanami/application/routing/middleware/stack.rb
208
+ - lib/hanami/application/routing/resolver.rb
209
+ - lib/hanami/application/routing/resolver/node.rb
210
+ - lib/hanami/application/routing/resolver/trie.rb
211
+ - lib/hanami/application/settings.rb
212
+ - lib/hanami/application/settings/definition.rb
213
+ - lib/hanami/application/settings/loader.rb
214
+ - lib/hanami/application/settings/struct.rb
182
215
  - lib/hanami/boot.rb
216
+ - lib/hanami/cli/application/cli.rb
217
+ - lib/hanami/cli/application/command.rb
218
+ - lib/hanami/cli/application/commands.rb
219
+ - lib/hanami/cli/application/commands/console.rb
220
+ - lib/hanami/cli/base_command.rb
183
221
  - lib/hanami/cli/commands.rb
184
222
  - lib/hanami/cli/commands/command.rb
185
223
  - lib/hanami/cli/commands/server.rb
186
224
  - lib/hanami/configuration.rb
187
- - lib/hanami/configuration/cookies.rb
188
225
  - lib/hanami/configuration/middleware.rb
189
- - lib/hanami/configuration/security.rb
226
+ - lib/hanami/configuration/router.rb
190
227
  - lib/hanami/configuration/sessions.rb
191
- - lib/hanami/container.rb
192
- - lib/hanami/frameworks.rb
193
- - lib/hanami/routes.rb
228
+ - lib/hanami/init.rb
194
229
  - lib/hanami/server.rb
230
+ - lib/hanami/setup.rb
231
+ - lib/hanami/slice.rb
195
232
  - lib/hanami/version.rb
233
+ - lib/hanami/web/rack_logger.rb
196
234
  homepage: http://hanamirb.org
197
235
  licenses:
198
236
  - MIT
199
237
  metadata:
200
238
  allowed_push_host: https://rubygems.org
201
- post_install_message:
239
+ post_install_message:
202
240
  rdoc_options: []
203
241
  require_paths:
204
242
  - lib
@@ -206,15 +244,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
206
244
  requirements:
207
245
  - - ">="
208
246
  - !ruby/object:Gem::Version
209
- version: 2.5.0
247
+ version: 2.6.0
210
248
  required_rubygems_version: !ruby/object:Gem::Requirement
211
249
  requirements:
212
250
  - - ">"
213
251
  - !ruby/object:Gem::Version
214
252
  version: 1.3.1
215
253
  requirements: []
216
- rubygems_version: 3.0.2
217
- signing_key:
254
+ rubygems_version: 3.2.3
255
+ signing_key:
218
256
  specification_version: 4
219
257
  summary: The web, with simplicity
220
258
  test_files: []
data/bin/hanami DELETED
@@ -1,8 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require "bundler"
5
- require "hanami/cli/commands"
6
-
7
- Bundler.require(*Hanami.bundler_groups) if File.exist?(ENV["BUNDLE_GEMFILE"] || "Gemfile")
8
- Hanami::CLI.new(Hanami::CLI::Commands).call
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Hanami
4
- class Configuration
5
- # Hanami configuration for HTTP cookies
6
- #
7
- # @since 2.0.0
8
- class Cookies
9
- def self.null
10
- { null: true }
11
- end
12
-
13
- attr_reader :options
14
-
15
- def initialize(options)
16
- @options = options
17
- end
18
-
19
- def enabled?
20
- options != self.class.null
21
- end
22
- end
23
- end
24
- end
@@ -1,141 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "concurrent/hash"
4
- require "hanami/utils/string"
5
-
6
- module Hanami
7
- class Configuration
8
- # Hanami configuration security settings
9
- #
10
- # @since 2.0.0
11
- class Security
12
- def initialize
13
- @settings = Concurrent::Hash.new
14
- settings[:x_frame_options] = Setting.new(HEADER_X_FRAME_OPTIONS, DEFAULT_X_FRAME_OPTIONS)
15
- settings[:x_content_type_options] = Setting.new(HEADER_X_CONTENT_TYPE_OPTIONS, DEFAULT_X_CONTENT_TYPE_OPTIONS)
16
- settings[:x_xss_protection] = Setting.new(HEADER_X_XSS_PROTECTION, DEFAULT_X_XSS_PROTECTION)
17
- settings[:content_security_policy] = ContentSecurityPolicy.new(HEADER_CONTENT_SECURITY_POLICY, DEFAULT_CONTENT_SECURITY_POLICY.dup)
18
- end
19
-
20
- def x_frame_options=(value)
21
- settings[:x_frame_options].value = value
22
- end
23
-
24
- def x_frame_options
25
- settings.fetch(:x_frame_options)
26
- end
27
-
28
- def x_content_type_options=(value)
29
- settings[:x_content_type_options].value = value
30
- end
31
-
32
- def x_content_type_options
33
- settings.fetch(:x_content_type_options)
34
- end
35
-
36
- def x_xss_protection=(value)
37
- settings[:x_xss_protection].value = value
38
- end
39
-
40
- def x_xss_protection
41
- settings.fetch(:x_xss_protection)
42
- end
43
-
44
- def content_security_policy=(options)
45
- settings[:content_security_policy].value = options
46
- end
47
-
48
- def content_security_policy
49
- settings.fetch(:content_security_policy)
50
- end
51
-
52
- def to_hash
53
- settings.each_with_object({}) do |(_, v), result|
54
- next if v.value.nil?
55
-
56
- result[v.header] = v.value
57
- end
58
- end
59
-
60
- private
61
-
62
- # X-Frame-Options
63
- HEADER_X_FRAME_OPTIONS = "X-Frame-Options"
64
- private_constant :HEADER_X_FRAME_OPTIONS
65
-
66
- DEFAULT_X_FRAME_OPTIONS = "DENY"
67
- private_constant :DEFAULT_X_FRAME_OPTIONS
68
-
69
- # X-Content-Type-Optionx
70
- HEADER_X_CONTENT_TYPE_OPTIONS = "X-Content-Type-Options"
71
- private_constant :HEADER_X_CONTENT_TYPE_OPTIONS
72
-
73
- DEFAULT_X_CONTENT_TYPE_OPTIONS = "nosniff"
74
- private_constant :DEFAULT_X_CONTENT_TYPE_OPTIONS
75
-
76
- # X-XSS-Protection
77
- HEADER_X_XSS_PROTECTION = "X-XSS-Protection"
78
- private_constant :HEADER_X_XSS_PROTECTION
79
-
80
- DEFAULT_X_XSS_PROTECTION = "1; mode=block"
81
- private_constant :DEFAULT_X_XSS_PROTECTION
82
-
83
- # Content-Security-Policy
84
- HEADER_CONTENT_SECURITY_POLICY = "Content-Security-Policy"
85
- private_constant :HEADER_CONTENT_SECURITY_POLICY
86
-
87
- DEFAULT_CONTENT_SECURITY_POLICY = {
88
- form_action: "'self'",
89
- frame_ancestors: "'self'",
90
- base_uri: "'self'",
91
- default_src: "'none'",
92
- script_src: "'self'",
93
- connect_src: "'self'",
94
- img_src: "'self' https: data:",
95
- style_src: "'self' 'unsafe-inline' https:",
96
- font_src: "'self'",
97
- object_src: "'none'",
98
- plugin_types: "application/pdf",
99
- child_src: "'self'",
100
- frame_src: "'self'",
101
- media_src: "'self'"
102
- }.freeze
103
- private_constant :DEFAULT_CONTENT_SECURITY_POLICY
104
-
105
- # Security setting
106
- #
107
- # @api private
108
- # @since 2.0.0
109
- class Setting
110
- attr_accessor :header, :value
111
-
112
- def initialize(header, value)
113
- @header = header.freeze
114
- @value = value
115
- end
116
- end
117
-
118
- # Content security policy settings
119
- #
120
- # @api private
121
- # @since 2.0.0
122
- class ContentSecurityPolicy < Setting
123
- def value
124
- @value.map do |k, v|
125
- "#{Utils::String.dasherize(k)} #{v}" unless v.nil?
126
- end.compact.join("; ")
127
- end
128
-
129
- def [](key)
130
- @value[key]
131
- end
132
-
133
- def []=(key, value)
134
- @value[key] = value
135
- end
136
- end
137
-
138
- attr_reader :settings
139
- end
140
- end
141
- end