You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用RestTemplate发送带PromQL查询参数的GET请求遇400错误

解决RestTemplate发送PromQL查询GET请求返回400 Bad Request的问题

问题场景

需使用RestTemplate发送包含PromQL查询参数的GET请求,查询参数为:query=100 - (avg(rate(node_cpu_seconds_total{job="prometheus",mode="idle"}[1m])) * 100)。但代码实现后始终返回400错误,相同请求在Postman中可正常执行,尝试URL编码后也无效。

错误信息

400 Bad Request: {"status":"error","errorType":"bad_data","error":"invalid parameter "query": unknown position: parse error: no expression found in input"}

尝试的代码

String url = "http://localhost:9090/api/v1/query";
String queryParam = "100 - (avg(rate(node_cpu_seconds_total{job=\"prometheus\",mode=\"idle\"}[1m])) * 100)";

Object response = getWithParam(url, "query", queryParam);

public Object getWithParam(String url, String paramName, String paramValue) {
    String encodedParamValue = UriComponentsBuilder
            .fromPath(paramValue)
            .build()
            .encode()
            .toUriString();
    HttpEntity requestEntity = new HttpEntity<>(null, createHeaders(paramName, encodedParamValue));

    ResponseEntity response = restTemplate.exchange(url, HttpMethod.GET,
            requestEntity, Object.class);

    return response.getBody();
}

private MultiValueMap<String, String> createHeaders(String paramName, String paramValue) {
    MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
    headers.add(paramName, paramValue);
    return headers;
}

问题原因及修复

核心错误是把查询参数放到了请求头里,而非URL的查询参数中。GET请求的查询参数需拼接在URL后,Prometheus API仅从URL查询字符串中读取query参数,这就是Postman正常但代码报错的原因。同时,手动编码方式也不正确,应借助UriComponentsBuilder构建带参数的完整URL。

修复后的代码:

String url = "http://localhost:9090/api/v1/query";
String queryParam = "100 - (avg(rate(node_cpu_seconds_total{job=\"prometheus\",mode=\"idle\"}[1m])) * 100)";

Object response = getWithParam(url, "query", queryParam);

public Object getWithParam(String url, String paramName, String paramValue) {
    // 构建带查询参数的URL,自动完成正确编码
    String fullUrl = UriComponentsBuilder.fromHttpUrl(url)
            .queryParam(paramName, paramValue)
            .build()
            .toUriString();

    // GET请求无需额外请求体和参数头,直接发起请求
    ResponseEntity<Object> response = restTemplate.exchange(fullUrl, HttpMethod.GET, null, Object.class);
    return response.getBody();
}

关键说明

  • GET请求的查询参数必须放在URL的查询字符串中,不能放入请求头。
  • 使用UriComponentsBuilder.fromHttpUrl()配合queryParam()方法,可自动完成参数的正确URL编码,无需手动处理特殊字符。
  • 无需构建包含参数的请求头,保持请求头简洁即可。

内容的提问来源于stack exchange,提问作者Магомед Абдулвагабов

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 01:17:10