rails: `request.url` does not take `relative_url_root` into account

The URL returned by request.url ignores the value of Rails.config.action_controller.relative_url_root.

The documentation of ActionDisplay::HTTP:URL#url says that it “Returns the complete URL used for this request”. This is not true for projects that are not mounted under /.

This means that projects that use request.url cannot work unmodified when mounted under other directories with RAILS_RELATIVE_URL_ROOT.

Steps to reproduce

  1. Create a minimal Rails application with the model “Foo”.

  2. In app/view/foo/index.html.erb write

    request.url = <%= request.url %>
    relative_url = <%= controller.relative_url_root %>
    
  3. Setup Apache

    RewriteRule      ^/bar(.*)$  http://localhost:4000/$1  [P,L]
    ProxyPassReverse  /bar       http://localhost:4000/
    
  4. Launch the Rails application

    RAILS_RELATIVE_URL_ROOT=/bar bundle exec bin/rails -p 4000
    
  5. Visit http://localhost/bar/foo

Expected behavior

The page should display

request.url = http://localhost/bar/foo
relative_url = /bar

Actual behavior

The page displays

request.url = http://localhost/foo
relative_url = /bar

Please note the missing /bar in request.url.

System configuration

Rails version: 4.2.5

Ruby version: 2.2.3

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 6
  • Comments: 18 (9 by maintainers)

Most upvoted comments

This is still an issue in Rails 6 as well. It would be very nice if this could get fixed.

This is still an issue in Rails 5.1.6. Any plans to tackle it?

@nicolrx it is not closed.

Is there a workaround that can help with patching this?

A change that could solve this problem (while being less intrusive than #24396) is to

  1. Generate a default config.ru that takes relative_url_root into account (PR #24412):

    -run Rails.application
    +map Rails.application.config.relative_url_root || '/' do
    +  run Rails.application
    +end
    
  2. Document that the RAILS_RELATIVE_URL_ROOT variable must be set to the same value of SCRIPT_NAME (and maybe complain if the two differ).