diff options
Diffstat (limited to 'actionpack/lib/action_dispatch')
9 files changed, 80 insertions, 26 deletions
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb index de014a9c00..796e0dbc45 100644 --- a/actionpack/lib/action_dispatch/http/request.rb +++ b/actionpack/lib/action_dispatch/http/request.rb @@ -17,7 +17,8 @@ module ActionDispatch include ActionDispatch::Http::Upload include ActionDispatch::Http::URL - LOCALHOST = [/^127\.0\.0\.\d{1,3}$/, "::1", /^0:0:0:0:0:0:0:1(%.*)?$/].freeze + LOCALHOST = Regexp.union [/^127\.0\.0\.\d{1,3}$/, /^::1$/, /^0:0:0:0:0:0:0:1(%.*)?$/] + ENV_METHODS = %w[ AUTH_TYPE GATEWAY_INTERFACE PATH_TRANSLATED REMOTE_HOST REMOTE_IDENT REMOTE_USER REMOTE_ADDR @@ -250,7 +251,7 @@ module ActionDispatch # True if the request came from localhost, 127.0.0.1. def local? - LOCALHOST.any? { |local_ip| local_ip === remote_addr && local_ip === remote_ip } + LOCALHOST =~ remote_addr && LOCALHOST =~ remote_ip end private diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb index 80ffbe575b..f9dae5dad7 100644 --- a/actionpack/lib/action_dispatch/http/url.rb +++ b/actionpack/lib/action_dispatch/http/url.rb @@ -40,7 +40,9 @@ module ActionDispatch rewritten_url << ":#{options.delete(:port)}" if options[:port] end - path = options.delete(:path) || '' + path = "" + path << options.delete(:script_name).to_s.chomp("/") + path << options.delete(:path).to_s params = options[:params] || {} params.reject! {|k,v| v.to_param.nil? } diff --git a/actionpack/lib/action_dispatch/middleware/request_id.rb b/actionpack/lib/action_dispatch/middleware/request_id.rb index d5a0b80fd5..6fff94707c 100644 --- a/actionpack/lib/action_dispatch/middleware/request_id.rb +++ b/actionpack/lib/action_dispatch/middleware/request_id.rb @@ -19,10 +19,7 @@ module ActionDispatch def call(env) env["action_dispatch.request_id"] = external_request_id(env) || internal_request_id - status, headers, body = @app.call(env) - - headers["X-Request-Id"] = env["action_dispatch.request_id"] - [ status, headers, body ] + @app.call(env).tap { |status, headers, body| headers["X-Request-Id"] = env["action_dispatch.request_id"] } end private diff --git a/actionpack/lib/action_dispatch/middleware/session/cache_store.rb b/actionpack/lib/action_dispatch/middleware/session/cache_store.rb index d3b6fd12fa..1db6194271 100644 --- a/actionpack/lib/action_dispatch/middleware/session/cache_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/cache_store.rb @@ -1,5 +1,4 @@ require 'action_dispatch/middleware/session/abstract_store' -require 'rack/session/memcache' module ActionDispatch module Session diff --git a/actionpack/lib/action_dispatch/railtie.rb b/actionpack/lib/action_dispatch/railtie.rb index 35f901c575..62f906219c 100644 --- a/actionpack/lib/action_dispatch/railtie.rb +++ b/actionpack/lib/action_dispatch/railtie.rb @@ -16,7 +16,7 @@ module ActionDispatch config.action_dispatch.rack_cache = { :metastore => "rails:/", :entitystore => "rails:/", - :verbose => true + :verbose => false } initializer "action_dispatch.configure" do |app| diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index 02a27110e4..80fcdab643 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -446,7 +446,11 @@ module ActionDispatch _route = @set.named_routes.routes[name.to_sym] _routes = @set app.routes.define_mounted_helper(name) - app.routes.class_eval do + app.routes.singleton_class.class_eval do + define_method :mounted? do + true + end + define_method :_generate_prefix do |options| prefix_options = options.slice(*_route.segment_keys) # we must actually delete prefix segment keys to avoid passing them to next url_for diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb index 57c6972078..30e9e5634b 100644 --- a/actionpack/lib/action_dispatch/routing/route_set.rb +++ b/actionpack/lib/action_dispatch/routing/route_set.rb @@ -191,14 +191,50 @@ module ActionDispatch selector = url_helper_name(name, kind) hash_access_method = hash_access_name(name, kind) - @module.module_eval <<-END_EVAL, __FILE__, __LINE__ + 1 - remove_possible_method :#{selector} - def #{selector}(*args) - url_for(#{hash_access_method}(*args)) - end - END_EVAL + if optimize_helper?(route) + @module.module_eval <<-END_EVAL, __FILE__, __LINE__ + 1 + remove_possible_method :#{selector} + def #{selector}(*args) + if args.size == #{route.required_parts.size} && !args.last.is_a?(Hash) && optimize_routes_generation? + options = #{options.inspect}.merge!(url_options) + options[:path] = "#{optimized_helper(route)}" + ActionDispatch::Http::URL.url_for(options) + else + url_for(#{hash_access_method}(*args)) + end + end + END_EVAL + else + @module.module_eval <<-END_EVAL, __FILE__, __LINE__ + 1 + remove_possible_method :#{selector} + def #{selector}(*args) + url_for(#{hash_access_method}(*args)) + end + END_EVAL + end + helpers << selector end + + # Clause check about when we need to generate an optimized helper. + def optimize_helper?(route) #:nodoc: + route.ast.grep(Journey::Nodes::Star).empty? && route.requirements.except(:controller, :action).empty? + end + + # Generates the interpolation to be used in the optimized helper. + def optimized_helper(route) + string_route = route.ast.to_s + + while string_route.gsub!(/\([^\)]*\)/, "") + true + end + + route.required_parts.each_with_index do |part, i| + string_route.gsub!(part.inspect, "\#{Journey::Router::Utils.escape_fragment(args[#{i}].to_param)}") + end + + string_route + end end attr_accessor :formatter, :set, :named_routes, :default_scope, :router @@ -323,7 +359,7 @@ module ActionDispatch # Rails.application.routes.url_helpers.url_for(args) @_routes = routes class << self - delegate :url_for, :to => '@_routes' + delegate :url_for, :optimize_routes_generation?, :to => '@_routes' end # Make named_routes available in the module singleton @@ -557,6 +593,14 @@ module ActionDispatch RESERVED_OPTIONS = [:host, :protocol, :port, :subdomain, :domain, :tld_length, :trailing_slash, :anchor, :params, :only_path, :script_name] + def mounted? + false + end + + def optimize_routes_generation? + !mounted? && default_url_options.empty? + end + def _generate_prefix(options = {}) nil end @@ -568,19 +612,17 @@ module ActionDispatch user, password = extract_authentication(options) path_segments = options.delete(:_path_segments) - script_name = options.delete(:script_name) - - path = (script_name.blank? ? _generate_prefix(options) : script_name.chomp('/')).to_s + script_name = options.delete(:script_name).presence || _generate_prefix(options) path_options = options.except(*RESERVED_OPTIONS) path_options = yield(path_options) if block_given? - path_addition, params = generate(path_options, path_segments || {}) - path << path_addition + path, params = generate(path_options, path_segments || {}) params.merge!(options[:params] || {}) ActionDispatch::Http::URL.url_for(options.merge!({ :path => path, + :script_name => script_name, :params => params, :user => user, :password => password @@ -594,6 +636,7 @@ module ActionDispatch def recognize_path(path, environment = {}) method = (environment[:method] || "GET").to_s.upcase path = Journey::Router::Utils.normalize_path(path) unless path =~ %r{://} + extras = environment[:extras] || {} begin env = Rack::MockRequest.env_for(path, {:method => method}) @@ -603,6 +646,7 @@ module ActionDispatch req = @request_class.new(env) @router.recognize(req) do |route, matches, params| + params.merge!(extras) params.each do |key, value| if value.is_a?(String) value = value.dup.force_encoding(Encoding::BINARY) diff --git a/actionpack/lib/action_dispatch/routing/url_for.rb b/actionpack/lib/action_dispatch/routing/url_for.rb index ee6616c5d3..94db36ce1f 100644 --- a/actionpack/lib/action_dispatch/routing/url_for.rb +++ b/actionpack/lib/action_dispatch/routing/url_for.rb @@ -102,6 +102,9 @@ module ActionDispatch super end + # Hook overriden in controller to add request information + # with `default_url_options`. Application logic should not + # go into url_options. def url_options default_url_options end @@ -152,6 +155,11 @@ module ActionDispatch protected + def optimize_routes_generation? + return @_optimized_routes if defined?(@_optimized_routes) + @_optimized_routes = _routes.optimize_routes_generation? && default_url_options.empty? + end + def _with_routes(routes) old_routes, @_routes = @_routes, routes yield diff --git a/actionpack/lib/action_dispatch/testing/assertions/routing.rb b/actionpack/lib/action_dispatch/testing/assertions/routing.rb index 1552676fbb..1f4b905d18 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/routing.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/routing.rb @@ -39,10 +39,9 @@ module ActionDispatch # # Test a custom route # assert_recognizes({:controller => 'items', :action => 'show', :id => '1'}, 'view/item1') def assert_recognizes(expected_options, path, extras={}, message=nil) - request = recognized_request_for(path) + request = recognized_request_for(path, extras) expected_options = expected_options.clone - extras.each_key { |key| expected_options.delete key } unless extras.nil? expected_options.stringify_keys! @@ -181,7 +180,7 @@ module ActionDispatch private # Recognizes the route for a given path. - def recognized_request_for(path) + def recognized_request_for(path, extras = {}) if path.is_a?(Hash) method = path[:method] path = path[:path] @@ -209,7 +208,7 @@ module ActionDispatch request.request_method = method if method - params = @routes.recognize_path(path, { :method => method }) + params = @routes.recognize_path(path, { :method => method, :extras => extras }) request.path_parameters = params.with_indifferent_access request |