Node.js调用HTTPS REST API报错:TypeError: First argument must be a string or Buffer
解决Node.js中调用REST API后返回响应时的TypeError问题
你遇到的这个TypeError: First argument must be a string or Buffer错误,其实很好定位——问题出在你的getResponse函数和异步请求的处理逻辑上。
错误根源
当用户发送包含prod的消息时,你调用了getProductData函数,但这个函数内部是用request.post做异步HTTP请求,它没有返回任何有效值(默认返回undefined)。而你的HTTP服务器代码里,直接把getResponse的返回值传给了response.write,当这个值是undefined时,Node.js就会抛出这个错误,因为response.write要求第一个参数必须是字符串或者Buffer。
修复步骤
我们需要把异步请求的逻辑改成Promise风格,让getResponse能正确返回处理后的结果:
- 改造
getProductData为Promise函数
把原来的回调式请求改成返回Promise,这样可以方便地处理异步结果:
function getProductData(message) { return new Promise((resolve, reject) => { const postURL = "https://myexample.com:8443/Products/SearchProduct"; const query = "db.Products.find( { $and : [{ productID : '" + message + "' }, { recTime : {$lt : '2018-05-23T23:59:59Z' }}, { recTime : {$gt : '2018-05-22T23:59:59Z' }} ] }, {productID:1,productType:1,productCol:1 } ).sort({_id:-1}).limit(10)"; request.post( postURL, { json: { query: query } }, (error, response, body) => { if (error) { reject(error); return; } if (response.statusCode === 200) { // 把API返回的结果转成字符串,确保符合response.write的要求 resolve(JSON.stringify(body)); } else { reject(new Error(`API请求失败,状态码:${response.statusCode}`)); } } ); }); }
- 让
getResponse统一返回Promise
不管是同步返回的问候语,还是异步的API结果,都用Promise包裹,保持接口一致性:
function getResponse(from, message) { if (message.indexOf('prod') > -1) { const messageArray = message.split(' '); return getProductData(messageArray[1]); } else { // 同步场景也返回Promise,方便后续统一处理 return Promise.resolve(`Hello <span style='color:blue;'>${from}</span>, you said: <span style='color:red;'>${message}</span>`); } }
- 修改HTTP服务器的请求处理逻辑
现在getResponse返回的是Promise,我们需要用.then()来获取结果,再写入响应:
POST请求部分修改:
request.on('end', function () { const post = JSON.parse(body); response.writeHead(200, {'Content-Type': 'text/html; charset=utf-8'}); getResponse(post.from, post.message) .then(result => { response.write(result, "UTF8"); response.end(); }) .catch(error => { // 错误处理,给用户返回友好提示 response.write(`请求处理失败:${error.message}`); response.end(); }); });
GET请求部分修改:
const p = url.parse(request.url, true); response.writeHead(200, {'Content-Type': 'text/html; charset=utf-8'}); getResponse(p.query.from, p.query.message) .then(result => { response.write(result, "UTF8"); response.end(); }) .catch(error => { response.write(`请求处理失败:${error.message}`); response.end(); });
额外注意事项
- 确保你已经安装了
request模块:如果没装,运行npm install request即可 - 你当前的查询字符串拼接方式存在注入风险(哪怕是MongoDB查询),建议用参数化查询来处理用户输入
- 给响应头加上
Content-Type可以避免编码相关的问题
内容的提问来源于stack exchange,提问作者Pushkar Rathod
相关产品推荐
相关产品推荐

