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报错日志大宝库~~