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.

url_for :escape parameter is ignored

#4762

The rdoc for url_for in actionpack/lib/action_view/helpers/url_helper.rb states:

   url_for(:action => 'checkout', :anchor => 'tax&ship', :escape => false) 
   => /testing/jump/#tax&ship

http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.htm...

however anchors always get url escaped, the :escape parameter is completely ignored. Is this intended behaviour? It would be nice to make the escaping optional.

if it is intended behaviour the documentation should be updated.

Reported by Jan Berkel · June 3rd, 2010 @ 06:42 PM

State: open
Milestone: 3.0.6
Assigned to: Andrew White Andrew White
Importance: High

Activity

  1. Martin Gamsjaeger (snusnu)
    Martin Gamsjaeger (snusnu)

    While this maybe isn't the exact issue Jan encountered, I noticed something similar, where #content_tag_as_string completely ignores the escape param on the content. This leads to errors with the engineyard/rails_metrics plugin for example, and basically, for every call to #content_tag where the 2nd param is given as a String.

    Patch can be found at: http://github.com/snusnu/rails/commit/7f1b5bc6452cd1ca65dae3283c4af...

    I'll keep on looking if there's already another ticket for that specific issue, or maybe it's even the same issue as this ticket describes anyway. If not, I'll probably open another ticket and link it back to this one too

    June 3rd, 2010 @ 10:09 PM

  2. Jan Berkel
    Jan Berkel

    that issue is unrelated. the problem is in actionpack/lib/action_dispatch/routing/route_set.rb:

    
    # route_set.rb
    def url_for(options)
      ...
      rewritten_url << "##{Rack::Utils.escape(options[:anchor].to_param.to_s)}" if options[:anchor]
    end
    
    # actionpack/lib/action_view/helpers/url_helper.rb
    def url_for(option)
      ...
      escape  = options.key?(:escape) ? options.delete(:escape) : false
      super
    end
    

    So what happens is that while url_for in url_helper.rb accepts an escape option, it doesn't get passed through route_set.rb (the key is deleted).

    I could fix this but wanted to check first if it the desired behaviour, to me it looks like a bug.

    June 3rd, 2010 @ 10:33 PM

  3. Neeraj Singh
    Neeraj Singh

    The culprit is following code

    rewritten_url << "##{Rack::Utils.escape(options[:anchor].to_param.to_s)}" if options[:anchor]
    

    As you can see anchor tag is always escaped. And it does not depend on options that is passed to this method.

    http://github.com/rails/rails/blob/master/actionpack/lib/action_dis...

    I tried to look at HTTP RFC and could not find any reference that anchor tag should always be escaped. If no such reference is found then it should be considered a bug. The patch and test can be generated easily.

    June 4th, 2010 @ 01:04 AM

  4. Jan Berkel
    Jan Berkel

    @neeraj: anchor tags are not even sent to the server, they are purely local. it still makes sense to escape the anchor tag to produce valid urls, but the content is more free form than for example the query string, so it should be possible to have that part not escaped automatically.

    my concrete use case is google analytics tracking. there's an option to append tracking parameters to the anchor instead of having them as query parameters.

    http://example.com?utm_campaign=bar
    http://example.com/#utm_campaign=bar
    

    However if the content of the anchor gets escaped the tracking stops working.

    June 4th, 2010 @ 01:41 AM

  5. Neeraj Singh
    Neeraj Singh
    • Assigned user set to José Valim

    Assigning it to rails core team member to get a verdict on whether anchor value should be escaped or not?

    June 25th, 2010 @ 09:42 PM

  6. José Valim
    José Valim

    :anchor (as everything else on url_for) should respect the :escape parameter. Patches please! :)

    June 25th, 2010 @ 11:22 PM

  7. Andrew White
    Andrew White
    • Milestone cleared.
    • State changed from new to open

    The :escape option is only for HTML entity escaping and not URL escaping which is what's happening here. However there is a bug in that the :anchor is being over-escaped. The attached patch fixes this issue and you won't need to pass :escape => false to get your Google Analytics use case working.

    June 26th, 2010 @ 02:02 AM

  8. Repository
    Repository
    • State changed from open to resolved

    June 26th, 2010 @ 02:06 AM

  9. Jan Berkel
    Jan Berkel
    • Importance changed from to High

    thanks! i backported the fix to 2-3-stable. any chance this can be applied? we're not ready for 3.x yet.

    June 29th, 2010 @ 11:07 AM

  10. Santiago Pastorino
    Santiago Pastorino
    • Milestone set to 2.3.9
    • State changed from resolved to open

    June 29th, 2010 @ 06:35 PM

  11. Repository
  12. José Valim
    José Valim
    • State changed from open to committed

    June 30th, 2010 @ 12:27 PM

  13. Shayan Guha
    Shayan Guha

    From http://tools.ietf.org/html/rfc3986#section-3.5, "/" and "?" should also be considered "safe" characters for the anchor. The patch doesn't look like it handles those characters. Also it looks like '%' should not be allowed.

    November 4th, 2010 @ 09:55 PM

  14. Shayan Guha
    Shayan Guha

    This fix also needs to be applied to the rewrite_url function on the 2.3 branch. The :anchor option is still being escaped using CGI.escape. https://github.com/rails/rails/blob/v2.3.10/actionpack/lib/action_c...

    November 4th, 2010 @ 11:15 PM

  15. iGEL
    iGEL

    I agree with Shayan: / and ? shouldn't be escaped. I would like to use URLs like www.server.com/controller/action#tab=controller/action, but Rails 3.0.3 escapes the /. Any chance to reopen this ticket?

    February 16th, 2011 @ 04:17 PM

  16. Santiago Pastorino
    Santiago Pastorino

    is this an issue in 3-0-stable and/or master?

    February 16th, 2011 @ 04:32 PM

  17. Andrew White
    Andrew White

    It's an issue in 2-3-stable, 3-0-stable and master. 3-0-stable and master use Rack::Mount::Utils.escape_uri which doesn't have '/' and '?' in the list since those need escaping for routes. 2-3-stable uses URI.escape directly which Rack::Mount::Util.escape_uri does as well, so we might as well use URI.escape directly in 3-0-stable and master.

    February 16th, 2011 @ 04:43 PM

  18. Santiago Pastorino
    Santiago Pastorino
    • State changed from committed to open
    • Milestone changed from 2.3.9 to 3.0.5

    February 16th, 2011 @ 04:55 PM

  19. iGEL
    iGEL

    Thank you. It's an issue on 3-0-stable and master. I've modified the tests, so it fails, if / or ? are escaped, but I don't dare to write a patch.

    February 16th, 2011 @ 05:36 PM

  20. iGEL
    iGEL

    Well, I dared after all, and put Andrews suggestion into a patch. Hope, everything is alright the way I did it.

    February 16th, 2011 @ 06:41 PM

  21. Andrew White
    Andrew White

    You need to double check the unsafe char list you are escaping - the default for URI.escape is UNSAFE, which includes anything not in the UNRESERVED and RESERVED list. The spec says it should be PCHAR + '/?' - this means #,[ & ] should be escaped but the default URI.escape doesn't encode them.

    February 16th, 2011 @ 09:32 PM

  22. Santiago Pastorino
    Santiago Pastorino

    Hey Andrew, can I leave the ticket for you to push when you think the fix is ready?

    February 17th, 2011 @ 01:29 AM

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

    Sure, I'll handle it.

    February 17th, 2011 @ 05:35 AM

  24. Santiago Pastorino
    Santiago Pastorino
    • Milestone changed from 3.0.5 to 3.0.6

    February 27th, 2011 @ 03:15 AM