调用Prometheus HTTP API时Curl与Node.js请求结果差异求助
Prometheus API调用结果差异问题排查
问题现象
调用Prometheus HTTP API时,两种方式返回结果完全不同:
- Bash+curl调用返回正常的
vector类型监控数据 - Node.js+https GET调用返回
string类型,结果为查询语句本身
1. Bash+curl 调用示例
调用代码
#!/bin/bash APIKEY="xxx-xxx" curl https://<server>/prometheus-api/query \ -H "x-api-key: $APIKEY" \ -H "content-type: application/x-www-form-urlencoded" \ --data-urlencode \ query='ifHCInOctets{instance="MYROUTER.xxx"} and ifHCInOctets{ifName=~"et-1/1/1"}'
返回结果
{ "status": "success", "data": { "resultType": "vector", "result": [ { "metric": { "__name__": "ifHCInOctets", "ifAlias": "--- Lien vers ...", "ifDescr": "et-1/1/1", "ifIndex": "682", "ifName": "et-1/1/1", "instance": "MYROUTER.xxx", "job": "ifmibsnmp" }, "value": [ 1725001024.046, "1975177966081341" ] } ] } }
2. Node.js+https 调用示例
调用代码
var request = '/prometheus-api/query?query=\"ifHCInOctets{instance=\'MYROUTER.xxx\'} and ifHCInOctets{ifName=~\'et-1/1/1\'}\"' var erequest = encodeURI(request) var options = { host:host, port: 443, method: "GET", path: erequest, headers: { 'x-api-key': 'xxxxx', 'content-type': 'application/x-www-form-urlencoded', }, rejectUnauthorized: false, } https.get(options,function(resp) { resp.setEncoding('utf8'); console.log('statusCode',resp.statusCode) if(resp.statusCode!=200) { console.log('-----------------') } let data = ''; resp.on('data',function(chunk) { data += chunk; }); resp.on('end', () => { exec.emit('data',data) }); }).on('error', (err) => { console.log('Error: ' + err.message); });
返回结果
{ "status": "success", "data": { "resultType": "string", "result": [ 1725001330.179, "ifHCInOctets{instance='MYROUTER.xxx'} and ifHCInOctets{ifName=~'et-1/1/1'}" ] } }
问题原因
Node.js代码存在两处关键错误:
- 多余转义字符:
request变量里给查询语句套了转义双引号,导致Prometheus把传入的内容识别为字符串字面量,而非查询表达式 - 错误编码范围:对整个路径(包含
?和=)执行encodeURI,导致API无法正确解析查询参数,应该仅对查询参数的值单独编码
修复方案
修改Node.js代码,正确处理查询参数的转义和编码:
// 定义原始查询语句,无需额外转义 const query = 'ifHCInOctets{instance="MYROUTER.xxx"} and ifHCInOctets{ifName=~"et-1/1/1"}'; // 仅对查询参数的值进行编码 const encodedQuery = encodeURIComponent(query); // 拼接正确的请求路径 const path = `/prometheus-api/query?query=${encodedQuery}`; const options = { host: host, port: 443, method: "GET", path: path, headers: { 'x-api-key': 'xxxxx', // GET请求无需设置content-type头,可移除 }, rejectUnauthorized: false, }; https.get(options, function(resp) { resp.setEncoding('utf8'); console.log('statusCode', resp.statusCode); let data = ''; resp.on('data', function(chunk) { data += chunk; }); resp.on('end', () => { exec.emit('data', data); }); }).on('error', (err) => { console.log('Error: ' + err.message); });
修复说明
- 使用
encodeURIComponent单独编码查询参数值,确保特殊字符被正确转义 - 移除多余的转义引号,让Prometheus正确识别查询表达式
- 移除不必要的
content-type头(GET请求参数在URL中,无需该头)
内容的提问来源于stack exchange,提问作者Gilles
相关产品推荐
相关产品推荐

