actionpack 3.2.19 → 4.2.11.3
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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +412 -503
- data/MIT-LICENSE +1 -1
- data/README.rdoc +11 -294
- data/lib/abstract_controller/asset_paths.rb +2 -2
- data/lib/abstract_controller/base.rb +52 -18
- data/lib/abstract_controller/callbacks.rb +87 -89
- data/lib/abstract_controller/collector.rb +17 -3
- data/lib/abstract_controller/helpers.rb +41 -14
- data/lib/abstract_controller/logger.rb +1 -2
- data/lib/abstract_controller/railties/routes_helpers.rb +3 -3
- data/lib/abstract_controller/rendering.rb +65 -118
- data/lib/abstract_controller/translation.rb +16 -1
- data/lib/abstract_controller/url_for.rb +7 -7
- data/lib/abstract_controller.rb +2 -10
- data/lib/action_controller/base.rb +61 -28
- data/lib/action_controller/caching/fragments.rb +30 -54
- data/lib/action_controller/caching.rb +38 -35
- data/lib/action_controller/log_subscriber.rb +35 -18
- data/lib/action_controller/metal/conditional_get.rb +103 -34
- data/lib/action_controller/metal/data_streaming.rb +20 -26
- data/lib/action_controller/metal/etag_with_template_digest.rb +50 -0
- data/lib/action_controller/metal/exceptions.rb +19 -6
- data/lib/action_controller/metal/flash.rb +41 -9
- data/lib/action_controller/metal/force_ssl.rb +70 -12
- data/lib/action_controller/metal/head.rb +30 -7
- data/lib/action_controller/metal/helpers.rb +11 -11
- data/lib/action_controller/metal/hide_actions.rb +0 -1
- data/lib/action_controller/metal/http_authentication.rb +140 -94
- data/lib/action_controller/metal/implicit_render.rb +1 -1
- data/lib/action_controller/metal/instrumentation.rb +11 -7
- data/lib/action_controller/metal/live.rb +328 -0
- data/lib/action_controller/metal/mime_responds.rb +161 -152
- data/lib/action_controller/metal/params_wrapper.rb +126 -81
- data/lib/action_controller/metal/rack_delegation.rb +10 -4
- data/lib/action_controller/metal/redirecting.rb +44 -41
- data/lib/action_controller/metal/renderers.rb +48 -19
- data/lib/action_controller/metal/rendering.rb +46 -11
- data/lib/action_controller/metal/request_forgery_protection.rb +250 -29
- data/lib/action_controller/metal/streaming.rb +30 -38
- data/lib/action_controller/metal/strong_parameters.rb +669 -0
- data/lib/action_controller/metal/testing.rb +12 -18
- data/lib/action_controller/metal/url_for.rb +31 -29
- data/lib/action_controller/metal.rb +31 -40
- data/lib/action_controller/model_naming.rb +12 -0
- data/lib/action_controller/railtie.rb +38 -18
- data/lib/action_controller/railties/helpers.rb +22 -0
- data/lib/action_controller/test_case.rb +359 -173
- data/lib/action_controller.rb +9 -16
- data/lib/action_dispatch/http/cache.rb +64 -11
- data/lib/action_dispatch/http/filter_parameters.rb +20 -10
- data/lib/action_dispatch/http/filter_redirect.rb +38 -0
- data/lib/action_dispatch/http/headers.rb +85 -17
- data/lib/action_dispatch/http/mime_negotiation.rb +55 -5
- data/lib/action_dispatch/http/mime_type.rb +167 -114
- data/lib/action_dispatch/http/mime_types.rb +2 -1
- data/lib/action_dispatch/http/parameter_filter.rb +44 -46
- data/lib/action_dispatch/http/parameters.rb +30 -46
- data/lib/action_dispatch/http/rack_cache.rb +2 -3
- data/lib/action_dispatch/http/request.rb +108 -45
- data/lib/action_dispatch/http/response.rb +247 -48
- data/lib/action_dispatch/http/upload.rb +60 -29
- data/lib/action_dispatch/http/url.rb +135 -45
- data/lib/action_dispatch/journey/backwards.rb +5 -0
- data/lib/action_dispatch/journey/formatter.rb +166 -0
- data/lib/action_dispatch/journey/gtg/builder.rb +162 -0
- data/lib/action_dispatch/journey/gtg/simulator.rb +47 -0
- data/lib/action_dispatch/journey/gtg/transition_table.rb +157 -0
- data/lib/action_dispatch/journey/nfa/builder.rb +76 -0
- data/lib/action_dispatch/journey/nfa/dot.rb +36 -0
- data/lib/action_dispatch/journey/nfa/simulator.rb +47 -0
- data/lib/action_dispatch/journey/nfa/transition_table.rb +163 -0
- data/lib/action_dispatch/journey/nodes/node.rb +128 -0
- data/lib/action_dispatch/journey/parser.rb +198 -0
- data/lib/action_dispatch/journey/parser.y +49 -0
- data/lib/action_dispatch/journey/parser_extras.rb +23 -0
- data/lib/action_dispatch/journey/path/pattern.rb +193 -0
- data/lib/action_dispatch/journey/route.rb +125 -0
- data/lib/action_dispatch/journey/router/strexp.rb +27 -0
- data/lib/action_dispatch/journey/router/utils.rb +93 -0
- data/lib/action_dispatch/journey/router.rb +144 -0
- data/lib/action_dispatch/journey/routes.rb +80 -0
- data/lib/action_dispatch/journey/scanner.rb +61 -0
- data/lib/action_dispatch/journey/visitors.rb +221 -0
- data/lib/action_dispatch/journey/visualizer/fsm.css +30 -0
- data/lib/action_dispatch/journey/visualizer/fsm.js +134 -0
- data/lib/action_dispatch/journey/visualizer/index.html.erb +52 -0
- data/lib/action_dispatch/journey.rb +5 -0
- data/lib/action_dispatch/middleware/callbacks.rb +16 -11
- data/lib/action_dispatch/middleware/cookies.rb +346 -125
- data/lib/action_dispatch/middleware/debug_exceptions.rb +52 -24
- data/lib/action_dispatch/middleware/exception_wrapper.rb +75 -9
- data/lib/action_dispatch/middleware/flash.rb +85 -72
- data/lib/action_dispatch/middleware/params_parser.rb +16 -31
- data/lib/action_dispatch/middleware/public_exceptions.rb +39 -14
- data/lib/action_dispatch/middleware/reloader.rb +16 -7
- data/lib/action_dispatch/middleware/remote_ip.rb +132 -40
- data/lib/action_dispatch/middleware/request_id.rb +3 -7
- data/lib/action_dispatch/middleware/session/abstract_store.rb +22 -20
- data/lib/action_dispatch/middleware/session/cache_store.rb +3 -3
- data/lib/action_dispatch/middleware/session/cookie_store.rb +84 -29
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +8 -3
- data/lib/action_dispatch/middleware/show_exceptions.rb +15 -44
- data/lib/action_dispatch/middleware/ssl.rb +72 -0
- data/lib/action_dispatch/middleware/stack.rb +6 -1
- data/lib/action_dispatch/middleware/static.rb +80 -23
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb +34 -0
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb +23 -0
- data/lib/action_dispatch/middleware/templates/rescues/_source.erb +27 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb +52 -0
- data/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb +9 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb +16 -0
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb +9 -0
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +133 -5
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.html.erb +11 -0
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.html.erb +32 -0
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.text.erb +11 -0
- data/lib/action_dispatch/middleware/templates/rescues/template_error.html.erb +20 -0
- data/lib/action_dispatch/middleware/templates/rescues/template_error.text.erb +7 -0
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.html.erb +6 -0
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.text.erb +3 -0
- data/lib/action_dispatch/middleware/templates/routes/_route.html.erb +16 -0
- data/lib/action_dispatch/middleware/templates/routes/_table.html.erb +200 -0
- data/lib/action_dispatch/railtie.rb +19 -6
- data/lib/action_dispatch/request/session.rb +193 -0
- data/lib/action_dispatch/request/utils.rb +35 -0
- data/lib/action_dispatch/routing/endpoint.rb +10 -0
- data/lib/action_dispatch/routing/inspector.rb +234 -0
- data/lib/action_dispatch/routing/mapper.rb +897 -436
- data/lib/action_dispatch/routing/polymorphic_routes.rb +213 -92
- data/lib/action_dispatch/routing/redirection.rb +97 -37
- data/lib/action_dispatch/routing/route_set.rb +432 -239
- data/lib/action_dispatch/routing/routes_proxy.rb +7 -4
- data/lib/action_dispatch/routing/url_for.rb +63 -34
- data/lib/action_dispatch/routing.rb +57 -89
- data/lib/action_dispatch/testing/assertions/dom.rb +2 -36
- data/lib/action_dispatch/testing/assertions/response.rb +24 -38
- data/lib/action_dispatch/testing/assertions/routing.rb +55 -54
- data/lib/action_dispatch/testing/assertions/selector.rb +2 -434
- data/lib/action_dispatch/testing/assertions/tag.rb +2 -137
- data/lib/action_dispatch/testing/assertions.rb +11 -7
- data/lib/action_dispatch/testing/integration.rb +88 -72
- data/lib/action_dispatch/testing/test_process.rb +9 -6
- data/lib/action_dispatch/testing/test_request.rb +13 -9
- data/lib/action_dispatch/testing/test_response.rb +1 -5
- data/lib/action_dispatch.rb +24 -21
- data/lib/action_pack/gem_version.rb +15 -0
- data/lib/action_pack/version.rb +5 -7
- data/lib/action_pack.rb +1 -1
- metadata +181 -292
- data/lib/abstract_controller/layouts.rb +0 -423
- data/lib/abstract_controller/view_paths.rb +0 -96
- data/lib/action_controller/caching/actions.rb +0 -185
- data/lib/action_controller/caching/pages.rb +0 -187
- data/lib/action_controller/caching/sweeping.rb +0 -97
- data/lib/action_controller/deprecated/integration_test.rb +0 -2
- data/lib/action_controller/deprecated/performance_test.rb +0 -1
- data/lib/action_controller/deprecated.rb +0 -3
- data/lib/action_controller/metal/compatibility.rb +0 -65
- data/lib/action_controller/metal/responder.rb +0 -286
- data/lib/action_controller/metal/session_management.rb +0 -14
- data/lib/action_controller/railties/paths.rb +0 -25
- data/lib/action_controller/record_identifier.rb +0 -85
- data/lib/action_controller/vendor/html-scanner/html/document.rb +0 -68
- data/lib/action_controller/vendor/html-scanner/html/node.rb +0 -532
- data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +0 -177
- data/lib/action_controller/vendor/html-scanner/html/selector.rb +0 -830
- data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +0 -107
- data/lib/action_controller/vendor/html-scanner/html/version.rb +0 -11
- data/lib/action_controller/vendor/html-scanner.rb +0 -20
- data/lib/action_dispatch/middleware/best_standards_support.rb +0 -30
- data/lib/action_dispatch/middleware/body_proxy.rb +0 -30
- data/lib/action_dispatch/middleware/head.rb +0 -18
- data/lib/action_dispatch/middleware/rescue.rb +0 -26
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +0 -31
- data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +0 -26
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +0 -10
- data/lib/action_dispatch/middleware/templates/rescues/missing_template.erb +0 -2
- data/lib/action_dispatch/middleware/templates/rescues/routing_error.erb +0 -15
- data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +0 -17
- data/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb +0 -2
- data/lib/action_dispatch/testing/performance_test.rb +0 -10
- data/lib/action_view/asset_paths.rb +0 -142
- data/lib/action_view/base.rb +0 -220
- data/lib/action_view/buffers.rb +0 -43
- data/lib/action_view/context.rb +0 -36
- data/lib/action_view/flows.rb +0 -79
- data/lib/action_view/helpers/active_model_helper.rb +0 -50
- data/lib/action_view/helpers/asset_paths.rb +0 -7
- data/lib/action_view/helpers/asset_tag_helper.rb +0 -457
- data/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +0 -146
- data/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +0 -93
- data/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +0 -193
- data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +0 -148
- data/lib/action_view/helpers/atom_feed_helper.rb +0 -200
- data/lib/action_view/helpers/cache_helper.rb +0 -64
- data/lib/action_view/helpers/capture_helper.rb +0 -203
- data/lib/action_view/helpers/controller_helper.rb +0 -25
- data/lib/action_view/helpers/csrf_helper.rb +0 -32
- data/lib/action_view/helpers/date_helper.rb +0 -1062
- data/lib/action_view/helpers/debug_helper.rb +0 -40
- data/lib/action_view/helpers/form_helper.rb +0 -1486
- data/lib/action_view/helpers/form_options_helper.rb +0 -658
- data/lib/action_view/helpers/form_tag_helper.rb +0 -685
- data/lib/action_view/helpers/javascript_helper.rb +0 -110
- data/lib/action_view/helpers/number_helper.rb +0 -622
- data/lib/action_view/helpers/output_safety_helper.rb +0 -38
- data/lib/action_view/helpers/record_tag_helper.rb +0 -111
- data/lib/action_view/helpers/rendering_helper.rb +0 -90
- data/lib/action_view/helpers/sanitize_helper.rb +0 -259
- data/lib/action_view/helpers/tag_helper.rb +0 -160
- data/lib/action_view/helpers/text_helper.rb +0 -426
- data/lib/action_view/helpers/translation_helper.rb +0 -91
- data/lib/action_view/helpers/url_helper.rb +0 -693
- data/lib/action_view/helpers.rb +0 -60
- data/lib/action_view/locale/en.yml +0 -160
- data/lib/action_view/log_subscriber.rb +0 -28
- data/lib/action_view/lookup_context.rb +0 -254
- data/lib/action_view/path_set.rb +0 -89
- data/lib/action_view/railtie.rb +0 -55
- data/lib/action_view/renderer/abstract_renderer.rb +0 -41
- data/lib/action_view/renderer/partial_renderer.rb +0 -415
- data/lib/action_view/renderer/renderer.rb +0 -54
- data/lib/action_view/renderer/streaming_template_renderer.rb +0 -106
- data/lib/action_view/renderer/template_renderer.rb +0 -94
- data/lib/action_view/template/error.rb +0 -128
- data/lib/action_view/template/handlers/builder.rb +0 -26
- data/lib/action_view/template/handlers/erb.rb +0 -125
- data/lib/action_view/template/handlers.rb +0 -50
- data/lib/action_view/template/resolver.rb +0 -272
- data/lib/action_view/template/text.rb +0 -30
- data/lib/action_view/template.rb +0 -337
- data/lib/action_view/test_case.rb +0 -245
- data/lib/action_view/testing/resolvers.rb +0 -50
- data/lib/action_view.rb +0 -84
- data/lib/sprockets/assets.rake +0 -99
- data/lib/sprockets/bootstrap.rb +0 -37
- data/lib/sprockets/compressors.rb +0 -83
- data/lib/sprockets/helpers/isolated_helper.rb +0 -13
- data/lib/sprockets/helpers/rails_helper.rb +0 -182
- data/lib/sprockets/helpers.rb +0 -6
- data/lib/sprockets/railtie.rb +0 -62
- data/lib/sprockets/static_compiler.rb +0 -56
@@ -1,85 +1,175 @@
|
|
1
|
+
require 'active_support/core_ext/module/attribute_accessors'
|
2
|
+
require 'active_support/core_ext/hash/slice'
|
3
|
+
|
1
4
|
module ActionDispatch
|
2
5
|
module Http
|
3
6
|
module URL
|
7
|
+
IP_HOST_REGEXP = /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/
|
8
|
+
HOST_REGEXP = /(^[^:]+:\/\/)?(\[[^\]]+\]|[^:]+)(?::(\d+$))?/
|
9
|
+
PROTOCOL_REGEXP = /^([^:]+)(:)?(\/\/)?$/
|
10
|
+
|
4
11
|
mattr_accessor :tld_length
|
5
12
|
self.tld_length = 1
|
6
13
|
|
7
14
|
class << self
|
8
|
-
def extract_domain(host, tld_length
|
9
|
-
|
10
|
-
host.split('.').last(1 + tld_length).join('.')
|
15
|
+
def extract_domain(host, tld_length)
|
16
|
+
extract_domain_from(host, tld_length) if named_host?(host)
|
11
17
|
end
|
12
18
|
|
13
|
-
def extract_subdomains(host, tld_length
|
14
|
-
|
15
|
-
|
16
|
-
|
19
|
+
def extract_subdomains(host, tld_length)
|
20
|
+
if named_host?(host)
|
21
|
+
extract_subdomains_from(host, tld_length)
|
22
|
+
else
|
23
|
+
[]
|
24
|
+
end
|
17
25
|
end
|
18
26
|
|
19
|
-
def extract_subdomain(host, tld_length
|
27
|
+
def extract_subdomain(host, tld_length)
|
20
28
|
extract_subdomains(host, tld_length).join('.')
|
21
29
|
end
|
22
30
|
|
23
|
-
def url_for(options
|
24
|
-
|
31
|
+
def url_for(options)
|
32
|
+
if options[:only_path]
|
33
|
+
path_for options
|
34
|
+
else
|
35
|
+
full_url_for options
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def full_url_for(options)
|
40
|
+
host = options[:host]
|
41
|
+
protocol = options[:protocol]
|
42
|
+
port = options[:port]
|
43
|
+
|
44
|
+
unless host
|
25
45
|
raise ArgumentError, 'Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true'
|
26
46
|
end
|
27
47
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
48
|
+
build_host_url(host, port, protocol, options, path_for(options))
|
49
|
+
end
|
50
|
+
|
51
|
+
def path_for(options)
|
52
|
+
path = options[:script_name].to_s.chomp("/")
|
53
|
+
path << options[:path] if options.key?(:path)
|
54
|
+
|
55
|
+
add_trailing_slash(path) if options[:trailing_slash]
|
56
|
+
add_params(path, options[:params]) if options.key?(:params)
|
57
|
+
add_anchor(path, options[:anchor]) if options.key?(:anchor)
|
58
|
+
|
59
|
+
path
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def add_params(path, params)
|
65
|
+
params = { params: params } unless params.is_a?(Hash)
|
66
|
+
params.reject! { |_,v| v.to_param.nil? }
|
67
|
+
path << "?#{params.to_query}" unless params.empty?
|
68
|
+
end
|
69
|
+
|
70
|
+
def add_anchor(path, anchor)
|
71
|
+
if anchor
|
72
|
+
path << "##{Journey::Router::Utils.escape_fragment(anchor.to_param)}"
|
39
73
|
end
|
74
|
+
end
|
40
75
|
|
41
|
-
|
76
|
+
def extract_domain_from(host, tld_length)
|
77
|
+
host.split('.').last(1 + tld_length).join('.')
|
78
|
+
end
|
42
79
|
|
43
|
-
|
44
|
-
|
80
|
+
def extract_subdomains_from(host, tld_length)
|
81
|
+
parts = host.split('.')
|
82
|
+
parts[0..-(tld_length + 2)]
|
83
|
+
end
|
45
84
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
85
|
+
def add_trailing_slash(path)
|
86
|
+
# includes querysting
|
87
|
+
if path.include?('?')
|
88
|
+
path.sub!(/\?/, '/\&')
|
89
|
+
# does not have a .format
|
90
|
+
elsif !path.include?(".")
|
91
|
+
path.sub!(/[^\/]\z|\A\z/, '\&/')
|
50
92
|
end
|
51
|
-
rewritten_url << "?#{params.to_query}" unless params.empty?
|
52
|
-
rewritten_url << "##{Journey::Router::Utils.escape_fragment(options[:anchor].to_param.to_s)}" if options[:anchor]
|
53
|
-
rewritten_url
|
54
93
|
end
|
55
94
|
|
56
|
-
|
95
|
+
def build_host_url(host, port, protocol, options, path)
|
96
|
+
if match = host.match(HOST_REGEXP)
|
97
|
+
protocol ||= match[1] unless protocol == false
|
98
|
+
host = match[2]
|
99
|
+
port = match[3] unless options.key? :port
|
100
|
+
end
|
101
|
+
|
102
|
+
protocol = normalize_protocol protocol
|
103
|
+
host = normalize_host(host, options)
|
104
|
+
|
105
|
+
result = protocol.dup
|
106
|
+
|
107
|
+
if options[:user] && options[:password]
|
108
|
+
result << "#{Rack::Utils.escape(options[:user])}:#{Rack::Utils.escape(options[:password])}@"
|
109
|
+
end
|
110
|
+
|
111
|
+
result << host
|
112
|
+
normalize_port(port, protocol) { |normalized_port|
|
113
|
+
result << ":#{normalized_port}"
|
114
|
+
}
|
115
|
+
|
116
|
+
result.concat path
|
117
|
+
end
|
57
118
|
|
58
119
|
def named_host?(host)
|
59
|
-
|
120
|
+
IP_HOST_REGEXP !~ host
|
60
121
|
end
|
61
122
|
|
62
|
-
def
|
63
|
-
|
64
|
-
|
123
|
+
def normalize_protocol(protocol)
|
124
|
+
case protocol
|
125
|
+
when nil
|
126
|
+
"http://"
|
127
|
+
when false, "//"
|
128
|
+
"//"
|
129
|
+
when PROTOCOL_REGEXP
|
130
|
+
"#{$1}://"
|
65
131
|
else
|
66
|
-
""
|
132
|
+
raise ArgumentError, "Invalid :protocol option: #{protocol.inspect}"
|
67
133
|
end
|
68
134
|
end
|
69
135
|
|
70
|
-
def
|
71
|
-
return
|
136
|
+
def normalize_host(_host, options)
|
137
|
+
return _host unless named_host?(_host)
|
72
138
|
|
73
139
|
tld_length = options[:tld_length] || @@tld_length
|
140
|
+
subdomain = options.fetch :subdomain, true
|
141
|
+
domain = options[:domain]
|
74
142
|
|
75
143
|
host = ""
|
76
|
-
|
77
|
-
|
78
|
-
|
144
|
+
if subdomain == true
|
145
|
+
return _host if domain.nil?
|
146
|
+
|
147
|
+
host << extract_subdomains_from(_host, tld_length).join('.')
|
148
|
+
elsif subdomain
|
149
|
+
host << subdomain.to_param
|
79
150
|
end
|
80
|
-
host <<
|
151
|
+
host << "." unless host.empty?
|
152
|
+
host << (domain || extract_domain_from(_host, tld_length))
|
81
153
|
host
|
82
154
|
end
|
155
|
+
|
156
|
+
def normalize_port(port, protocol)
|
157
|
+
return unless port
|
158
|
+
|
159
|
+
case protocol
|
160
|
+
when "//" then yield port
|
161
|
+
when "https://"
|
162
|
+
yield port unless port.to_i == 443
|
163
|
+
else
|
164
|
+
yield port unless port.to_i == 80
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def initialize(env)
|
170
|
+
super
|
171
|
+
@protocol = nil
|
172
|
+
@port = nil
|
83
173
|
end
|
84
174
|
|
85
175
|
# Returns the complete URL used for this request.
|
@@ -94,7 +184,7 @@ module ActionDispatch
|
|
94
184
|
|
95
185
|
# Returns the \host for this request, such as "example.com".
|
96
186
|
def raw_host_with_port
|
97
|
-
if forwarded = env["HTTP_X_FORWARDED_HOST"]
|
187
|
+
if forwarded = env["HTTP_X_FORWARDED_HOST"].presence
|
98
188
|
forwarded.split(/,\s?/).last
|
99
189
|
else
|
100
190
|
env['HTTP_HOST'] || "#{env['SERVER_NAME'] || env['SERVER_ADDR']}:#{env['SERVER_PORT']}"
|
@@ -171,7 +261,7 @@ module ActionDispatch
|
|
171
261
|
# such as 2 to catch <tt>"www"</tt> instead of <tt>"www.rubyonrails"</tt>
|
172
262
|
# in "www.rubyonrails.co.uk".
|
173
263
|
def subdomain(tld_length = @@tld_length)
|
174
|
-
|
264
|
+
ActionDispatch::Http::URL.extract_subdomain(host, tld_length)
|
175
265
|
end
|
176
266
|
end
|
177
267
|
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
require 'action_controller/metal/exceptions'
|
2
|
+
require 'active_support/deprecation'
|
3
|
+
|
4
|
+
module ActionDispatch
|
5
|
+
module Journey
|
6
|
+
# The Formatter class is used for formatting URLs. For example, parameters
|
7
|
+
# passed to +url_for+ in Rails will eventually call Formatter#generate.
|
8
|
+
class Formatter # :nodoc:
|
9
|
+
attr_reader :routes
|
10
|
+
|
11
|
+
def initialize(routes)
|
12
|
+
@routes = routes
|
13
|
+
@cache = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def generate(name, options, path_parameters, parameterize = nil)
|
17
|
+
constraints = path_parameters.merge(options)
|
18
|
+
missing_keys = []
|
19
|
+
|
20
|
+
match_route(name, constraints) do |route|
|
21
|
+
parameterized_parts = extract_parameterized_parts(route, options, path_parameters, parameterize)
|
22
|
+
|
23
|
+
# Skip this route unless a name has been provided or it is a
|
24
|
+
# standard Rails route since we can't determine whether an options
|
25
|
+
# hash passed to url_for matches a Rack application or a redirect.
|
26
|
+
next unless name || route.dispatcher?
|
27
|
+
|
28
|
+
missing_keys = missing_keys(route, parameterized_parts)
|
29
|
+
next unless missing_keys.empty?
|
30
|
+
params = options.dup.delete_if do |key, _|
|
31
|
+
parameterized_parts.key?(key) || route.defaults.key?(key)
|
32
|
+
end
|
33
|
+
|
34
|
+
defaults = route.defaults
|
35
|
+
required_parts = route.required_parts
|
36
|
+
parameterized_parts.delete_if do |key, value|
|
37
|
+
value.to_s == defaults[key].to_s && !required_parts.include?(key)
|
38
|
+
end
|
39
|
+
|
40
|
+
return [route.format(parameterized_parts), params]
|
41
|
+
end
|
42
|
+
|
43
|
+
message = "No route matches #{Hash[constraints.sort_by{|k,v| k.to_s}].inspect}"
|
44
|
+
message << " missing required keys: #{missing_keys.sort.inspect}" unless missing_keys.empty?
|
45
|
+
|
46
|
+
raise ActionController::UrlGenerationError, message
|
47
|
+
end
|
48
|
+
|
49
|
+
def clear
|
50
|
+
@cache = nil
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def extract_parameterized_parts(route, options, recall, parameterize = nil)
|
56
|
+
parameterized_parts = recall.merge(options)
|
57
|
+
|
58
|
+
keys_to_keep = route.parts.reverse.drop_while { |part|
|
59
|
+
!options.key?(part) || (options[part] || recall[part]).nil?
|
60
|
+
} | route.required_parts
|
61
|
+
|
62
|
+
(parameterized_parts.keys - keys_to_keep).each do |bad_key|
|
63
|
+
parameterized_parts.delete(bad_key)
|
64
|
+
end
|
65
|
+
|
66
|
+
if parameterize
|
67
|
+
parameterized_parts.each do |k, v|
|
68
|
+
parameterized_parts[k] = parameterize.call(k, v)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
parameterized_parts.keep_if { |_, v| v }
|
73
|
+
parameterized_parts
|
74
|
+
end
|
75
|
+
|
76
|
+
def named_routes
|
77
|
+
routes.named_routes
|
78
|
+
end
|
79
|
+
|
80
|
+
def match_route(name, options)
|
81
|
+
if named_routes.key?(name)
|
82
|
+
yield named_routes[name]
|
83
|
+
else
|
84
|
+
# Make sure we don't show the deprecation warning more than once
|
85
|
+
warned = false
|
86
|
+
|
87
|
+
routes = non_recursive(cache, options)
|
88
|
+
|
89
|
+
hash = routes.group_by { |_, r| r.score(options) }
|
90
|
+
|
91
|
+
hash.keys.sort.reverse_each do |score|
|
92
|
+
break if score < 0
|
93
|
+
|
94
|
+
hash[score].sort_by { |i, _| i }.each do |_, route|
|
95
|
+
if name && !warned
|
96
|
+
ActiveSupport::Deprecation.warn <<-MSG.squish
|
97
|
+
You are trying to generate the URL for a named route called
|
98
|
+
#{name.inspect} but no such route was found. In the future,
|
99
|
+
this will result in an `ActionController::UrlGenerationError`
|
100
|
+
exception.
|
101
|
+
MSG
|
102
|
+
|
103
|
+
warned = true
|
104
|
+
end
|
105
|
+
|
106
|
+
yield route
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def non_recursive(cache, options)
|
113
|
+
routes = []
|
114
|
+
queue = [cache]
|
115
|
+
|
116
|
+
while queue.any?
|
117
|
+
c = queue.shift
|
118
|
+
routes.concat(c[:___routes]) if c.key?(:___routes)
|
119
|
+
|
120
|
+
options.each do |pair|
|
121
|
+
queue << c[pair] if c.key?(pair)
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
routes
|
126
|
+
end
|
127
|
+
|
128
|
+
# Returns an array populated with missing keys if any are present.
|
129
|
+
def missing_keys(route, parts)
|
130
|
+
missing_keys = []
|
131
|
+
tests = route.path.requirements
|
132
|
+
route.required_parts.each { |key|
|
133
|
+
if tests.key?(key)
|
134
|
+
missing_keys << key unless /\A#{tests[key]}\Z/ === parts[key]
|
135
|
+
else
|
136
|
+
missing_keys << key unless parts[key]
|
137
|
+
end
|
138
|
+
}
|
139
|
+
missing_keys
|
140
|
+
end
|
141
|
+
|
142
|
+
def possibles(cache, options, depth = 0)
|
143
|
+
cache.fetch(:___routes) { [] } + options.find_all { |pair|
|
144
|
+
cache.key?(pair)
|
145
|
+
}.flat_map { |pair|
|
146
|
+
possibles(cache[pair], options, depth + 1)
|
147
|
+
}
|
148
|
+
end
|
149
|
+
|
150
|
+
def build_cache
|
151
|
+
root = { ___routes: [] }
|
152
|
+
routes.each_with_index do |route, i|
|
153
|
+
leaf = route.required_defaults.inject(root) do |h, tuple|
|
154
|
+
h[tuple] ||= {}
|
155
|
+
end
|
156
|
+
(leaf[:___routes] ||= []) << [i, route]
|
157
|
+
end
|
158
|
+
root
|
159
|
+
end
|
160
|
+
|
161
|
+
def cache
|
162
|
+
@cache ||= build_cache
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
require 'action_dispatch/journey/gtg/transition_table'
|
2
|
+
|
3
|
+
module ActionDispatch
|
4
|
+
module Journey # :nodoc:
|
5
|
+
module GTG # :nodoc:
|
6
|
+
class Builder # :nodoc:
|
7
|
+
DUMMY = Nodes::Dummy.new
|
8
|
+
|
9
|
+
attr_reader :root, :ast, :endpoints
|
10
|
+
|
11
|
+
def initialize(root)
|
12
|
+
@root = root
|
13
|
+
@ast = Nodes::Cat.new root, DUMMY
|
14
|
+
@followpos = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def transition_table
|
18
|
+
dtrans = TransitionTable.new
|
19
|
+
marked = {}
|
20
|
+
state_id = Hash.new { |h,k| h[k] = h.length }
|
21
|
+
|
22
|
+
start = firstpos(root)
|
23
|
+
dstates = [start]
|
24
|
+
until dstates.empty?
|
25
|
+
s = dstates.shift
|
26
|
+
next if marked[s]
|
27
|
+
marked[s] = true # mark s
|
28
|
+
|
29
|
+
s.group_by { |state| symbol(state) }.each do |sym, ps|
|
30
|
+
u = ps.flat_map { |l| followpos(l) }
|
31
|
+
next if u.empty?
|
32
|
+
|
33
|
+
if u.uniq == [DUMMY]
|
34
|
+
from = state_id[s]
|
35
|
+
to = state_id[Object.new]
|
36
|
+
dtrans[from, to] = sym
|
37
|
+
|
38
|
+
dtrans.add_accepting(to)
|
39
|
+
ps.each { |state| dtrans.add_memo(to, state.memo) }
|
40
|
+
else
|
41
|
+
dtrans[state_id[s], state_id[u]] = sym
|
42
|
+
|
43
|
+
if u.include?(DUMMY)
|
44
|
+
to = state_id[u]
|
45
|
+
|
46
|
+
accepting = ps.find_all { |l| followpos(l).include?(DUMMY) }
|
47
|
+
|
48
|
+
accepting.each { |accepting_state|
|
49
|
+
dtrans.add_memo(to, accepting_state.memo)
|
50
|
+
}
|
51
|
+
|
52
|
+
dtrans.add_accepting(state_id[u])
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
dstates << u
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
dtrans
|
61
|
+
end
|
62
|
+
|
63
|
+
def nullable?(node)
|
64
|
+
case node
|
65
|
+
when Nodes::Group
|
66
|
+
true
|
67
|
+
when Nodes::Star
|
68
|
+
true
|
69
|
+
when Nodes::Or
|
70
|
+
node.children.any? { |c| nullable?(c) }
|
71
|
+
when Nodes::Cat
|
72
|
+
nullable?(node.left) && nullable?(node.right)
|
73
|
+
when Nodes::Terminal
|
74
|
+
!node.left
|
75
|
+
when Nodes::Unary
|
76
|
+
nullable?(node.left)
|
77
|
+
else
|
78
|
+
raise ArgumentError, 'unknown nullable: %s' % node.class.name
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def firstpos(node)
|
83
|
+
case node
|
84
|
+
when Nodes::Star
|
85
|
+
firstpos(node.left)
|
86
|
+
when Nodes::Cat
|
87
|
+
if nullable?(node.left)
|
88
|
+
firstpos(node.left) | firstpos(node.right)
|
89
|
+
else
|
90
|
+
firstpos(node.left)
|
91
|
+
end
|
92
|
+
when Nodes::Or
|
93
|
+
node.children.flat_map { |c| firstpos(c) }.uniq
|
94
|
+
when Nodes::Unary
|
95
|
+
firstpos(node.left)
|
96
|
+
when Nodes::Terminal
|
97
|
+
nullable?(node) ? [] : [node]
|
98
|
+
else
|
99
|
+
raise ArgumentError, 'unknown firstpos: %s' % node.class.name
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def lastpos(node)
|
104
|
+
case node
|
105
|
+
when Nodes::Star
|
106
|
+
firstpos(node.left)
|
107
|
+
when Nodes::Or
|
108
|
+
node.children.flat_map { |c| lastpos(c) }.uniq
|
109
|
+
when Nodes::Cat
|
110
|
+
if nullable?(node.right)
|
111
|
+
lastpos(node.left) | lastpos(node.right)
|
112
|
+
else
|
113
|
+
lastpos(node.right)
|
114
|
+
end
|
115
|
+
when Nodes::Terminal
|
116
|
+
nullable?(node) ? [] : [node]
|
117
|
+
when Nodes::Unary
|
118
|
+
lastpos(node.left)
|
119
|
+
else
|
120
|
+
raise ArgumentError, 'unknown lastpos: %s' % node.class.name
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def followpos(node)
|
125
|
+
followpos_table[node]
|
126
|
+
end
|
127
|
+
|
128
|
+
private
|
129
|
+
|
130
|
+
def followpos_table
|
131
|
+
@followpos ||= build_followpos
|
132
|
+
end
|
133
|
+
|
134
|
+
def build_followpos
|
135
|
+
table = Hash.new { |h, k| h[k] = [] }
|
136
|
+
@ast.each do |n|
|
137
|
+
case n
|
138
|
+
when Nodes::Cat
|
139
|
+
lastpos(n.left).each do |i|
|
140
|
+
table[i] += firstpos(n.right)
|
141
|
+
end
|
142
|
+
when Nodes::Star
|
143
|
+
lastpos(n).each do |i|
|
144
|
+
table[i] += firstpos(n)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
table
|
149
|
+
end
|
150
|
+
|
151
|
+
def symbol(edge)
|
152
|
+
case edge
|
153
|
+
when Journey::Nodes::Symbol
|
154
|
+
edge.regexp
|
155
|
+
else
|
156
|
+
edge.left
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'strscan'
|
2
|
+
|
3
|
+
module ActionDispatch
|
4
|
+
module Journey # :nodoc:
|
5
|
+
module GTG # :nodoc:
|
6
|
+
class MatchData # :nodoc:
|
7
|
+
attr_reader :memos
|
8
|
+
|
9
|
+
def initialize(memos)
|
10
|
+
@memos = memos
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class Simulator # :nodoc:
|
15
|
+
attr_reader :tt
|
16
|
+
|
17
|
+
def initialize(transition_table)
|
18
|
+
@tt = transition_table
|
19
|
+
end
|
20
|
+
|
21
|
+
def simulate(string)
|
22
|
+
ms = memos(string) { return }
|
23
|
+
MatchData.new(ms)
|
24
|
+
end
|
25
|
+
|
26
|
+
alias :=~ :simulate
|
27
|
+
alias :match :simulate
|
28
|
+
|
29
|
+
def memos(string)
|
30
|
+
input = StringScanner.new(string)
|
31
|
+
state = [0]
|
32
|
+
while sym = input.scan(%r([/.?]|[^/.?]+))
|
33
|
+
state = tt.move(state, sym)
|
34
|
+
end
|
35
|
+
|
36
|
+
acceptance_states = state.find_all { |s|
|
37
|
+
tt.accepting? s
|
38
|
+
}
|
39
|
+
|
40
|
+
return yield if acceptance_states.empty?
|
41
|
+
|
42
|
+
acceptance_states.flat_map { |x| tt.memo(x) }.compact
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|