如何在 Rails 中使用空格作为 '%20' 而不是 '+' 获取 url 的参数
How to get params for url with whitespace as '%20' instead of '+' in Rails
如果我有这个参数可以添加到 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
的情况下 return 带有“%20”的参数?
您尝试过使用 uri
吗?例如
require 'uri'
URI.escape('John Smith')
本例中的结果应该是John%20Smith
从其他 post 那里了解到 URI.escape 在技术上已被弃用。其中 h
代表散列,而 k
是散列中的键,试试这个:
params.keys.inject({}) {|h, k| h[k] = ERB::Util.url_encode(params[k]); h }
我建议只坚持使用 gsub
,或许可以用注释来解释这种行为的必要性。
虽然您 可以 使用 URI.escape
解决问题,但据说它已被弃用,因为它不完全符合 RFC 规范。 See here 写了一篇很棒的文章。
Hash#to_param
是Hash#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.escape
和 URI.escape
之间的区别。
怎么样
URI.encode 'John Smith'
# => John%20Smith
不是真的。
建议使用:your_params_hash.to_query.gsub("+", "%20")
扩展 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"
如果你想要一个没有上下文的字符串的文字百分比编码(例如 RFC 5987 encoding of something like a Content-Disposition
HTTP header's filename*=...
value) then use of URI.escape
/ URI.encode
(its alias) would have been correct. The core library documentation's suggested replacements 在这种情况下是错误的,因为它们不等价:
转换为+
,而不是%20
+
转换为 %2B
,而不是 +
一些关于此的帖子建议 gsub
将字符串改回原始字符串,但这要简单得多:
...切换源代码以查看其工作原理 - 它只是一个没有上下文的钝编码器。当您知道自己在做什么时,这 正是您有时想要的,所以希望它不会从标准库中删除或弃用。
如果我有时间,我打算向核心库文档提交一个补丁,其中列出了 三个(不是两个)可能的替代方案,并提供了有关何时使用的更多信息他们每个人。现在,从大量 Google 的点击率和大量 at-best 的误导性回答中可以清楚地看出,社区对现状感到非常困惑。
如果我有这个参数可以添加到 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
的情况下 return 带有“%20”的参数?
您尝试过使用 uri
吗?例如
require 'uri'
URI.escape('John Smith')
本例中的结果应该是John%20Smith
从其他 post 那里了解到 URI.escape 在技术上已被弃用。其中 h
代表散列,而 k
是散列中的键,试试这个:
params.keys.inject({}) {|h, k| h[k] = ERB::Util.url_encode(params[k]); h }
我建议只坚持使用 gsub
,或许可以用注释来解释这种行为的必要性。
虽然您 可以 使用 URI.escape
解决问题,但据说它已被弃用,因为它不完全符合 RFC 规范。 See here 写了一篇很棒的文章。
Hash#to_param
是Hash#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.escape
和 URI.escape
之间的区别。
怎么样
URI.encode 'John Smith'
# => John%20Smith
不是真的。
建议使用:your_params_hash.to_query.gsub("+", "%20")
扩展 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"
如果你想要一个没有上下文的字符串的文字百分比编码(例如 RFC 5987 encoding of something like a Content-Disposition
HTTP header's filename*=...
value) then use of URI.escape
/ URI.encode
(its alias) would have been correct. The core library documentation's suggested replacements 在这种情况下是错误的,因为它们不等价:
+
,而不是%20
+
转换为%2B
,而不是+
一些关于此的帖子建议 gsub
将字符串改回原始字符串,但这要简单得多:
...切换源代码以查看其工作原理 - 它只是一个没有上下文的钝编码器。当您知道自己在做什么时,这 正是您有时想要的,所以希望它不会从标准库中删除或弃用。
如果我有时间,我打算向核心库文档提交一个补丁,其中列出了 三个(不是两个)可能的替代方案,并提供了有关何时使用的更多信息他们每个人。现在,从大量 Google 的点击率和大量 at-best 的误导性回答中可以清楚地看出,社区对现状感到非常困惑。