Closed gr2m closed 2 years ago
Yeah, the req
passed as the first parameter to your request
handler is an instance of IncomingMessage
, so you can consume it as a readable stream and get the request body:
const assert = require('assert');
const createMitm = require('mitm');
const http = require('http');
const mitm = createMitm();
async function consumeReadableStream(readableStream) {
const chunks = [];
for await (const chunk of readableStream) {
chunks.push(chunk);
}
return Buffer.concat(chunks);
}
mitm.on('request', async (req, res) => {
assert(req instanceof http.IncomingMessage);
const requestBodyBuffer = await consumeReadableStream(req);
const requestBodyObj = JSON.parse(requestBodyBuffer.toString());
console.log('Got request body', requestBodyObj);
});
const req = http.request({
method: 'POST',
hostname: 'example.com',
path: '/thepath',
port: 1234,
headers: {
'Content-Type': 'application/json',
},
});
req.end('{"here": {"you": "go"}}');
Output:
Got request body { here: { you: 'go' } }
Totally makes sense, thanks a lot!
Thanks, @papandreou, for the quick comment! I'll add to that, that you can easily use Mitm.js with Express.js as an example of composability that Mitm.js's approach affords.
That's how I generally test:
var Mitm = require("mitm")
var Router = require("express").Router
var parseBody = require("body-parser").json()
var mitm = Mitm()
var router = Router().use(parseBody)
mitm.on("request", function(req, res) {
router(req, res, function(err) {
if (err == null) return
res.statusCode = 502
res.end()
})
})
router.get("/foo/bar", function(req, res) {
req.headers.host.must.equal("api.example.com")
req.query.foo.must.equal("bar")
req.body.must.eql({foo: "bar"})
res.statusCode = 201
res.json({foo: "bar"})
})
This is great, you should add it to the README!
A common use case for http mocking is to match a request by its body. Is there a way to retrieve the request body using today's APIs of Mitm.js?