【问题标题】:How to get params for url with whitespace as '%20' instead of '+' in Rails如何在Rails中使用空格作为'%20'而不是'+'获取url的参数
【发布时间】:2016-07-13 13:56:45
【问题描述】:

如果我有添加到 URL 的参数

params = { name: 'John Key' }

并使用方法to_param:

params.to_param
 => "name=John+Key"

关键是使用的服务没有正确读取'+',需要'%20'而不是name=John%20Key:When to encode space to plus (+) or %20?

有没有办法在不使用 gsub 的情况下返回带有 '%20' 的参数?

【问题讨论】:

  • 您误读了所链接问题的答案。在 query 中,加号完全有效,被视为空格,因此不存在这样的冗余 Rails 助手。
  • 我需要 typeform url 的参数。它不能很好地处理'+',但它可以处理'%20'

标签: ruby-on-rails ruby url-encoding


【解决方案1】:

我会建议坚持使用gsub,或许还可以加上注释来解释这种行为的必要性。

虽然您可以通过使用URI.escape 解决问题,但据说它已被弃用,因为它不完全符合 RFC 规范。 See here 写了一篇精彩的文章。

Hash#to_paramHash#to_query 的别名,它调用Object#to_query。演示 +%20 问题的最简单示例是:

'John Key'.to_query(:name) # => "name=John+Key"

Object#to_query的实现是:

def to_query(key)
  "#{CGI.escape(key.to_param)}=#{CGI.escape(to_param.to_s)}"
end

因此,我们发现:

CGI.escape("John Key") # => "John+Key"

因此,这就是我引用CGI.escapeURI.escape 之间差异的原因。

【讨论】:

    【解决方案2】:

    怎么样

    URI.encode 'John Smith'
    # => John%20Smith
    

    【讨论】:

      【解决方案3】:

      不是真的。

      建议使用:your_params_hash.to_query.gsub("+", "%20")

      【讨论】:

        【解决方案4】:

        您是否尝试过使用uri?例如

        require 'uri' URI.escape('John Smith')

        本例中的结果应该是John%20Smith

        从其他帖子中了解到 URI.escape 在技术上已被弃用。其中h代表hash,k是hash中的key,试试这个:

        params.keys.inject({}) {|h, k| h[k] = ERB::Util.url_encode(params[k]); h }

        【讨论】:

        • 是的,它适用于参数的值。但在这种情况下,我想获得一组带有 '%20' 的参数。类似于 to_param 方法,但不返回带有 '+' 的空格 name=John%20Key
        【解决方案5】:

        扩展 Julie 的答案以实现编码值的字符串而不是哈希。

        随着URI.encode 的贬值,可以使用ERB::Util.url_encode 实现此目的,但是您只需编码键和值对,而不是完整参数,然后将它们连接在一起。


        params = { name: 'John Key' }
        
        # not what we want
        ERB::Util.url_encode(params) # => "%7B%3Aname%3D%3E%22John%20Key%22%7D"
        

        这里有一个(相当长的)命令可以工作:

        # Construct a new object (a string here) and build our params into it correctly.
        # k = key of hash. 
        # v = value of hash. 
        # a = array created in each_with_object.
        
        params.each_with_object([]) { |(k, v), a| a << [ERB::Util.url_encode(k), ERB::Util.url_encode(v)].join('=') }.join('&')
        
        # => "name=John%20Key"
        

        更多参数:

        params = { name: 'John Key', occupation: 'Web Developer!', 'Bad Key' => 'but works' }
        
        params.each_with_object([]) { |(k, v), a| a << [ERB::Util.url_encode(k), ERB::Util.url_encode(v)].join('=') }.join('&')
        
        # => "name=John%20Key&occupation=Web%20Developer%21&Bad%20Key=but%20works"
        

        与 Hash.to_query 相比

        params.to_query
        
        # => "Bad+Key=but+works&name=John+Key&occupation=Web+Developer%21"
        

        【讨论】:

          【解决方案6】:

          如果您想要在没有上下文的情况下对字符串进行文字百分比编码(例如,对于RFC 5987 编码类似Content-Disposition HTTP 标头的filename*=... 值)然后使用URI.escape / URI.encode(它的别名)本来是正确的。在这种情况下,core library documentation's suggested replacements 错了,因为它们不等价:

          • 转换为 +,而不是 %20
          • + 转换为 %2B,而不是保留为 +

          一些关于此的帖子建议使用gsub 将字符串改回原来的位置,但这要简单得多:

          ...切换源代码以查看它是如何工作的——它只是一个没有上下文的钝编码器。当您知道自己在做什么时,这正是您有时想要的,所以我们希望它不会从标准库中删除或弃用。

          如果我有时间我打算向核心库文档提交一个补丁,其中列出了三个(不是两个)可能的替代方案,并提供了有关何时使用它们的更多信息。目前,从 Google 的大量点击以及大量的误导性答案中可以清楚地看出,社区对现状感到非常困惑。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-05-04
            • 1970-01-01
            • 1970-01-01
            • 2015-01-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多