# url\_for always escape string.

**URL:** <https://discuss.rubyonrails.org/t/url-for-always-escape-string/1203>\
**Category:** rubyonrails-core\
**Created:** [September 7, 2006, 2:02am UTC](https://discuss.rubyonrails.org/t/url-for-always-escape-string/1203 "2006-09-07T02:02:34Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Mathieu\_Jobin](https://sea2.discourse-cdn.com/rubyonrails/user_avatar/discuss.rubyonrails.org/mathieu_jobin/32/5180_2.png) [@Mathieu\_Jobin](https://discuss.rubyonrails.org/u/Mathieu_Jobin)\
**Post date:** [September 7, 2006, 2:02am UTC](https://discuss.rubyonrails.org/t/url-for-always-escape-string/1203/1 "2006-09-07T02:02:34Z")

</div>

according to the documentation, only the url\_for from ActionView escape the URL. which happens on this line

escape ? html\_escape(url) : url

and can be prevented by passing :escape =\> false to url\_for. still according to the documentation, the url\_for from ActionController is not supposed to escape the url.

BUT IT DOES.

at the moment of this line

escape ? html\_escape(url) : url

url has already been escaped by the url\_for from action\_controller thus the option :escape is irrelevant.

I believe someone change something without knowing this.

the url\_for from the controller is not suppose to escape the url while it does. and the :escape =\> false just prevent the url from being escaped AGAIN.

I went a bit into the code, as far as Routing::Routes.generate so it get escaped somewhere in there. That's as far as I check

regards,

---

<div class="post-metadata">

**Author:** ![Chris\_Mear1](https://avatars.discourse-cdn.com/v4/letter/c/e19b73/32.png) [@Chris\_Mear1](https://discuss.rubyonrails.org/u/Chris_Mear1)\
**Post date:** [September 7, 2006, 7:02am UTC](https://discuss.rubyonrails.org/t/url-for-always-escape-string/1203/2 "2006-09-07T07:02:28Z")

</div>

somekool wrote:

> according to the documentation, only the url\_for from ActionView escape the URL.

\<snip\>

> still according to the documentation, the url\_for from ActionController is not supposed to escape the url. BUT IT DOES.

Where have you seen the double-escaping behaviour? I've found some problems with some of the form-related helpers where URLs are double-escaped, but the problem is in the helpers, not in ActionController's url\_for.

Can you give us some example code that shows this escaping happening?

Chris

---

<div class="post-metadata">

**Author:** ![Mathieu\_Jobin](https://sea2.discourse-cdn.com/rubyonrails/user_avatar/discuss.rubyonrails.org/mathieu_jobin/32/5180_2.png) [@Mathieu\_Jobin](https://discuss.rubyonrails.org/u/Mathieu_Jobin)\
**Post date:** [September 7, 2006, 11:55am UTC](https://discuss.rubyonrails.org/t/url-for-always-escape-string/1203/3 "2006-09-07T11:55:25Z")

</div>

Lets clarify what I said. The url is escaped twice, but the output is the same.

it changes a quote for example into %xx but the second time, it remains %xx unchanged, cuz its ok

lets look at the function

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def url\_for(options = {}, \*parameters\_for\_method\_reference) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if options.kind\_of? Hash &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;options = { :only\_path =\> true }.update(options.symbolize\_keys) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;escape = options.key?(:escape) ? options.delete(:escape) : true &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;escape = true &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;url = @controller.send(:url\_for, options, \*parameters\_for\_method\_reference) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;escape ? html\_escape(url) : url &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end

most of this function is related to check if :escape =\> false is passed, in which case html\_escape won't be call. but before this last line, url already been escaped. so its not possible to prevent url\_for from escaping the URL anymore. and at this point. providing this option does nothing

but the value returned by html\_escape will be the same as the value url already has. so it does not get really escaped twice. but the string is going into the machine twice, if you see what I mean.

---

<div class="post-metadata">

**Author:** ![Chris\_Mear1](https://avatars.discourse-cdn.com/v4/letter/c/e19b73/32.png) [@Chris\_Mear1](https://discuss.rubyonrails.org/u/Chris_Mear1)\
**Post date:** [September 7, 2006, 3:09pm UTC](https://discuss.rubyonrails.org/t/url-for-always-escape-string/1203/4 "2006-09-07T15:09:16Z")

</div>

somekool wrote:

> it changes a quote for example into %xx but the second time, it remains %xx unchanged, cuz its ok

I think this is where the confusion is arising. There are two different kinds of escaping going on.

It sounds like you're talking about the URL encoding that uses '%xx' to represent special characters.

However, the html\_escape function does something completely different. It takes a string and turns '&' into '&amp;' and '\<' into '&lt;', etc., so that it can go into HTML without being interpreted as literal '&'s and '\<'s.

Escaping special characters in URLs using the '%xx' scheme is mandatory, otherwise they are not valid URLs.

But HTML-escaping using '&' can be turned off using the :escape =\> false option. Of course, you always want to HTML-escape the URL at some point before outputting it in HTML. And most of the time it's okay to let url\_for do this for you. But sometimes you need to take the result of url\_for and pass it through another function that does its own HTML-escaping. That's when you can make use of the :escape =\> false option to url\_for.

Chris

---

<div class="post-metadata">

**Author:** ![Mathieu\_Jobin](https://sea2.discourse-cdn.com/rubyonrails/user_avatar/discuss.rubyonrails.org/mathieu_jobin/32/5180_2.png) [@Mathieu\_Jobin](https://discuss.rubyonrails.org/u/Mathieu_Jobin)\
**Post date:** [September 7, 2006, 11:25pm UTC](https://discuss.rubyonrails.org/t/url-for-always-escape-string/1203/5 "2006-09-07T23:25:55Z")

</div>

thank you for the enlightenment, it does clarify bunch of things

the reason I need the URL encoding not to be done, is because I pass the url\_for results to javascript code, and some part of the url is javascript that gets evaluated to then become a valid URI.

so I decided to do something like this url\_for(:action =\> 'foo', :id =\> '\_\_js\_\_').gsub('\_\_js\_\_', js)

which works like I want, but I thought I could just pass an option to url\_for instead of the gsub
