java 避免使用 Spring 的 RestTemplate 对 URL 查询参数进行双重编码
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/34321361/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Avoid Double Encoding of URL query param with Spring's RestTemplate
提问by cscan
I'm trying to use Spring's RestTemplate::getForObject to make a request for a URL which has a URL query param.
我正在尝试使用 Spring 的 RestTemplate::getForObject 来请求具有 URL 查询参数的 URL。
I've tried:
我试过了:
- Using a string
- Creating a URI with URI::new
- Creating a URI with URI::create
- Using UriComponentsBuilder to build the URI
- 使用字符串
- 使用 URI::new 创建 URI
- 使用 URI::create 创建 URI
- 使用 UriComponentsBuilder 构建 URI
No matter which of these I use, encoding the url query param with URLEncoder::encode gets double encoded and using this encoding leaves the url query param unencoded.
无论我使用其中的哪一个,使用 URLEncoder::encode 对 url 查询参数进行编码都会得到双重编码,并且使用此编码会使 url 查询参数未编码。
How can I send this request without double encoding the URL? Here's the method:
如何在不对 URL 进行双重编码的情况下发送此请求?这是方法:
try {
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(detectUrl)
.queryParam("url", URLEncoder.encode(url, "UTF-8"))
.queryParam("api_key", "KEY")
.queryParam("api_secret", "SECRET");
URI uri = builder.build().toUri();
JSONObject jsonObject = restTemplate.getForObject(uri, JSONObject.class);
return jsonObject.getJSONArray("face").length() > 0;
} catch (JSONException | UnsupportedEncodingException e) {
e.printStackTrace();
}
Here's an example:
下面是一个例子:
Without URLEncoder:
没有 URLEncoder:
http://www.example.com/query?url=http://query.param/example&api_key=KEY&api_secret=SECRET
With URLEncoder:
使用 URLEncoder:
http://www.example.com/query?url=http%253A%252F%252Fquery.param%252Fexample&api_key=KEY&api_secret=SECRET
':' should be encoded as %3A and '/' should be encoded as %2F. This does happen - but then the % is encoded as %25.
':' 应编码为 %3A,而 '/' 应编码为 %2F。这确实发生了 - 但随后 % 被编码为 %25。
回答by Sotirios Delimanolis
A UriComponentsBuilder
is a builder for UriComponents
which
AUriComponentsBuilder
是一个建造者,UriComponents
其中
Represents an immutable collection of URI components, mapping component type to
String
values.
表示 URI 组件的不可变集合,将组件类型映射到
String
值。
The URI specificationdefines what characters are allowed in a URI. This answersummarizes the list to the characters
该URI规范定义了什么角色被允许在一个URI。这个答案总结了字符列表
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=
By those rules, your URI
根据这些规则,您的 URI
http://www.example.com/query?url=http://query.param/example&api_key=KEY&api_secret=SECRET
is perfectly valid and requires no additional encoding.
是完全有效的,不需要额外的编码。
The method URLEncoder#encode(String, String)
方法 URLEncoder#encode(String, String)
Translates a string into
application/x-www-form-urlencoded
format using a specific encoding scheme.
application/x-www-form-urlencoded
使用特定的编码方案将字符串转换为格式。
That is not the same thing. That process is defined here, and URLEncoder
(afaik) should be following it pretty closely.
那不是一回事。该过程在此处定义,并且URLEncoder
(afaik)应该非常密切地遵循它。
In your original code, using URLEncoder#encode
converted your input url
into
在您的原始代码中,使用URLEncoder#encode
将您的输入url
转换为
http%3A%2F%2Fquery.param%2Fexample
The character %
is invalid in a URI so must be encoded. That's what the UriComponents
object constructed by your UriComponentsBuilder
is doing.
该字符%
在 URI 中无效,因此必须进行编码。这就是你UriComponents
构造的对象UriComponentsBuilder
正在做的事情。
This is unnecessary since your URI is completely valid to begin with. Get rid of the use of URLEncoder
.
这是不必要的,因为您的 URI 一开始就完全有效。摆脱使用URLEncoder
.