actionpack 7.0.4.3 → 7.0.8.6

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.

Potentially problematic release.


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

Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +117 -1
  3. data/README.rdoc +2 -2
  4. data/lib/abstract_controller/helpers.rb +15 -11
  5. data/lib/abstract_controller/rendering.rb +9 -11
  6. data/lib/abstract_controller/translation.rb +25 -3
  7. data/lib/action_controller/api.rb +1 -1
  8. data/lib/action_controller/metal/basic_implicit_render.rb +3 -1
  9. data/lib/action_controller/metal/conditional_get.rb +121 -123
  10. data/lib/action_controller/metal/content_security_policy.rb +4 -4
  11. data/lib/action_controller/metal/data_streaming.rb +18 -18
  12. data/lib/action_controller/metal/etag_with_flash.rb +1 -1
  13. data/lib/action_controller/metal/head.rb +1 -1
  14. data/lib/action_controller/metal/http_authentication.rb +2 -1
  15. data/lib/action_controller/metal/live.rb +1 -1
  16. data/lib/action_controller/metal/permissions_policy.rb +1 -1
  17. data/lib/action_controller/metal/redirecting.rb +20 -3
  18. data/lib/action_controller/metal/renderers.rb +2 -2
  19. data/lib/action_controller/metal/rendering.rb +114 -2
  20. data/lib/action_controller/metal/request_forgery_protection.rb +5 -3
  21. data/lib/action_controller/metal/rescue.rb +4 -3
  22. data/lib/action_controller/metal/streaming.rb +1 -1
  23. data/lib/action_controller/metal/strong_parameters.rb +40 -63
  24. data/lib/action_controller/metal/url_for.rb +2 -4
  25. data/lib/action_controller/railtie.rb +2 -1
  26. data/lib/action_controller/renderer.rb +1 -20
  27. data/lib/action_dispatch/http/cache.rb +7 -7
  28. data/lib/action_dispatch/http/content_security_policy.rb +5 -1
  29. data/lib/action_dispatch/http/filter_parameters.rb +13 -28
  30. data/lib/action_dispatch/http/headers.rb +1 -1
  31. data/lib/action_dispatch/http/permissions_policy.rb +0 -7
  32. data/lib/action_dispatch/http/request.rb +15 -16
  33. data/lib/action_dispatch/http/response.rb +0 -4
  34. data/lib/action_dispatch/http/upload.rb +13 -2
  35. data/lib/action_dispatch/middleware/cookies.rb +6 -6
  36. data/lib/action_dispatch/middleware/host_authorization.rb +12 -5
  37. data/lib/action_dispatch/middleware/remote_ip.rb +4 -4
  38. data/lib/action_dispatch/middleware/request_id.rb +2 -2
  39. data/lib/action_dispatch/middleware/show_exceptions.rb +10 -7
  40. data/lib/action_dispatch/middleware/static.rb +3 -3
  41. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.html.erb +7 -3
  42. data/lib/action_dispatch/middleware/templates/rescues/blocked_host.text.erb +5 -3
  43. data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +17 -8
  44. data/lib/action_dispatch/routing/mapper.rb +23 -0
  45. data/lib/action_dispatch/routing/url_for.rb +21 -21
  46. data/lib/action_dispatch/system_testing/browser.rb +1 -1
  47. data/lib/action_dispatch/system_testing/driver.rb +1 -1
  48. data/lib/action_dispatch/testing/assertions/response.rb +1 -1
  49. data/lib/action_pack/gem_version.rb +2 -2
  50. metadata +17 -17
@@ -37,7 +37,6 @@ module ActionDispatch # :nodoc:
37
37
  request = ActionDispatch::Request.new(env)
38
38
  _, headers, _ = response = @app.call(env)
39
39
 
40
- return response unless html_response?(headers)
41
40
  return response if policy_present?(headers)
42
41
 
43
42
  if policy = request.permissions_policy
@@ -52,12 +51,6 @@ module ActionDispatch # :nodoc:
52
51
  end
53
52
 
54
53
  private
55
- def html_response?(headers)
56
- if content_type = headers[CONTENT_TYPE]
57
- /html/.match?(content_type)
58
- end
59
- end
60
-
61
54
  def policy_present?(headers)
62
55
  headers[POLICY]
63
56
  end
@@ -107,22 +107,21 @@ module ActionDispatch
107
107
  has_header? key
108
108
  end
109
109
 
110
- # List of HTTP request methods from the following RFCs:
111
- # Hypertext Transfer Protocol -- HTTP/1.1 (https://www.ietf.org/rfc/rfc2616.txt)
112
- # HTTP Extensions for Distributed Authoring -- WEBDAV (https://www.ietf.org/rfc/rfc2518.txt)
113
- # Versioning Extensions to WebDAV (https://www.ietf.org/rfc/rfc3253.txt)
114
- # Ordered Collections Protocol (WebDAV) (https://www.ietf.org/rfc/rfc3648.txt)
115
- # Web Distributed Authoring and Versioning (WebDAV) Access Control Protocol (https://www.ietf.org/rfc/rfc3744.txt)
116
- # Web Distributed Authoring and Versioning (WebDAV) SEARCH (https://www.ietf.org/rfc/rfc5323.txt)
117
- # Calendar Extensions to WebDAV (https://www.ietf.org/rfc/rfc4791.txt)
118
- # PATCH Method for HTTP (https://www.ietf.org/rfc/rfc5789.txt)
110
+ # HTTP methods from {RFC 2616: Hypertext Transfer Protocol -- HTTP/1.1}[https://www.ietf.org/rfc/rfc2616.txt]
119
111
  RFC2616 = %w(OPTIONS GET HEAD POST PUT DELETE TRACE CONNECT)
112
+ # HTTP methods from {RFC 2518: HTTP Extensions for Distributed Authoring -- WEBDAV}[https://www.ietf.org/rfc/rfc2518.txt]
120
113
  RFC2518 = %w(PROPFIND PROPPATCH MKCOL COPY MOVE LOCK UNLOCK)
114
+ # HTTP methods from {RFC 3253: Versioning Extensions to WebDAV}[https://www.ietf.org/rfc/rfc3253.txt]
121
115
  RFC3253 = %w(VERSION-CONTROL REPORT CHECKOUT CHECKIN UNCHECKOUT MKWORKSPACE UPDATE LABEL MERGE BASELINE-CONTROL MKACTIVITY)
116
+ # HTTP methods from {RFC 3648: WebDAV Ordered Collections Protocol}[https://www.ietf.org/rfc/rfc3648.txt]
122
117
  RFC3648 = %w(ORDERPATCH)
118
+ # HTTP methods from {RFC 3744: WebDAV Access Control Protocol}[https://www.ietf.org/rfc/rfc3744.txt]
123
119
  RFC3744 = %w(ACL)
120
+ # HTTP methods from {RFC 5323: WebDAV SEARCH}[https://www.ietf.org/rfc/rfc5323.txt]
124
121
  RFC5323 = %w(SEARCH)
122
+ # HTTP methods from {RFC 4791: Calendaring Extensions to WebDAV}[https://www.ietf.org/rfc/rfc4791.txt]
125
123
  RFC4791 = %w(MKCALENDAR)
124
+ # HTTP methods from {RFC 5789: PATCH Method for HTTP}[https://www.ietf.org/rfc/rfc5789.txt]
126
125
  RFC5789 = %w(PATCH)
127
126
 
128
127
  HTTP_METHODS = RFC2616 + RFC2518 + RFC3253 + RFC3648 + RFC3744 + RFC5323 + RFC4791 + RFC5789
@@ -271,7 +270,7 @@ module ActionDispatch
271
270
  super.to_i
272
271
  end
273
272
 
274
- # Returns true if the "X-Requested-With" header contains "XMLHttpRequest"
273
+ # Returns true if the +X-Requested-With+ header contains "XMLHttpRequest"
275
274
  # (case-insensitive), which may need to be manually added depending on the
276
275
  # choice of JavaScript libraries and frameworks.
277
276
  def xml_http_request?
@@ -297,7 +296,7 @@ module ActionDispatch
297
296
 
298
297
  ACTION_DISPATCH_REQUEST_ID = "action_dispatch.request_id" # :nodoc:
299
298
 
300
- # Returns the unique request id, which is based on either the X-Request-Id header that can
299
+ # Returns the unique request id, which is based on either the +X-Request-Id+ header that can
301
300
  # be generated by a firewall, load balancer, or web server, or by the RequestId middleware
302
301
  # (which sets the +action_dispatch.request_id+ environment variable).
303
302
  #
@@ -341,13 +340,13 @@ module ActionDispatch
341
340
  end
342
341
 
343
342
  # Determine whether the request body contains form-data by checking
344
- # the request Content-Type for one of the media-types:
345
- # "application/x-www-form-urlencoded" or "multipart/form-data". The
343
+ # the request +Content-Type+ for one of the media-types:
344
+ # +application/x-www-form-urlencoded+ or +multipart/form-data+. The
346
345
  # list of form-data media types can be modified through the
347
346
  # +FORM_DATA_MEDIA_TYPES+ array.
348
347
  #
349
348
  # A request body is not assumed to contain form-data when no
350
- # Content-Type header is provided and the request_method is POST.
349
+ # +Content-Type+ header is provided and the request_method is POST.
351
350
  def form_data?
352
351
  FORM_DATA_MEDIA_TYPES.include?(media_type)
353
352
  end
@@ -379,7 +378,7 @@ module ActionDispatch
379
378
  Request::Utils.check_param_encoding(rack_query_params)
380
379
  set_header k, Request::Utils.normalize_encode_params(rack_query_params)
381
380
  end
382
- rescue Rack::Utils::ParameterTypeError, Rack::Utils::InvalidParameterError => e
381
+ rescue Rack::Utils::ParameterTypeError, Rack::Utils::InvalidParameterError, Rack::QueryParser::ParamsTooDeepError => e
383
382
  raise ActionController::BadRequest.new("Invalid query parameters: #{e.message}")
384
383
  end
385
384
  alias :query_parameters :GET
@@ -394,7 +393,7 @@ module ActionDispatch
394
393
  Request::Utils.check_param_encoding(pr)
395
394
  self.request_parameters = Request::Utils.normalize_encode_params(pr)
396
395
  end
397
- rescue Rack::Utils::ParameterTypeError, Rack::Utils::InvalidParameterError => e
396
+ rescue Rack::Utils::ParameterTypeError, Rack::Utils::InvalidParameterError, Rack::QueryParser::ParamsTooDeepError, EOFError => e
398
397
  raise ActionController::BadRequest.new("Invalid request parameters: #{e.message}")
399
398
  end
400
399
  alias :request_parameters :POST
@@ -501,10 +501,6 @@ module ActionDispatch # :nodoc:
501
501
  def to_path
502
502
  @response.stream.to_path
503
503
  end
504
-
505
- def to_ary
506
- nil
507
- end
508
504
  end
509
505
 
510
506
  def handle_no_content!
@@ -28,6 +28,8 @@ module ActionDispatch
28
28
  @tempfile = hash[:tempfile]
29
29
  raise(ArgumentError, ":tempfile is required") unless @tempfile
30
30
 
31
+ @content_type = hash[:type]
32
+
31
33
  if hash[:filename]
32
34
  @original_filename = hash[:filename].dup
33
35
 
@@ -40,8 +42,17 @@ module ActionDispatch
40
42
  @original_filename = nil
41
43
  end
42
44
 
43
- @content_type = hash[:type]
44
- @headers = hash[:head]
45
+ if hash[:head]
46
+ @headers = hash[:head].dup
47
+
48
+ begin
49
+ @headers.encode!(Encoding::UTF_8)
50
+ rescue EncodingError
51
+ @headers.force_encoding(Encoding::UTF_8)
52
+ end
53
+ else
54
+ @headers = nil
55
+ end
45
56
  end
46
57
 
47
58
  # Shortcut for +tempfile.read+.
@@ -95,7 +95,7 @@ module ActionDispatch
95
95
  # Read and write data to cookies through ActionController::Base#cookies.
96
96
  #
97
97
  # When reading cookie data, the data is read from the HTTP request header, Cookie.
98
- # When writing cookie data, the data is sent out in the HTTP response header, Set-Cookie.
98
+ # When writing cookie data, the data is sent out in the HTTP response header, +Set-Cookie+.
99
99
  #
100
100
  # Examples of writing:
101
101
  #
@@ -443,7 +443,7 @@ module ActionDispatch
443
443
 
444
444
  if options[:domain] == :all || options[:domain] == "all"
445
445
  cookie_domain = ""
446
- dot_splitted_host = request.host.split('.', -1)
446
+ dot_splitted_host = request.host.split(".", -1)
447
447
 
448
448
  # Case where request.host is not an IP address or it's an invalid domain
449
449
  # (ip confirms to the domain structure we expect so we explicitly check for ip)
@@ -453,10 +453,10 @@ module ActionDispatch
453
453
  end
454
454
 
455
455
  # If there is a provided tld length then we use it otherwise default domain.
456
- if options[:tld_length].present?
456
+ if options[:tld_length].present?
457
457
  # Case where the tld_length provided is valid
458
458
  if dot_splitted_host.length >= options[:tld_length]
459
- cookie_domain = dot_splitted_host.last(options[:tld_length]).join('.')
459
+ cookie_domain = dot_splitted_host.last(options[:tld_length]).join(".")
460
460
  end
461
461
  # Case where tld_length is not provided
462
462
  else
@@ -465,7 +465,7 @@ module ActionDispatch
465
465
  cookie_domain = dot_splitted_host.last(2).join(".")
466
466
  # **.**, ***.** style TLDs like co.uk and com.au
467
467
  else
468
- cookie_domain = dot_splitted_host.last(3).join('.')
468
+ cookie_domain = dot_splitted_host.last(3).join(".")
469
469
  end
470
470
  end
471
471
 
@@ -683,7 +683,7 @@ module ActionDispatch
683
683
  deserialize(name) do |rotate|
684
684
  @encryptor.decrypt_and_verify(encrypted_message, on_rotation: rotate, purpose: purpose)
685
685
  end
686
- rescue ActiveSupport::MessageEncryptor::InvalidMessage, ActiveSupport::MessageVerifier::InvalidSignature
686
+ rescue ActiveSupport::MessageEncryptor::InvalidMessage, ActiveSupport::MessageVerifier::InvalidSignature, JSON::ParserError
687
687
  nil
688
688
  end
689
689
 
@@ -95,7 +95,7 @@ module ActionDispatch
95
95
  def response_body(request)
96
96
  return "" unless request.get_header("action_dispatch.show_detailed_exceptions")
97
97
 
98
- template = DebugView.new(host: request.host)
98
+ template = DebugView.new(hosts: request.env["action_dispatch.blocked_hosts"])
99
99
  template.render(template: "rescues/blocked_host", layout: "rescues/layout")
100
100
  end
101
101
 
@@ -111,7 +111,7 @@ module ActionDispatch
111
111
 
112
112
  return unless logger
113
113
 
114
- logger.error("[#{self.class.name}] Blocked host: #{request.host}")
114
+ logger.error("[#{self.class.name}] Blocked hosts: #{request.env["action_dispatch.blocked_hosts"].join(", ")}")
115
115
  end
116
116
 
117
117
  def available_logger(request)
@@ -131,21 +131,28 @@ module ActionDispatch
131
131
  return @app.call(env) if @permissions.empty?
132
132
 
133
133
  request = Request.new(env)
134
+ hosts = blocked_hosts(request)
134
135
 
135
- if authorized?(request) || excluded?(request)
136
+ if hosts.empty? || excluded?(request)
136
137
  mark_as_authorized(request)
137
138
  @app.call(env)
138
139
  else
140
+ env["action_dispatch.blocked_hosts"] = hosts
139
141
  @response_app.call(env)
140
142
  end
141
143
  end
142
144
 
143
145
  private
144
- def authorized?(request)
146
+ def blocked_hosts(request)
147
+ hosts = []
148
+
145
149
  origin_host = request.get_header("HTTP_HOST")
150
+ hosts << origin_host unless @permissions.allows?(origin_host)
151
+
146
152
  forwarded_host = request.x_forwarded_host&.split(/,\s?/)&.last
153
+ hosts << forwarded_host unless forwarded_host.blank? || @permissions.allows?(forwarded_host)
147
154
 
148
- @permissions.allows?(origin_host) && (forwarded_host.blank? || @permissions.allows?(forwarded_host))
155
+ hosts
149
156
  end
150
157
 
151
158
  def excluded?(request)
@@ -22,7 +22,7 @@ module ActionDispatch
22
22
  # This middleware assumes that there is at least one proxy sitting around
23
23
  # and setting headers with the client's remote IP address. If you don't use
24
24
  # a proxy, because you are hosted on e.g. Heroku without SSL, any client can
25
- # claim to have any IP address by setting the X-Forwarded-For header. If you
25
+ # claim to have any IP address by setting the +X-Forwarded-For+ header. If you
26
26
  # care about that, then you need to explicitly drop or ignore those headers
27
27
  # sometime before this middleware runs.
28
28
  class RemoteIp
@@ -53,7 +53,7 @@ module ActionDispatch
53
53
  #
54
54
  # The +custom_proxies+ argument can take an enumerable which will be used
55
55
  # instead of +TRUSTED_PROXIES+. Any proxy setup will put the value you
56
- # want in the middle (or at the beginning) of the X-Forwarded-For list,
56
+ # want in the middle (or at the beginning) of the +X-Forwarded-For+ list,
57
57
  # with your proxy servers after it. If your proxies aren't removed, pass
58
58
  # them in via the +custom_proxies+ parameter. That way, the middleware will
59
59
  # ignore those IP addresses, and return the one that you want.
@@ -110,9 +110,9 @@ module ActionDispatch
110
110
  # REMOTE_ADDR will be correct if the request is made directly against the
111
111
  # Ruby process, on e.g. Heroku. When the request is proxied by another
112
112
  # server like HAProxy or NGINX, the IP address that made the original
113
- # request will be put in an X-Forwarded-For header. If there are multiple
113
+ # request will be put in an +X-Forwarded-For+ header. If there are multiple
114
114
  # proxies, that header may contain a list of IPs. Other proxy services
115
- # set the Client-Ip header instead, so we check that too.
115
+ # set the +Client-Ip+ header instead, so we check that too.
116
116
  #
117
117
  # As discussed in {this post about Rails IP Spoofing}[https://blog.gingerlime.com/2012/rails-ip-spoofing-vulnerabilities-and-protection/],
118
118
  # while the first IP in the list is likely to be the "originating" IP,
@@ -6,9 +6,9 @@ require "active_support/core_ext/string/access"
6
6
  module ActionDispatch
7
7
  # Makes a unique request id available to the +action_dispatch.request_id+ env variable (which is then accessible
8
8
  # through ActionDispatch::Request#request_id or the alias ActionDispatch::Request#uuid) and sends
9
- # the same id to the client via the X-Request-Id header.
9
+ # the same id to the client via the +X-Request-Id+ header.
10
10
  #
11
- # The unique request id is either based on the X-Request-Id header in the request, which would typically be generated
11
+ # The unique request id is either based on the +X-Request-Id+ header in the request, which would typically be generated
12
12
  # by a firewall, load balancer, or the web server, or, if this header is not available, a random uuid. If the
13
13
  # header is accepted from the outside world, we sanitize it to a max of 255 chars and alphanumeric and dashes only.
14
14
  #
@@ -6,14 +6,17 @@ module ActionDispatch
6
6
  # This middleware rescues any exception returned by the application
7
7
  # and calls an exceptions app that will wrap it in a format for the end user.
8
8
  #
9
- # The exceptions app should be passed as parameter on initialization
10
- # of ShowExceptions. Every time there is an exception, ShowExceptions will
11
- # store the exception in env["action_dispatch.exception"], rewrite the
12
- # PATH_INFO to the exception status code and call the Rack app.
9
+ # The exceptions app should be passed as a parameter on initialization of
10
+ # +ShowExceptions+. Every time there is an exception, +ShowExceptions+ will
11
+ # store the exception in <tt>env["action_dispatch.exception"]</tt>, rewrite
12
+ # the +PATH_INFO+ to the exception status code and call the Rack app.
13
13
  #
14
- # If the application returns a "X-Cascade" pass response, this middleware
15
- # will send an empty response as result with the correct status code.
16
- # If any exception happens inside the exceptions app, this middleware
14
+ # In \Rails applications, the exceptions app can be configured with
15
+ # +config.exceptions_app+, which defaults to ActionDispatch::PublicExceptions.
16
+ #
17
+ # If the application returns an <tt>"X-Cascade" => "pass"</tt> response, this
18
+ # middleware will send an empty response as a result with the correct status
19
+ # code. If any exception happens inside the exceptions app, this middleware
17
20
  # catches the exceptions and returns a failsafe response.
18
21
  class ShowExceptions
19
22
  def initialize(app, exceptions_app)
@@ -24,7 +24,7 @@ module ActionDispatch
24
24
  end
25
25
  end
26
26
 
27
- # This endpoint serves static files from disk using Rack::File.
27
+ # This endpoint serves static files from disk using +Rack::File+.
28
28
  #
29
29
  # URL paths are matched with static files according to expected
30
30
  # conventions: +path+, +path+.html, +path+/index.html.
@@ -33,13 +33,13 @@ module ActionDispatch
33
33
  # and gzip (.gz) files are supported. If +path+.br exists, this
34
34
  # endpoint returns that file with a <tt>Content-Encoding: br</tt> header.
35
35
  #
36
- # If no matching file is found, this endpoint responds 404 Not Found.
36
+ # If no matching file is found, this endpoint responds <tt>404 Not Found</tt>.
37
37
  #
38
38
  # Pass the +root+ directory to search for matching files, an optional
39
39
  # <tt>index: "index"</tt> to change the default +path+/index.html, and optional
40
40
  # additional response headers.
41
41
  class FileHandler
42
- # Accept-Encoding value -> file extension
42
+ # +Accept-Encoding+ value -> file extension
43
43
  PRECOMPRESSED = {
44
44
  "br" => ".br",
45
45
  "gzip" => ".gz",
@@ -1,8 +1,12 @@
1
1
  <header>
2
- <h1>Blocked host: <%= @host %></h1>
2
+ <h1>Blocked hosts: <%= @hosts.join(", ") %></h1>
3
3
  </header>
4
4
  <main role="main" id="container">
5
- <h2>To allow requests to <%= @host %> make sure it is a valid hostname (containing only numbers, letters, dashes and dots), then add the following to your environment configuration:</h2>
6
- <pre>config.hosts &lt;&lt; "<%= @host %>"</pre>
5
+ <h2>To allow requests to these hosts, make sure they are valid hostnames (containing only numbers, letters, dashes and dots), then add the following to your environment configuration:</h2>
6
+ <pre>
7
+ <% @hosts.each do |host| %>
8
+ config.hosts &lt;&lt; "<%= host %>"
9
+ <% end %>
10
+ </pre>
7
11
  <p>For more details view: <a href="https://guides.rubyonrails.org/configuring.html#actiondispatch-hostauthorization">the Host Authorization guide</a></p>
8
12
  </main>
@@ -1,7 +1,9 @@
1
- Blocked host: <%= @host %>
1
+ Blocked hosts: <%= @hosts.join(", ") %>
2
2
 
3
- To allow requests to <%= @host %> make sure it is a valid hostname (containing only numbers, letters, dashes and dots), then add the following to your environment configuration:
3
+ To allow requests to these hosts, make sure they are valid hostnames (containing only numbers, letters, dashes and dots), then add the following to your environment configuration:
4
4
 
5
- config.hosts << "<%= @host %>"
5
+ <% @hosts.each do |host| %>
6
+ config.hosts << "<%= host %>"
7
+ <% end %>
6
8
 
7
9
  For more details on host authorization view: https://guides.rubyonrails.org/configuring.html#actiondispatch-hostauthorization
@@ -102,9 +102,9 @@
102
102
  // Enables path search functionality
103
103
  function setupMatchPaths() {
104
104
  // Check if there are any matched results in a section
105
- function checkNoMatch(section, noMatchText) {
105
+ function checkNoMatch(section, trElement) {
106
106
  if (section.children.length <= 1) {
107
- section.innerHTML += noMatchText;
107
+ section.appendChild(trElement);
108
108
  }
109
109
  }
110
110
 
@@ -145,21 +145,30 @@
145
145
  }
146
146
  }
147
147
 
148
+ function buildTr(string) {
149
+ var tr = document.createElement('tr');
150
+ var th = document.createElement('th');
151
+ th.setAttribute('colspan', 4);
152
+ tr.appendChild(th);
153
+ th.innerText = string;
154
+ return tr;
155
+ }
156
+
148
157
  // On key press perform a search for matching paths
149
158
  delayedKeyup(searchElem, function() {
150
159
  var path = sanitizePath(searchElem.value),
151
- defaultExactMatch = '<tr><th colspan="4">Paths Matching (' + path +'):</th></tr>',
152
- defaultFuzzyMatch = '<tr><th colspan="4">Paths Containing (' + path +'):</th></tr>',
153
- noExactMatch = '<tr><th colspan="4">No Exact Matches Found</th></tr>',
154
- noFuzzyMatch = '<tr><th colspan="4">No Fuzzy Matches Found</th></tr>';
160
+ defaultExactMatch = buildTr('Paths Matching (' + path + '):'),
161
+ defaultFuzzyMatch = buildTr('Paths Containing (' + path +'):'),
162
+ noExactMatch = buildTr('No Exact Matches Found'),
163
+ noFuzzyMatch = buildTr('No Fuzzy Matches Found');
155
164
 
156
165
  if (!path)
157
166
  return searchElem.onblur();
158
167
 
159
168
  getJSON('/rails/info/routes?path=' + path, function(matches){
160
169
  // Clear out results section
161
- exactSection.innerHTML = defaultExactMatch;
162
- fuzzySection.innerHTML = defaultFuzzyMatch;
170
+ exactSection.replaceChildren(defaultExactMatch);
171
+ fuzzySection.replaceChildren(defaultFuzzyMatch);
163
172
 
164
173
  // Display exact matches and fuzzy matches
165
174
  pathElements.forEach(function(elem) {
@@ -1584,6 +1584,29 @@ module ActionDispatch
1584
1584
  !parent_resource.singleton? && @scope[:shallow]
1585
1585
  end
1586
1586
 
1587
+ # Loads another routes file with the given +name+ located inside the
1588
+ # +config/routes+ directory. In that file, you can use the normal
1589
+ # routing DSL, but <i>do not</i> surround it with a
1590
+ # +Rails.application.routes.draw+ block.
1591
+ #
1592
+ # # config/routes.rb
1593
+ # Rails.application.routes.draw do
1594
+ # draw :admin # Loads `config/routes/admin.rb`
1595
+ # draw "third_party/some_gem" # Loads `config/routes/third_party/some_gem.rb`
1596
+ # end
1597
+ #
1598
+ # # config/routes/admin.rb
1599
+ # namespace :admin do
1600
+ # resources :accounts
1601
+ # end
1602
+ #
1603
+ # # config/routes/third_party/some_gem.rb
1604
+ # mount SomeGem::Engine, at: "/some_gem"
1605
+ #
1606
+ # <b>CAUTION:</b> Use this feature with care. Having multiple routes
1607
+ # files can negatively impact discoverability and readability. For most
1608
+ # applications — even those with a few hundred routes — it's easier for
1609
+ # developers to have a single routes file.
1587
1610
  def draw(name)
1588
1611
  path = @draw_paths.find do |_path|
1589
1612
  File.exist? "#{_path}/#{name}.rb"
@@ -6,16 +6,16 @@ module ActionDispatch
6
6
  # is also possible: a URL can be generated from one of your routing definitions.
7
7
  # URL generation functionality is centralized in this module.
8
8
  #
9
- # See ActionDispatch::Routing for general information about routing and routes.rb.
9
+ # See ActionDispatch::Routing for general information about routing and <tt>config/routes.rb</tt>.
10
10
  #
11
11
  # <b>Tip:</b> If you need to generate URLs from your models or some other place,
12
- # then ActionController::UrlFor is what you're looking for. Read on for
12
+ # then ActionDispatch::Routing::UrlFor is what you're looking for. Read on for
13
13
  # an introduction. In general, this module should not be included on its own,
14
- # as it is usually included by url_helpers (as in Rails.application.routes.url_helpers).
14
+ # as it is usually included by +url_helpers+ (as in <tt>Rails.application.routes.url_helpers</tt>).
15
15
  #
16
16
  # == URL generation from parameters
17
17
  #
18
- # As you may know, some functions, such as ActionController::Base#url_for
18
+ # As you may know, some functions, such as <tt>ActionController::Base#url_for</tt>
19
19
  # and ActionView::Helpers::UrlHelper#link_to, can generate URLs given a set
20
20
  # of parameters. For example, you've probably had the chance to write code
21
21
  # like this in one of your views:
@@ -24,12 +24,12 @@ module ActionDispatch
24
24
  # action: 'new', message: 'Welcome!') %>
25
25
  # # => <a href="/users/new?message=Welcome%21">Click here</a>
26
26
  #
27
- # link_to, and all other functions that require URL generation functionality,
28
- # actually use ActionController::UrlFor under the hood. And in particular,
29
- # they use the ActionController::UrlFor#url_for method. One can generate
27
+ # +link_to+, and all other functions that require URL generation functionality,
28
+ # actually use ActionDispatch::Routing::UrlFor under the hood. And in particular,
29
+ # they use the ActionDispatch::Routing::UrlFor#url_for method. One can generate
30
30
  # the same path as the above example by using the following code:
31
31
  #
32
- # include UrlFor
32
+ # include ActionDispatch::Routing::UrlFor
33
33
  # url_for(controller: 'users',
34
34
  # action: 'new',
35
35
  # message: 'Welcome!',
@@ -48,17 +48,17 @@ module ActionDispatch
48
48
  # host: 'www.example.com')
49
49
  # # => "http://www.example.com/users/new?message=Welcome%21"
50
50
  #
51
- # By default, all controllers and views have access to a special version of url_for,
52
- # that already knows what the current hostname is. So if you use url_for in your
51
+ # By default, all controllers and views have access to a special version of +url_for+,
52
+ # that already knows what the current hostname is. So if you use +url_for+ in your
53
53
  # controllers or your views, then you don't need to explicitly pass the <tt>:host</tt>
54
54
  # argument.
55
55
  #
56
- # For convenience reasons, mailers provide a shortcut for ActionController::UrlFor#url_for.
57
- # So within mailers, you only have to type +url_for+ instead of 'ActionController::UrlFor#url_for'
58
- # in full. However, mailers don't have hostname information, and you still have to provide
59
- # the +:host+ argument or set the default host that will be used in all mailers using the
60
- # configuration option +config.action_mailer.default_url_options+. For more information on
61
- # url_for in mailers read the ActionMailer#Base documentation.
56
+ # For convenience, mailers also include ActionDispatch::Routing::UrlFor. So
57
+ # within mailers, you can use url_for. However, mailers cannot access
58
+ # incoming web requests in order to derive hostname information, so you have
59
+ # to provide the +:host+ option or set the default host using
60
+ # +default_url_options+. For more information on url_for in mailers see the
61
+ # ActionMailer::Base documentation.
62
62
  #
63
63
  #
64
64
  # == URL generation for named routes
@@ -72,7 +72,7 @@ module ActionDispatch
72
72
  # This generates, among other things, the method <tt>users_path</tt>. By default,
73
73
  # this method is accessible from your controllers, views, and mailers. If you need
74
74
  # to access this auto-generated method from other places (such as a model), then
75
- # you can do that by including Rails.application.routes.url_helpers in your class:
75
+ # you can do that by including <tt>Rails.application.routes.url_helpers</tt> in your class:
76
76
  #
77
77
  # class User < ActiveRecord::Base
78
78
  # include Rails.application.routes.url_helpers
@@ -115,11 +115,11 @@ module ActionDispatch
115
115
  default_url_options
116
116
  end
117
117
 
118
- # Generate a URL based on the options provided, default_url_options, and the
119
- # routes defined in routes.rb. The following options are supported:
118
+ # Generate a URL based on the options provided, +default_url_options+, and the
119
+ # routes defined in <tt>config/routes.rb</tt>. The following options are supported:
120
120
  #
121
121
  # * <tt>:only_path</tt> - If true, the relative URL is returned. Defaults to +false+.
122
- # * <tt>:protocol</tt> - The protocol to connect to. Defaults to 'http'.
122
+ # * <tt>:protocol</tt> - The protocol to connect to. Defaults to <tt>"http"</tt>.
123
123
  # * <tt>:host</tt> - Specifies the host the link should be targeted at.
124
124
  # If <tt>:only_path</tt> is false, this option must be
125
125
  # provided either explicitly, or via +default_url_options+.
@@ -134,7 +134,7 @@ module ActionDispatch
134
134
  # * <tt>:port</tt> - Optionally specify the port to connect to.
135
135
  # * <tt>:anchor</tt> - An anchor name to be appended to the path.
136
136
  # * <tt>:params</tt> - The query parameters to be appended to the path.
137
- # * <tt>:trailing_slash</tt> - If true, adds a trailing slash, as in "/archive/2009/"
137
+ # * <tt>:trailing_slash</tt> - If true, adds a trailing slash, as in <tt>"/archive/2009/"</tt>.
138
138
  # * <tt>:script_name</tt> - Specifies application path relative to domain root. If provided, prepends application path.
139
139
  #
140
140
  # Any other key (<tt>:controller</tt>, <tt>:action</tt>, etc.) given to
@@ -26,7 +26,7 @@ module ActionDispatch
26
26
  yield options if block_given? && options
27
27
  end
28
28
 
29
- # driver_path can be configured as a proc. The webdrivers gem uses this
29
+ # driver_path can be configured as a proc.
30
30
  # proc to update web drivers. Running this proc early allows us to only
31
31
  # update the webdriver once and avoid race conditions when using
32
32
  # parallel tests.
@@ -56,7 +56,7 @@ module ActionDispatch
56
56
  end
57
57
 
58
58
  def browser_options
59
- @options.merge(capabilities: @browser.options).compact
59
+ @options.merge(options: @browser.options).compact
60
60
  end
61
61
 
62
62
  def register_selenium(app)
@@ -20,7 +20,7 @@ module ActionDispatch
20
20
  #
21
21
  # You can also pass an explicit status number like <tt>assert_response(501)</tt>
22
22
  # or its symbolic equivalent <tt>assert_response(:not_implemented)</tt>.
23
- # See Rack::Utils::SYMBOL_TO_STATUS_CODE for a full list.
23
+ # See +Rack::Utils::SYMBOL_TO_STATUS_CODE+ for a full list.
24
24
  #
25
25
  # # Asserts that the response was a redirection
26
26
  # assert_response :redirect
@@ -9,8 +9,8 @@ module ActionPack
9
9
  module VERSION
10
10
  MAJOR = 7
11
11
  MINOR = 0
12
- TINY = 4
13
- PRE = "3"
12
+ TINY = 8
13
+ PRE = "6"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end