actionpack 5.2.3 → 6.0.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (128) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +191 -292
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +3 -2
  5. data/lib/abstract_controller/base.rb +4 -2
  6. data/lib/abstract_controller/caching/fragments.rb +6 -22
  7. data/lib/abstract_controller/callbacks.rb +12 -0
  8. data/lib/abstract_controller/collector.rb +1 -1
  9. data/lib/abstract_controller/helpers.rb +2 -2
  10. data/lib/abstract_controller/railties/routes_helpers.rb +1 -1
  11. data/lib/abstract_controller/translation.rb +1 -0
  12. data/lib/action_controller.rb +5 -1
  13. data/lib/action_controller/api.rb +2 -1
  14. data/lib/action_controller/base.rb +2 -7
  15. data/lib/action_controller/caching.rb +1 -1
  16. data/lib/action_controller/log_subscriber.rb +8 -5
  17. data/lib/action_controller/metal.rb +3 -3
  18. data/lib/action_controller/metal/basic_implicit_render.rb +1 -1
  19. data/lib/action_controller/metal/conditional_get.rb +9 -3
  20. data/lib/action_controller/metal/data_streaming.rb +5 -6
  21. data/lib/action_controller/metal/default_headers.rb +17 -0
  22. data/lib/action_controller/metal/etag_with_template_digest.rb +1 -1
  23. data/lib/action_controller/metal/exceptions.rb +23 -2
  24. data/lib/action_controller/metal/flash.rb +5 -5
  25. data/lib/action_controller/metal/force_ssl.rb +15 -56
  26. data/lib/action_controller/metal/head.rb +1 -1
  27. data/lib/action_controller/metal/helpers.rb +3 -4
  28. data/lib/action_controller/metal/http_authentication.rb +20 -21
  29. data/lib/action_controller/metal/implicit_render.rb +4 -14
  30. data/lib/action_controller/metal/instrumentation.rb +3 -5
  31. data/lib/action_controller/metal/live.rb +29 -27
  32. data/lib/action_controller/metal/mime_responds.rb +13 -2
  33. data/lib/action_controller/metal/params_wrapper.rb +18 -14
  34. data/lib/action_controller/metal/redirecting.rb +5 -5
  35. data/lib/action_controller/metal/renderers.rb +4 -4
  36. data/lib/action_controller/metal/rendering.rb +2 -2
  37. data/lib/action_controller/metal/request_forgery_protection.rb +23 -12
  38. data/lib/action_controller/metal/strong_parameters.rb +63 -44
  39. data/lib/action_controller/metal/url_for.rb +1 -1
  40. data/lib/action_controller/railties/helpers.rb +1 -1
  41. data/lib/action_controller/renderer.rb +16 -3
  42. data/lib/action_controller/template_assertions.rb +1 -1
  43. data/lib/action_controller/test_case.rb +4 -6
  44. data/lib/action_dispatch.rb +4 -2
  45. data/lib/action_dispatch/http/cache.rb +14 -10
  46. data/lib/action_dispatch/http/content_disposition.rb +45 -0
  47. data/lib/action_dispatch/http/content_security_policy.rb +28 -16
  48. data/lib/action_dispatch/http/filter_parameters.rb +8 -6
  49. data/lib/action_dispatch/http/filter_redirect.rb +1 -1
  50. data/lib/action_dispatch/http/headers.rb +1 -1
  51. data/lib/action_dispatch/http/mime_negotiation.rb +7 -5
  52. data/lib/action_dispatch/http/mime_type.rb +14 -6
  53. data/lib/action_dispatch/http/parameter_filter.rb +5 -79
  54. data/lib/action_dispatch/http/parameters.rb +13 -3
  55. data/lib/action_dispatch/http/request.rb +10 -13
  56. data/lib/action_dispatch/http/response.rb +39 -18
  57. data/lib/action_dispatch/http/upload.rb +9 -1
  58. data/lib/action_dispatch/http/url.rb +81 -81
  59. data/lib/action_dispatch/journey/formatter.rb +2 -2
  60. data/lib/action_dispatch/journey/nfa/simulator.rb +0 -2
  61. data/lib/action_dispatch/journey/nodes/node.rb +9 -8
  62. data/lib/action_dispatch/journey/path/pattern.rb +8 -3
  63. data/lib/action_dispatch/journey/route.rb +5 -4
  64. data/lib/action_dispatch/journey/router.rb +0 -3
  65. data/lib/action_dispatch/journey/router/utils.rb +10 -10
  66. data/lib/action_dispatch/journey/routes.rb +0 -1
  67. data/lib/action_dispatch/journey/scanner.rb +11 -4
  68. data/lib/action_dispatch/journey/visitors.rb +1 -1
  69. data/lib/action_dispatch/middleware/actionable_exceptions.rb +39 -0
  70. data/lib/action_dispatch/middleware/callbacks.rb +2 -4
  71. data/lib/action_dispatch/middleware/cookies.rb +52 -74
  72. data/lib/action_dispatch/middleware/debug_exceptions.rb +39 -59
  73. data/lib/action_dispatch/middleware/debug_locks.rb +5 -5
  74. data/lib/action_dispatch/middleware/debug_view.rb +68 -0
  75. data/lib/action_dispatch/middleware/exception_wrapper.rb +49 -15
  76. data/lib/action_dispatch/middleware/flash.rb +1 -1
  77. data/lib/action_dispatch/middleware/host_authorization.rb +103 -0
  78. data/lib/action_dispatch/middleware/public_exceptions.rb +6 -2
  79. data/lib/action_dispatch/middleware/remote_ip.rb +9 -11
  80. data/lib/action_dispatch/middleware/request_id.rb +2 -2
  81. data/lib/action_dispatch/middleware/session/cookie_store.rb +1 -6
  82. data/lib/action_dispatch/middleware/show_exceptions.rb +1 -1
  83. data/lib/action_dispatch/middleware/ssl.rb +8 -8
  84. data/lib/action_dispatch/middleware/stack.rb +34 -2
  85. data/lib/action_dispatch/middleware/static.rb +5 -6
  86. data/lib/action_dispatch/middleware/templates/rescues/_actions.html.erb +13 -0
  87. data/lib/action_dispatch/middleware/templates/rescues/_actions.text.erb +0 -0
  88. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +3 -1
  89. data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +1 -1
  90. data/lib/action_dispatch/middleware/templates/rescues/_source.html.erb +4 -2
  91. data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +45 -35
  92. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +7 -0
  93. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +5 -0
  94. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +26 -4
  95. data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +1 -1
  96. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.html.erb +7 -4
  97. data/lib/action_dispatch/middleware/templates/rescues/invalid_statement.text.erb +4 -2
  98. data/lib/action_dispatch/middleware/templates/rescues/layout.erb +4 -0
  99. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.html.erb +19 -0
  100. data/lib/action_dispatch/middleware/templates/rescues/missing_exact_template.text.erb +3 -0
  101. data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +2 -2
  102. data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +1 -1
  103. data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +2 -2
  104. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +3 -0
  105. data/lib/action_dispatch/railtie.rb +7 -2
  106. data/lib/action_dispatch/request/session.rb +8 -0
  107. data/lib/action_dispatch/routing.rb +21 -20
  108. data/lib/action_dispatch/routing/inspector.rb +99 -50
  109. data/lib/action_dispatch/routing/mapper.rb +61 -39
  110. data/lib/action_dispatch/routing/polymorphic_routes.rb +3 -4
  111. data/lib/action_dispatch/routing/route_set.rb +24 -27
  112. data/lib/action_dispatch/routing/url_for.rb +1 -0
  113. data/lib/action_dispatch/system_test_case.rb +43 -5
  114. data/lib/action_dispatch/system_testing/browser.rb +38 -7
  115. data/lib/action_dispatch/system_testing/driver.rb +10 -1
  116. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +6 -5
  117. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +7 -6
  118. data/lib/action_dispatch/testing/assertions.rb +1 -1
  119. data/lib/action_dispatch/testing/assertions/response.rb +2 -3
  120. data/lib/action_dispatch/testing/assertions/routing.rb +15 -3
  121. data/lib/action_dispatch/testing/integration.rb +12 -5
  122. data/lib/action_dispatch/testing/request_encoder.rb +2 -2
  123. data/lib/action_dispatch/testing/test_process.rb +2 -2
  124. data/lib/action_dispatch/testing/test_response.rb +4 -32
  125. data/lib/action_pack.rb +1 -1
  126. data/lib/action_pack/gem_version.rb +3 -3
  127. metadata +29 -16
  128. data/lib/action_dispatch/system_testing/test_helpers/undef_methods.rb +0 -26
@@ -111,13 +111,23 @@ module ActionDispatch
111
111
  begin
112
112
  strategy.call(raw_post)
113
113
  rescue # JSON or Ruby code block errors.
114
- my_logger = logger || ActiveSupport::Logger.new($stderr)
115
- my_logger.debug "Error occurred while parsing request parameters.\nContents:\n\n#{raw_post}"
116
-
114
+ log_parse_error_once
117
115
  raise ParseError
118
116
  end
119
117
  end
120
118
 
119
+ def log_parse_error_once
120
+ @parse_error_logged ||= begin
121
+ parse_logger = logger || ActiveSupport::Logger.new($stderr)
122
+ parse_logger.debug <<~MSG.chomp
123
+ Error occurred while parsing request parameters.
124
+ Contents:
125
+
126
+ #{raw_post}
127
+ MSG
128
+ end
129
+ end
130
+
121
131
  def params_parsers
122
132
  ActionDispatch::Request.parameter_parsers
123
133
  end
@@ -136,11 +136,11 @@ module ActionDispatch
136
136
  end
137
137
 
138
138
  def routes # :nodoc:
139
- get_header("action_dispatch.routes".freeze)
139
+ get_header("action_dispatch.routes")
140
140
  end
141
141
 
142
142
  def routes=(routes) # :nodoc:
143
- set_header("action_dispatch.routes".freeze, routes)
143
+ set_header("action_dispatch.routes", routes)
144
144
  end
145
145
 
146
146
  def engine_script_name(_routes) # :nodoc:
@@ -158,11 +158,11 @@ module ActionDispatch
158
158
  end
159
159
 
160
160
  def controller_instance # :nodoc:
161
- get_header("action_controller.instance".freeze)
161
+ get_header("action_controller.instance")
162
162
  end
163
163
 
164
164
  def controller_instance=(controller) # :nodoc:
165
- set_header("action_controller.instance".freeze, controller)
165
+ set_header("action_controller.instance", controller)
166
166
  end
167
167
 
168
168
  def http_auth_salt
@@ -173,7 +173,7 @@ module ActionDispatch
173
173
  # We're treating `nil` as "unset", and we want the default setting to be
174
174
  # `true`. This logic should be extracted to `env_config` and calculated
175
175
  # once.
176
- !(get_header("action_dispatch.show_exceptions".freeze) == false)
176
+ !(get_header("action_dispatch.show_exceptions") == false)
177
177
  end
178
178
 
179
179
  # Returns a symbol form of the #request_method.
@@ -280,10 +280,10 @@ module ActionDispatch
280
280
  end
281
281
 
282
282
  def remote_ip=(remote_ip)
283
- set_header "action_dispatch.remote_ip".freeze, remote_ip
283
+ set_header "action_dispatch.remote_ip", remote_ip
284
284
  end
285
285
 
286
- ACTION_DISPATCH_REQUEST_ID = "action_dispatch.request_id".freeze # :nodoc:
286
+ ACTION_DISPATCH_REQUEST_ID = "action_dispatch.request_id" # :nodoc:
287
287
 
288
288
  # Returns the unique request id, which is based on either the X-Request-Id header that can
289
289
  # be generated by a firewall, load balancer, or web server or by the RequestId middleware
@@ -383,9 +383,6 @@ module ActionDispatch
383
383
  end
384
384
  self.request_parameters = Request::Utils.normalize_encode_params(pr)
385
385
  end
386
- rescue Http::Parameters::ParseError # one of the parse strategies blew up
387
- self.request_parameters = Request::Utils.normalize_encode_params(super || {})
388
- raise
389
386
  rescue Rack::Utils::ParameterTypeError, Rack::Utils::InvalidParameterError => e
390
387
  raise ActionController::BadRequest.new("Invalid request parameters: #{e.message}")
391
388
  end
@@ -407,18 +404,18 @@ module ActionDispatch
407
404
 
408
405
  def request_parameters=(params)
409
406
  raise if params.nil?
410
- set_header("action_dispatch.request.request_parameters".freeze, params)
407
+ set_header("action_dispatch.request.request_parameters", params)
411
408
  end
412
409
 
413
410
  def logger
414
- get_header("action_dispatch.logger".freeze)
411
+ get_header("action_dispatch.logger")
415
412
  end
416
413
 
417
414
  def commit_flash
418
415
  end
419
416
 
420
417
  def ssl?
421
- super || scheme == "wss".freeze
418
+ super || scheme == "wss"
422
419
  end
423
420
 
424
421
  private
@@ -78,14 +78,14 @@ module ActionDispatch # :nodoc:
78
78
  x
79
79
  end
80
80
 
81
- CONTENT_TYPE = "Content-Type".freeze
82
- SET_COOKIE = "Set-Cookie".freeze
83
- LOCATION = "Location".freeze
81
+ CONTENT_TYPE = "Content-Type"
82
+ SET_COOKIE = "Set-Cookie"
83
+ LOCATION = "Location"
84
84
  NO_CONTENT_CODES = [100, 101, 102, 204, 205, 304]
85
- CONTENT_TYPE_PARSER = /\A(?<type>[^;\s]+)?(?:.*;\s*charset=(?<quote>"?)(?<charset>[^;\s]+)\k<quote>)?/ # :nodoc:
86
85
 
87
86
  cattr_accessor :default_charset, default: "utf-8"
88
87
  cattr_accessor :default_headers
88
+ cattr_accessor :return_only_media_type_on_content_type, default: false
89
89
 
90
90
  include Rack::Response::Helpers
91
91
  # Aliasing these off because AD::Http::Cache::Response defines them.
@@ -106,7 +106,7 @@ module ActionDispatch # :nodoc:
106
106
 
107
107
  def body
108
108
  @str_body ||= begin
109
- buf = "".dup
109
+ buf = +""
110
110
  each { |chunk| buf << chunk }
111
111
  buf
112
112
  end
@@ -225,16 +225,6 @@ module ActionDispatch # :nodoc:
225
225
  @status = Rack::Utils.status_code(status)
226
226
  end
227
227
 
228
- # Sets the HTTP content type.
229
- def content_type=(content_type)
230
- return unless content_type
231
- new_header_info = parse_content_type(content_type.to_s)
232
- prev_header_info = parsed_content_type_header
233
- charset = new_header_info.charset || prev_header_info.charset
234
- charset ||= self.class.default_charset unless prev_header_info.mime_type
235
- set_content_type new_header_info.mime_type, charset
236
- end
237
-
238
228
  # Sets the HTTP response's content MIME type. For example, in the controller
239
229
  # you could write this:
240
230
  #
@@ -243,8 +233,32 @@ module ActionDispatch # :nodoc:
243
233
  # If a character set has been defined for this response (see charset=) then
244
234
  # the character set information will also be included in the content type
245
235
  # information.
236
+ def content_type=(content_type)
237
+ return unless content_type
238
+ new_header_info = parse_content_type(content_type.to_s)
239
+ prev_header_info = parsed_content_type_header
240
+ charset = new_header_info.charset || prev_header_info.charset
241
+ charset ||= self.class.default_charset unless prev_header_info.mime_type
242
+ set_content_type new_header_info.mime_type, charset
243
+ end
246
244
 
245
+ # Content type of response.
247
246
  def content_type
247
+ if self.class.return_only_media_type_on_content_type
248
+ ActiveSupport::Deprecation.warn(
249
+ "Rails 6.1 will return Content-Type header without modification." \
250
+ " If you want just the MIME type, please use `#media_type` instead."
251
+ )
252
+
253
+ content_type = super
254
+ content_type ? content_type.split(/;\s*charset=/)[0].presence : content_type
255
+ else
256
+ super.presence
257
+ end
258
+ end
259
+
260
+ # Media type of response.
261
+ def media_type
248
262
  parsed_content_type_header.mime_type
249
263
  end
250
264
 
@@ -405,13 +419,18 @@ module ActionDispatch # :nodoc:
405
419
  end
406
420
 
407
421
  private
408
-
409
422
  ContentTypeHeader = Struct.new :mime_type, :charset
410
423
  NullContentTypeHeader = ContentTypeHeader.new nil, nil
411
424
 
425
+ CONTENT_TYPE_PARSER = /
426
+ \A
427
+ (?<mime_type>[^;\s]+\s*(?:;\s*(?:(?!charset)[^;\s])+)*)?
428
+ (?:;\s*charset=(?<quote>"?)(?<charset>[^;\s]+)\k<quote>)?
429
+ /x # :nodoc:
430
+
412
431
  def parse_content_type(content_type)
413
432
  if content_type && match = CONTENT_TYPE_PARSER.match(content_type)
414
- ContentTypeHeader.new(match[:type], match[:charset])
433
+ ContentTypeHeader.new(match[:mime_type], match[:charset])
415
434
  else
416
435
  NullContentTypeHeader
417
436
  end
@@ -458,7 +477,7 @@ module ActionDispatch # :nodoc:
458
477
  end
459
478
 
460
479
  def assign_default_content_type_and_charset!
461
- return if content_type
480
+ return if media_type
462
481
 
463
482
  ct = parsed_content_type_header
464
483
  set_content_type(ct.mime_type || Mime[:html].to_s,
@@ -516,4 +535,6 @@ module ActionDispatch # :nodoc:
516
535
  end
517
536
  end
518
537
  end
538
+
539
+ ActiveSupport.run_load_hooks(:action_dispatch_response, Response)
519
540
  end
@@ -20,7 +20,6 @@ module ActionDispatch
20
20
  # A +Tempfile+ object with the actual uploaded file. Note that some of
21
21
  # its interface is available directly.
22
22
  attr_accessor :tempfile
23
- alias :to_io :tempfile
24
23
 
25
24
  # A string with the headers of the multipart request.
26
25
  attr_accessor :headers
@@ -65,6 +64,11 @@ module ActionDispatch
65
64
  @tempfile.path
66
65
  end
67
66
 
67
+ # Shortcut for +tempfile.to_path+.
68
+ def to_path
69
+ @tempfile.to_path
70
+ end
71
+
68
72
  # Shortcut for +tempfile.rewind+.
69
73
  def rewind
70
74
  @tempfile.rewind
@@ -79,6 +83,10 @@ module ActionDispatch
79
83
  def eof?
80
84
  @tempfile.eof?
81
85
  end
86
+
87
+ def to_io
88
+ @tempfile.to_io
89
+ end
82
90
  end
83
91
  end
84
92
  end
@@ -67,7 +67,7 @@ module ActionDispatch
67
67
  end
68
68
 
69
69
  def path_for(options)
70
- path = options[:script_name].to_s.chomp("/".freeze)
70
+ path = options[:script_name].to_s.chomp("/")
71
71
  path << options[:path] if options.key?(:path)
72
72
 
73
73
  add_trailing_slash(path) if options[:trailing_slash]
@@ -79,108 +79,108 @@ module ActionDispatch
79
79
 
80
80
  private
81
81
 
82
- def add_params(path, params)
83
- params = { params: params } unless params.is_a?(Hash)
84
- params.reject! { |_, v| v.to_param.nil? }
85
- query = params.to_query
86
- path << "?#{query}" unless query.empty?
87
- end
88
-
89
- def add_anchor(path, anchor)
90
- if anchor
91
- path << "##{Journey::Router::Utils.escape_fragment(anchor.to_param)}"
82
+ def add_params(path, params)
83
+ params = { params: params } unless params.is_a?(Hash)
84
+ params.reject! { |_, v| v.to_param.nil? }
85
+ query = params.to_query
86
+ path << "?#{query}" unless query.empty?
92
87
  end
93
- end
94
88
 
95
- def extract_domain_from(host, tld_length)
96
- host.split(".").last(1 + tld_length).join(".")
97
- end
89
+ def add_anchor(path, anchor)
90
+ if anchor
91
+ path << "##{Journey::Router::Utils.escape_fragment(anchor.to_param)}"
92
+ end
93
+ end
98
94
 
99
- def extract_subdomains_from(host, tld_length)
100
- parts = host.split(".")
101
- parts[0..-(tld_length + 2)]
102
- end
95
+ def extract_domain_from(host, tld_length)
96
+ host.split(".").last(1 + tld_length).join(".")
97
+ end
103
98
 
104
- def add_trailing_slash(path)
105
- if path.include?("?")
106
- path.sub!(/\?/, '/\&')
107
- elsif !path.include?(".")
108
- path.sub!(/[^\/]\z|\A\z/, '\&/')
99
+ def extract_subdomains_from(host, tld_length)
100
+ parts = host.split(".")
101
+ parts[0..-(tld_length + 2)]
109
102
  end
110
- end
111
103
 
112
- def build_host_url(host, port, protocol, options, path)
113
- if match = host.match(HOST_REGEXP)
114
- protocol ||= match[1] unless protocol == false
115
- host = match[2]
116
- port = match[3] unless options.key? :port
104
+ def add_trailing_slash(path)
105
+ if path.include?("?")
106
+ path.sub!(/\?/, '/\&')
107
+ elsif !path.include?(".")
108
+ path.sub!(/[^\/]\z|\A\z/, '\&/')
109
+ end
117
110
  end
118
111
 
119
- protocol = normalize_protocol protocol
120
- host = normalize_host(host, options)
112
+ def build_host_url(host, port, protocol, options, path)
113
+ if match = host.match(HOST_REGEXP)
114
+ protocol ||= match[1] unless protocol == false
115
+ host = match[2]
116
+ port = match[3] unless options.key? :port
117
+ end
121
118
 
122
- result = protocol.dup
119
+ protocol = normalize_protocol protocol
120
+ host = normalize_host(host, options)
123
121
 
124
- if options[:user] && options[:password]
125
- result << "#{Rack::Utils.escape(options[:user])}:#{Rack::Utils.escape(options[:password])}@"
126
- end
122
+ result = protocol.dup
127
123
 
128
- result << host
129
- normalize_port(port, protocol) { |normalized_port|
130
- result << ":#{normalized_port}"
131
- }
124
+ if options[:user] && options[:password]
125
+ result << "#{Rack::Utils.escape(options[:user])}:#{Rack::Utils.escape(options[:password])}@"
126
+ end
132
127
 
133
- result.concat path
134
- end
128
+ result << host
129
+ normalize_port(port, protocol) { |normalized_port|
130
+ result << ":#{normalized_port}"
131
+ }
135
132
 
136
- def named_host?(host)
137
- IP_HOST_REGEXP !~ host
138
- end
133
+ result.concat path
134
+ end
139
135
 
140
- def normalize_protocol(protocol)
141
- case protocol
142
- when nil
143
- "http://"
144
- when false, "//"
145
- "//"
146
- when PROTOCOL_REGEXP
147
- "#{$1}://"
148
- else
149
- raise ArgumentError, "Invalid :protocol option: #{protocol.inspect}"
136
+ def named_host?(host)
137
+ IP_HOST_REGEXP !~ host
150
138
  end
151
- end
152
139
 
153
- def normalize_host(_host, options)
154
- return _host unless named_host?(_host)
140
+ def normalize_protocol(protocol)
141
+ case protocol
142
+ when nil
143
+ "http://"
144
+ when false, "//"
145
+ "//"
146
+ when PROTOCOL_REGEXP
147
+ "#{$1}://"
148
+ else
149
+ raise ArgumentError, "Invalid :protocol option: #{protocol.inspect}"
150
+ end
151
+ end
155
152
 
156
- tld_length = options[:tld_length] || @@tld_length
157
- subdomain = options.fetch :subdomain, true
158
- domain = options[:domain]
153
+ def normalize_host(_host, options)
154
+ return _host unless named_host?(_host)
159
155
 
160
- host = "".dup
161
- if subdomain == true
162
- return _host if domain.nil?
156
+ tld_length = options[:tld_length] || @@tld_length
157
+ subdomain = options.fetch :subdomain, true
158
+ domain = options[:domain]
163
159
 
164
- host << extract_subdomains_from(_host, tld_length).join(".")
165
- elsif subdomain
166
- host << subdomain.to_param
160
+ host = +""
161
+ if subdomain == true
162
+ return _host if domain.nil?
163
+
164
+ host << extract_subdomains_from(_host, tld_length).join(".")
165
+ elsif subdomain
166
+ host << subdomain.to_param
167
+ end
168
+ host << "." unless host.empty?
169
+ host << (domain || extract_domain_from(_host, tld_length))
170
+ host
167
171
  end
168
- host << "." unless host.empty?
169
- host << (domain || extract_domain_from(_host, tld_length))
170
- host
171
- end
172
172
 
173
- def normalize_port(port, protocol)
174
- return unless port
173
+ def normalize_port(port, protocol)
174
+ return unless port
175
175
 
176
- case protocol
177
- when "//" then yield port
178
- when "https://"
179
- yield port unless port.to_i == 443
180
- else
181
- yield port unless port.to_i == 80
176
+ case protocol
177
+ when "//" then yield port
178
+ when "https://"
179
+ yield port unless port.to_i == 443
180
+ else
181
+ yield port unless port.to_i == 80
182
+ end
182
183
  end
183
- end
184
184
  end
185
185
 
186
186
  def initialize
@@ -231,7 +231,7 @@ module ActionDispatch
231
231
  # req = ActionDispatch::Request.new 'HTTP_HOST' => 'example.com:8080'
232
232
  # req.host # => "example.com"
233
233
  def host
234
- raw_host_with_port.sub(/:\d+$/, "".freeze)
234
+ raw_host_with_port.sub(/:\d+$/, "")
235
235
  end
236
236
 
237
237
  # Returns a \host:\port string for this request, such as "example.com" or