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

  • 相关阅读:
    Twitter OA prepare: Rational Sum
    Java: Best Way to read a file
    Summary: gcd最大公约数、lcm最小公倍数算法
    Twitter OA prepare: Flipping a bit
    Twitter OA prepare: Equilibrium index of an array
    echo -e 参数
    openwrt 添加luci选项
    基于TLS的EAP 认证方法
    linux命令 dirname
    freeradius 错误: error:140890C7:SSL routines:ssl3_get_client_certificate:peer did not return a certificate
  • 原文地址:https://www.cnblogs.com/JetpropelledSnake/p/16275076.html
Copyright © 2020-2023  润新知