There's currently a bug in Safari, or more likely somewhere in the OS X HTTP API that breaks HTTP Authentication when there is a semicolon in the path part of the URL. This means it's impossible to use HTTP Authentication when you're building a RESTful Rails app that needs to work in Safari.
Right now this still seems to be broken in Leopard. It would be great if somebody who knows the right people inside Apple could try to raise awareness of this issue. It would be somewhat ironic if Leopard Server ships with Rails while this is still broken.
On 25/11/2006, at 6:35 AM, Thijs van der Vossen wrote:
> There's currently a bug in Safari, or more likely somewhere in the OS > X HTTP API that breaks HTTP Authentication when there is a semicolon > in the path part of the URL. This means it's impossible to use HTTP > Authentication when you're building a RESTful Rails app that needs to > work in Safari.
I stumbled across this in September, and it required this ugly, ugly work around: http://toolmantim.com/article/2006/9/19/ safari_urls_the_semi_colon_and_one_night_in_paris
Thanks for raising the issue properly and trying to get it addressed.
> On 25/11/2006, at 6:35 AM, Thijs van der Vossen wrote: >> There's currently a bug in Safari, or more likely somewhere in the OS >> X HTTP API that breaks HTTP Authentication when there is a semicolon >> in the path part of the URL. This means it's impossible to use HTTP >> Authentication when you're building a RESTful Rails app that needs to >> work in Safari.
> I stumbled across this in September, and it required this ugly, ugly > work around: > http://toolmantim.com/article/2006/9/19/ > safari_urls_the_semi_colon_and_one_night_in_paris
> Thanks for raising the issue properly and trying to get it addressed.
Great idea to try escaping the semicolon! For those interested, you can work around this issue by adding the following to your ApplicationController in app/controllers/ application.rb:
# make HTTP Authentication work on Safari for RESTful Rails alias_method :orig_url_for, :url_for def url_for(options = {}, *parameters_for_method_reference) result = orig_url_for(options, parameters_for_method_reference) if request.env['HTTP_USER_AGENT'].to_s.include? 'AppleWebKit' result.is_a?(String) ? result.gsub(';', '%3B') : result else result end end
> On Nov 25, 2006, at 12:01 AM, Tim Lucas wrote: >> On 25/11/2006, at 6:35 AM, Thijs van der Vossen wrote: >>> There's currently a bug in Safari, or more likely somewhere in >>> the OS >>> X HTTP API that breaks HTTP Authentication when there is a semicolon >>> in the path part of the URL. This means it's impossible to use HTTP >>> Authentication when you're building a RESTful Rails app that >>> needs to >>> work in Safari.
>> I stumbled across this in September, and it required this ugly, ugly >> work around: >> http://toolmantim.com/article/2006/9/19/ >> safari_urls_the_semi_colon_and_one_night_in_paris
>> Thanks for raising the issue properly and trying to get it addressed.
> Great idea to try escaping the semicolon! > For those interested, you can work around this issue by adding the > following to your ApplicationController in app/controllers/ > application.rb:
> # make HTTP Authentication work on Safari for RESTful Rails > alias_method :orig_url_for, :url_for > def url_for(options = {}, *parameters_for_method_reference) > result = orig_url_for(options, parameters_for_method_reference) > if request.env['HTTP_USER_AGENT'].to_s.include? 'AppleWebKit' > result.is_a?(String) ? result.gsub(';', '%3B') : result > else > result > end > end
Very nice, Thijs. A minor nitpick, and nothing to do with the actual solution: when overriding a method in a subclass, you can just call 'super' to get at the original. You don't actually need to alias the original. The alias trick is only needed when you are altering a method of the current class. For instance, if you were monkeypatching a new url_for implementation into ActionController::Base itself, you'd need to use alias there to preserve the original url_for.
> On Nov 25, 2006, at 12:01 AM, Tim Lucas wrote: >> On 25/11/2006, at 6:35 AM, Thijs van der Vossen wrote: >>> There's currently a bug in Safari, or more likely somewhere in >>> the OS >>> X HTTP API that breaks HTTP Authentication when there is a semicolon >>> in the path part of the URL. This means it's impossible to use HTTP >>> Authentication when you're building a RESTful Rails app that >>> needs to >>> work in Safari.
>> I stumbled across this in September, and it required this ugly, ugly >> work around: >> http://toolmantim.com/article/2006/9/19/ >> safari_urls_the_semi_colon_and_one_night_in_paris
>> Thanks for raising the issue properly and trying to get it addressed.
> Great idea to try escaping the semicolon! > For those interested, you can work around this issue by adding the > following to your ApplicationController in app/controllers/ > application.rb:
> # make HTTP Authentication work on Safari for RESTful Rails > alias_method :orig_url_for, :url_for > def url_for(options = {}, *parameters_for_method_reference) > result = orig_url_for(options, parameters_for_method_reference) > if request.env['HTTP_USER_AGENT'].to_s.include? 'AppleWebKit' > result.is_a?(String) ? result.gsub(';', '%3B') : result > else > result > end > end
> On Nov 29, 2006, at 6:09 AM, Thijs van der Vossen wrote: >> On Nov 25, 2006, at 12:01 AM, Tim Lucas wrote: >> Great idea to try escaping the semicolon! >> For those interested, you can work around this issue by adding the >> following to your ApplicationController in app/controllers/ >> application.rb:
>> # make HTTP Authentication work on Safari for RESTful Rails >> alias_method :orig_url_for, :url_for >> def url_for(options = {}, *parameters_for_method_reference) >> result = orig_url_for(options, parameters_for_method_reference) >> if request.env['HTTP_USER_AGENT'].to_s.include? 'AppleWebKit' >> result.is_a?(String) ? result.gsub(';', '%3B') : result >> else >> result >> end >> end
> Very nice, Thijs. A minor nitpick, and nothing to do with the > actual solution: when overriding a method in a subclass, you can > just call 'super' to get at the original. You don't actually need > to alias the original. The alias trick is only needed when you are > altering a method of the current class. For instance, if you were > monkeypatching a new url_for implementation into > ActionController::Base itself, you'd need to use alias there to > preserve the original url_for.
At first I tried to call super as Tim did, but I ended up with an url without the ';edit' part while using the url helpers generated by ActionController::Resources.
I've looked into this again and it seems that I need to explicitly pass the parameters to super to make it work. Like this:
def url_for(options = {}, *parameters_for_method_reference) result = super(options, parameters_for_method_reference) if request.env['HTTP_USER_AGENT'].to_s.include? 'AppleWebKit' result.is_a?(String) ? result.gsub(';','%3B') : result else result end end
My understanding of super was that it passed the original method's parameters, but maybe not in this case.