在 node.js 服务器上使用 supertest/superagent 读取响应输出缓冲区/流
Posted
技术标签:
【中文标题】在 node.js 服务器上使用 supertest/superagent 读取响应输出缓冲区/流【英文标题】:Read response output buffer/stream with supertest/superagent on node.js server 【发布时间】:2012-11-14 10:18:34 【问题描述】:我正在尝试编写一个测试来检查 API 路由是否输出具有正确内容的 ZIP 文件。
我正在使用 mocha 和 supertest 进行测试,我想实际读取输出流/缓冲区,读取 zip 文件内容并查看内容是否正确。
任何想法我应该怎么做?当我尝试阅读 res.body
时,它只是一个空对象。
request(app)
.get( "/api/v1/orders/download?id[]=1&id=2" )
.set( "Authorization", authData )
.expect( 200 )
.expect( 'Content-Type', /application\/zip/ )
.end( function (err, res)
if (err) return done( err );
console.log( 'body:', res.body )
// Write the temp html file to filesystem using utf-8 encoding
var zip = new AdmZip( res.body );
var zipEntries = zip.getEntries();
console.log( 'zipentries:', zipEntries );
zipEntries.forEach(function(zipEntry)
console.log(zipEntry.toString()); // outputs zip entries information
);
done();
);
【问题讨论】:
【参考方案1】:如Testing binary response with supertest 中所述,在请求中设置.responseType('blob')
将导致req.body
成为缓冲区。
https://visionmedia.github.io/superagent/#binary
it('test', async () =>
await request(app)
.get('/api/some-zip')
.responseType('blob')
.expect(200)
.expect('Content-Type', /application\/zip/)
.expect(( res) =>
const zipEntries = new AdmZip(res.body).getEntries().map(e => e.entryName);
expect(zipEntries).toEqual(expect.arrayContaining(['zipfile1.pdf', 'zipfile2.pdf']));
);
);
【讨论】:
【参考方案2】:我刚刚遇到了同样的情况,我需要编写一个测试来检查 zip 文件的内容。我就是这样做的。
it('test', async function ()
let data = '';
const res = await request(app)
.get('/api/some-zip')
.parse((res, callback) =>
res.setEncoding('binary');
res.on('data', function (chunk)
data += chunk;
);
res.on('end', function ()
callback(null, Buffer.from(data, 'binary'));
);
)
const zip = new AdmZip(res.body)
const zipEntries = zip.getEntries();
expect(zipEntries[0].name).to.equal('zipfile1.pdf');
expect(zipEntries[1].name).to.equal('zipfile2.pdf');
);
我使用了 async/await 语法
【讨论】:
【参考方案3】:现有的答案对我不起作用。我最终做的是:
// parses response.body buffer into a data object
const parsePDF = response =>
return new Promise((resolve, reject) =>
// code that parses response.body as buffer
// and calls resolve(data); when done
// or reject(err); on error
)
;
const binaryParser = require('superagent-binary-parser');
// test snippet
request(app)
.get('/some/api/returning/pdf')
.expect(200)
.expect('content-type', 'application/pdf')
.parse(binaryParser)
.buffer()
.then(parsePDF)
.then((pdf) =>
chai.expect(pdf.pages.length).to.be.equal(5);
)
【讨论】:
【参考方案4】:扩展@Beau 的答案,以下可用于获取任何二进制响应内容作为缓冲区,您可以在request.end()
中进一步检查:
function binaryParser(res, callback)
res.setEncoding('binary');
res.data = '';
res.on('data', function (chunk)
res.data += chunk;
);
res.on('end', function ()
callback(null, new Buffer(res.data, 'binary'));
);
// example mocha test
it('my test', function(done)
request(app)
.get('/path/to/image.png')
.expect(200)
.expect('Content-Type', 'image.png')
.buffer()
.parse(binaryParser)
.end(function(err, res)
if (err) return done(err);
// binary response data is in res.body as a buffer
assert.ok(Buffer.isBuffer(res.body));
console.log("res=", res.body);
done();
);
);
【讨论】:
这很好用,虽然我必须在请求中添加.buffer()
。
使用@Nate,来自docs,“如果未启用响应缓冲(.buffer(false)),则将发出响应事件而无需等待正文解析器完成,因此响应.body 将不可用”。
@ZachB 所以.buffer().parse(binaryParser)
?
@rcoup 是的,文档说,但如果没有快速测试,它似乎也可以正常工作。更长的响应可能需要它...?【参考方案5】:
我认为您会想要为应用程序/zip 创建自己的解析器并使用它来获取实际的响应数据;例如,JSON 解析器是 here。一旦你得到它,你可以通过将它传递给 request.parse 来使用它;所以你的测试会变成:
request(app)
.get( "/api/v1/orders/download?id[]=1&id=2" )
.set( "Authorization", authData )
.expect( 200 )
.expect( 'Content-Type', /application\/zip/ )
.parse( function (res, fn)
res.data = '';
res.on( 'data', function (chunk) res.data += chunk; );
res.on( 'end', function ()
try
fn( null, new AdmZip( res.data ) );
catch ( err )
fn( err );
);
)
.end( function (err, res)
if (err) return done( err );
console.log( 'body:', res.body )
// Write the temp HTML file to filesystem using utf-8 encoding
var zipEntries = res.body.getEntries();
console.log( 'zipentries:', zipEntries );
zipEntries.forEach(function(zipEntry)
console.log(zipEntry.toString()); // outputs zip entries information
);
done();
);
为了找到这个问题的答案,我主要依靠检查 superagent 测试套件。 :)
【讨论】:
以上是关于在 node.js 服务器上使用 supertest/superagent 读取响应输出缓冲区/流的主要内容,如果未能解决你的问题,请参考以下文章
在 iOS 上加密和在 Node.js 上使用 RAW RSA 解密时遇到问题
如何在 Node.js 服务器上部署 Vue.js 应用程序
在 Firebase 上部署使用 node.js 服务器的应用程序
如何使用 XAMPP 或 node.js 使 AJAX 在本地服务器上工作