url_for之疑问
在控制器中,我们经常要实现这样的功能:如果未登录时访问action A,则该过滤器自动将请求重定向到登录页,登录之后将参数原封不动地再传递给action A。可以使用下列代码简单地实现这个重定向:
1 | redirect_to :controller => '/accounts/login', :continue => url_for(params) |
其中continue参数表示,登录之后需要回调的地址。
但有这样的一种情况:如果需要点击某个链接而不是直接重定向去登录,登录后再通过continue值将原参数返回到原始action中。用上面方法实现时,你就会发现参数传递错误,如下面的实现方式都是错误的:
1 2 3 4 5 | 参数会被截断: <a href="<%="#{home}/signin?f=1&continue=#{url_for(params)}"%>">example</a> 参数传递错误,在浏览器地址栏中会出现诸如&continue=xxx <a href="<%="#{home}/signin?continue=#{URI.encode(url_for(params), /[&:\/]/)}"%>">example</a> |
查看了生成链接的源代码,发现url_for(params)生成的链接会将url中参数的连接符&转成&符号,而正确的转换应是%26。因此在使用encode编码url_for字符串之前,需要先转换url中的HTML实体:
1 2 3 4 5 6 7 8 9 10 11 | # 在irb中转换字符串的HTML实体示例 require 'cgi' require "erb" include ERB::Util str='a=1&b=2' str1 = CGI.unescapeHTML(str) # output:a=1&b=2 str2 = ERB::Util.html_escape(str1) #output:a=1&b=2 CGI.unescapeHTML '&' # 输出 & CGI.unescapeHTML '&' # 输出 & |
因此,最终实现如下:
1 2 3 4 5 | <% continue = "#{@config['home']}#{CGI.unescapeHTML(url_for(params))}" # 关键 continue = URI.encode(continue, /[&:\/]/) %> <a href="<%="#{home}/signin?f=1&continue=#{continue}"%>">example</a> |
还有要注意的是,在action中使用params[:continue]时不需要再用URI.deconde解码了,rails会自动转换%26为&符号。
使用Escape, Unescape, Encode, Decode, HTML, XML, URI, URL的例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | require 'cgi' # escape name = "ruby?" value = "yes" url = "http://example.com/?" + CGI.escape(name) + '=' + CGI.escape(value) + "&var=T" # url: http://example.com/?ruby%3F=yes&var=T html = %(<a href="#{CGI.escapeHTML(url)}">example</a>) # html: <a href="http://example.com/?ruby%3F=yes&var=T">example</a> # unescape name_encoded = html.match(/http:([^"]+)/)[0] # name_encoded: http://example.com/?ruby%3F=yes&var=T href = CGI.unescapeHTML(name_encoded) # href: http://example.com/?ruby%3F=yes&var=T query = href.match(/\?(.*)$/)[1] # query: ruby%3F=yes&var=T pairs = query.split('&') # pairs: ["ruby%3F=yes", "var=T"] name, value = pairs[0].split('=').map{|v| CGI.unescape(v)} # name, value: ["ruby?", "yes"] |
Monitor Your Web Site 24/7 - Receive email and SMS alerts anytime your web site goes down.
