Postman转k6脚本后Content-Type未更新致请求报错排查
问题:Postman转k6脚本后POST请求报"POST body missing"错误
前提
Postman中对应的请求可正常运行。
执行的操作
- 运行postman-to-k6转换命令:
postman-to-k6 loadTest.postman_collection.json -o k6-script.js - 带HTTP调试参数执行k6脚本:
k6 run --out csv=test_results.csv k6-script.js --http-debug="full"
自动生成的k6脚本
// Auto-generated by the postman-to-k6 converter export let options = { maxRedirects: 4 }; const Request = Symbol.for("request"); postman[Symbol.for("initial")]({ options }); export default function() { postman[Request]({ name: "Campaigns", id: "189fa369-87c7-4dcb-bf9d-e812d4efd6e8", method: "POST", address: "https://api.beta.detail-page.journeys.a2z.com/graphql", data: '{"query":"\n query campaigns($projectId: ID!) {\n campaigns(projectId: $projectId) {\n id\n createdAt\n createdBy\n typeId\n originalPodData\n useReactAppUrl\n }\n }\n ","variables":{"projectId":"ghost:PublishTest 2:US"}}', headers: { "Content-Type": "application/json", identitytoken: <Backend-JWT-Token> }, auth(config, Var) { const address = new URI(config.address); const options = { method: "POST", protocol: address.protocol(), hostname: address.hostname(), port: address.port(), path: address.path() + address.search(), body: config.data, region: "us-west-2", service: <Service-Name> }; const credential = { accessKeyId: <accessKey-ID>, secretAccessKey: <Secret-key>, sessionToken: <Session-token> }; const signed = aws4.sign(options, credential); const [path, query = ""] = signed.path.split("?"); config.address = new URI() .protocol(address.protocol()) .hostname(signed.hostname) .path(path) .query(query) .toString(); Object.assign(config.headers, signed.headers); } }); }
请求日志
POST /graphql HTTP/1.1 Host: api.beta.detail-page.journeys.a2z.com User-Agent: k6/0.40.0 (https://k6.io/) Content-Length: 354 Authorization: AWS4-HMAC-SHA256 Credential=ASIAVGC47R5TZOZXHHNM/20221025/us-west-2/execute-api/aws4_request, SignedHeaders=content-length;content-type;host;x-amz-date;x-amz-security-token, Signature=9dceffc3e3376fd6f9b860025ce9a82454f740bd189ffa8da3c0a6d8d83e230f Content-Type: application/x-www-form-urlencoded; charset=utf-8 Identitytoken: <Identity-token> X-Amz-Date: 20221025T200827Z X-Amz-Security-Token: <Security-token> Accept-Encoding: gzip
响应日志
HTTP/2.0 500 Internal Server Error Content-Length: 61 Access-Control-Allow-Origin: * Content-Type: text/html; charset=utf-8 Date: Tue, 25 Oct 2022 20:08:27 GMT Etag: W/"3d-hTSca7jJI4XwK3C0Li5aF8JIkvc" X-Amz-Apigw-Id: ak9JUEu-PHcFefQ= X-Amzn-Remapped-Connection: close X-Amzn-Remapped-Content-Length: 61 X-Amzn-Remapped-Date: Tue, 25 Oct 2022 20:08:27 GMT X-Amzn-Requestid: bee58104-704c-4cb0-9ec4-399e6f69450d X-Amzn-Trace-Id: Root=1-6358423b-5dc39ed81536364944f6bd11 X-Powered-By: Express
错误提示
POST body missing. Did you forget use body-parser middleware? group= iter=0 request_id=ad10989c-1023-46c9-5f34-e381a7d5795b scenario=default source=http-debug vu=1
问题分析
从请求日志可见,实际发送的Content-Type被篡改成了application/x-www-form-urlencoded,但脚本里明明配置了application/json。根源在AWS签名流程:
aws4.sign方法若未收到明确的Content-Type,会默认设置为application/x-www-form-urlencoded- 后续
Object.assign(config.headers, signed.headers)用签名后的头部覆盖了原配置,导致正确的Content-Type丢失
服务器因Content-Type不匹配,无法解析JSON格式的请求体,因此抛出"POST body missing"错误。
解决方法
修改脚本中的auth函数,在签名配置里明确指定Content-Type,并在签名完成后强制保留正确的头部:
auth(config, Var) { const address = new URI(config.address); const options = { method: "POST", protocol: address.protocol(), hostname: address.hostname(), port: address.port(), path: address.path() + address.search(), body: config.data, region: "us-west-2", service: <Service-Name>, // 新增:将原请求的Content-Type加入签名配置 headers: { "Content-Type": config.headers["Content-Type"] } }; const credential = { accessKeyId: <accessKey-ID>, secretAccessKey: <Secret-key>, sessionToken: <Session-token> }; const signed = aws4.sign(options, credential); const [path, query = ""] = signed.path.split("?"); config.address = new URI() .protocol(address.protocol()) .hostname(signed.hostname) .path(path) .query(query) .toString(); Object.assign(config.headers, signed.headers); // 强制覆盖Content-Type,确保最终发送的是application/json config.headers["Content-Type"] = "application/json"; }
修改后重新运行k6脚本,请求日志中的Content-Type会变为application/json,服务器就能正确解析请求体,错误将消失。
内容的提问来源于stack exchange,提问作者Dharight
相关产品推荐
相关产品推荐

