Java开发笔记之%被转码为%25导致url无法请求

0x00 概述

在使用RestTemplate(import org.springframework.web.client.RestTemplate)进行开发时候发现,

拼装好的url请求在经过RestTemplate发送HTTP请求时候,url会被再次经行UrlEncode编码,导致已经拼装好的url内多出很多%25。

参考此RestTemplate经典问题:%被转码为%25导致url错误,殊途同归的解决方案。

由于请求路径内带有{}, 导致Spring认为这里是传参,还会引发日志报错:

Spring. Exception- Not enough variables available to expand xxxxxx

 

0x01 问题经过

由于业务和转码需要,需要在RestTemplate发送请求之前,,拼装好完整的URL请求路径,拼装代码如下:

String queryUrl =  serverURL+"?query="+ URLEncoder.encode(serverQL, StandardCharsets.UTF_8.toString());

以上会发现queryUrl是正常字符串+部分字符串进行了URLEncoder,样例如下:

// http://192.168.150.24:31190/api/v1/query?query=sum(irate(container_cpu_usage_seconds_total%7Bcontainer_name!%3D%27POD%27%7D%5B5m%5D))%20by%20(namespace%2C%20container_name)

在经过RestTemplate发送后,queryUrl变成了如下:

// http://192.168.150.24:31190/api/v1/query?query=sum(irate(container_cpu_usage_seconds_total%257Bcontainer_name!%253D%2527POD%2527%257D%255B5m%255D))%2520by%2520(namespace%252C%2520container_name)

仔细对比会发现%被转码为%25,使用站长工具urlencode, 使用UrlDecode解码两次,才能恢复到最初的queryUrl;

说明query字符串部分被进行了2次UrlDecode;

 

0x03 问题解决

在将queryUrl传入RestTemplate之前,将其封装为一个URL对象,避免了queryUrl被RestTemplate进行2次UrlDecode

String queryUrl =  serverURL+"?query="+ URLEncoder.encode(serverQL, StandardCharsets.UTF_8.toString());
URI uriObj = URI.create(queryUrl);
String http = null;
try {
        http = RestTemplateUtil.get(uriObj);
        log.info("【监控指标】查询结果:" + http);
} catch (Exception e) {
        log.error("【监控指标】获取异常,请求地址:{},请求指标:{},异常信息:{}", serverURL, serverQL, e);
}

 同时RestTemplate传参也是传入一个URL对象:

public static String get(URI url) {
        HttpHeaders headers = new HttpHeaders();
        headers.add("Accept", "application/json");
        headers.add("Content-Encoding", "UTF-8");
        headers.add("Content-Type", "application/json; charset=UTF-8");
        HttpEntity<String> requestEntity = new HttpEntity<>(null, headers);
        ResponseEntity<String> response = RestTemplateUtil.getInstance().exchange(url, HttpMethod.GET, requestEntity, String.class);
        String responseBody = response.getBody();
        return responseBody;
}

 

0x04 参考

Stackoverflow:Using RestTemplate in Spring. Exception- Not enough variables available to expand

Stackoverflow报错日志大宝库~~

 

posted @ 2022-05-15 22:38  时光飞逝,逝者如斯  阅读(765)  评论(0编辑  收藏  举报