避免使用Spring的RESTTemplate对URL查询参数进行双重编码

2022-09-04 21:07:34

我正在尝试使用Spring的RestTemplate::getForObject来请求具有URL查询参数的URL。

我试过了:

  • 使用字符串
  • 使用 URI 创建 URI::new
  • 使用 URI 创建 URI::创建
  • 使用 UriComponentsBuilder 构建 URI

无论我使用哪一个,使用URLEncoder::encode对url查询参数进行编码都会进行双重编码,并且使用此编码会使url查询参数保持未编码状态。

如何在不对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();
}

下面是一个示例:

没有URLEncoder:

http://www.example.com/query?url=http://query.param/example&api_key=KEY&api_secret=SECRET

使用 URLEncoder:

http://www.example.com/query?url=http%253A%252F%252Fquery.param%252Fexample&api_key=KEY&api_secret=SECRET

“:”应编码为 %3A,“/”应编码为 %2F。这确实会发生 - 但随后 % 被编码为 %25。


答案 1

A 是其构建器UriComponentsBuilderUriComponents

表示 URI 组件的不可变集合,将组件类型映射到值。String

URI 规范定义了 URI 中允许使用的字符。这个答案总结了角色的列表

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~:/?#[]@!$&'()*+,;=

根据这些规则,您的 URI

http://www.example.com/query?url=http://query.param/example&api_key=KEY&api_secret=SECRET

是完全有效的,不需要额外的编码。

方法 URLEncoder#encode(String, String)

使用特定编码方案将字符串转换为格式。application/x-www-form-urlencoded

这不是一回事。该过程在这里定义,并且(afaik)应该非常密切地遵循它。URLEncoder

在原始代码中,使用转换后的输入URLEncoder#encodeurl

http%3A%2F%2Fquery.param%2Fexample

该字符在 URI 中无效,因此必须进行编码。这就是你构建的对象正在做的事情。%UriComponentsUriComponentsBuilder

这是不必要的,因为您的 URI 从一开始就是完全有效的。摆脱使用 .URLEncoder


答案 2

推荐