Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

There was a problem

This project is archived and is in readonly mode.

Routing bug when using :constraints

#5157

When matching a request fails due to a constraints proc, the next routes gets params with names as in the failing previous routing rule
Steps to recreate are below

rails new routing_bug -O --edge
cd routing_bug
rails g controller home
rm public/index.html

## edit config/routes.rb to the following
RoutingBug::Application.routes.draw do
  scope "/:country", :constraints => Proc.new { |req| %w[all France Italy Spain].include?(req.symbolized_path_parameters[:country]) } do
    match "/",       :to => "home#index"
    match "/cities", :to => "home#cities"
  end

  match '/:invalid_country(/*other)', :to => redirect { |params, req|
    Rails.logger.warn("~~~~ " + params.inspect)
    # "/all" + params[:other]
    "/all"
  }
end

## Edit app/controllers/home_controller.rb to the following
class HomeController < ApplicationController
  def index
    render :text => params.inspect
  end
  def cities
    render :text => params.inspect
  end
end

$ curl -I localhost:3000/France HTTP/1.1 200 OK
Etag: "e85a20831b64f267c5f41eef6356c95b"
Connection: Keep-Alive
Content-Type: text/html; charset=utf-8
Date: Tue, 20 Jul 2010 09:09:38 GMT
Server: WEBrick/1.3.1 (Ruby/1.8.7/2009-06-12)
X-Runtime: 0.012149
Content-Length: 0
Cache-Control: max-age=0, private, must-revalidate

$ curl -I localhost:3000/Germany HTTP/1.1 301 Moved Permanently
Location: http://localhost:3000/all
Connection: Keep-Alive
Content-Type: text/html
Date: Tue, 20 Jul 2010 09:09:45 GMT
Server: WEBrick/1.3.1 (Ruby/1.8.7/2009-06-12)
X-Runtime: 0.000981
Content-Length: 17

But I would get this in the log
~~~~ {:controller=>"home", :action=>"index", :country=>"Germany"} The behavior I'm trying to achieve is to redirect the users to /all/REST_OF_URL whenever they go to an invalid country
I hacked around it by playing with req.path

Reported by Fouad Mardini · July 20th, 2010 @ 10:25 AM

State: resolved
Milestone: 3.0.2
Assigned to: José Valim José Valim
Importance: High

Activity

  1. Fouad Mardini
    Fouad Mardini
    • No changes were found…

    July 20th, 2010 @ 10:26 AM

  2. Andrew White
    Andrew White
    • Milestone cleared.
    • State changed from new to open
    • Assigned user set to Andrew White
    • Tag set to rails 3.0, parameters, routing
    • Importance changed from to High

    What's happening is that the symbolized path parameters are getting cached in the rack environment hash so when you use them in your redirect you get the params from the first route that matches. As a workaround the routes below do what you want them to do.

    RoutingBug::Application.routes.draw do
      scope "/:country", :country => /all|France|Italy|Spain/ do
        match "/",       :to => "home#index"
        match "/cities", :to => "home#cities"
      end
    
      match '/:invalid_country', :to => redirect("/all")
      match '/:invalid_country/cities', :to => redirect("/all/cities")
    end
    

    The string key path parameters hash is correct so you could use that.

    August 20th, 2010 @ 07:42 AM

  3. Fouad Mardini
    Fouad Mardini

    Thanks Andrew! Unfortunately, my logic is a bit more involved and the regexp won't do

    August 21st, 2010 @ 03:27 PM

  4. Andrew White
    Andrew White
    • Assigned user changed from Andrew White to José Valim

    Attached patch fixes the issue by caching the symbolized path parameters in the request object rather than the environment hash.

    August 22nd, 2010 @ 06:58 PM

  5. Repository
    Repository
    • State changed from open to resolved

    (from [ae2c60734a0f71593709608710a0c7507bb8699e]) Cache the symbolized path parameters using a instance variable in the request object rather than the environment hash. This it to prevent stale parameters in later routing constraints/redirects as only the normal path parameters are set by Rack::Mount.

    Also if a constraint proc arity is more than one, pass the symbolized path parameters
    as the first argument to match redirect proc args and provide easier access.

    [#5157 state:resolved]

    Signed-off-by: José Valim jose.valim@gmail.com
    http://github.com/rails/rails/commit/ae2c60734a0f71593709608710a0c7...

    August 22nd, 2010 @ 08:17 PM

  6. Repository
    Repository

    (from [df0a7bfb8fa3f0255fe4ab082863f27c43c278d9]) Cache the symbolized path parameters using a instance variable in the request object rather than the environment hash. This it to prevent stale parameters in later routing constraints/redirects as only the normal path parameters are set by Rack::Mount.

    Also if a constraint proc arity is more than one, pass the symbolized path parameters
    as the first argument to match redirect proc args and provide easier access.

    [#5157 state:resolved]

    Signed-off-by: José Valim jose.valim@gmail.com
    http://github.com/rails/rails/commit/df0a7bfb8fa3f0255fe4ab082863f2...

    August 22nd, 2010 @ 08:18 PM

  7. Jeremy Kemper