How to get both parsed body and raw body in Express
By Flavio Copes
Learn how to get both the parsed JSON body and the raw body in Express by adding a verify function to body-parser that saves the buffer to req.rawBody.
You can get both the parsed body and the raw body in Express by passing a verify function to body-parser, and saving the raw buffer to req.rawBody there.
In one application I’m building, I had this problem.
Using Express, I can import body-parser to parse the body as JSON:
import bodyParser from 'body-parser'
app.use(bodyParser.json())
However to integrate with the Stripe payments API I had the need to expose the raw body (not parsed) into an endpoint, and I couldn’t figure out how to do it, while still parsing the body as JSON.
Why do you need the raw body at all?
Stripe signs every webhook it sends you. To verify the signature, you must compute a hash over the exact bytes Stripe sent.
Once body-parser turns those bytes into a JavaScript object, the original bytes are gone. You might think you can rebuild them with JSON.stringify(req.body), but that produces different whitespace and key ordering, so the signature check fails. This is the pitfall almost everyone hits with Stripe webhooks.
The fix is to keep a copy of the raw buffer before parsing happens.
The solution
body-parser accepts a verify option. It’s a function called with the request, the response, and the raw body buffer, before the body is parsed.
We use it to store the buffer on the request object:
app.use(bodyParser.json({
verify: (req, res, buf) => {
req.rawBody = buf
}
}))
Now the raw body is available on req.rawBody and the JSON parsed data is available on req.body.
In the webhook handler you pass req.rawBody to the signature check, and keep using req.body everywhere else:
app.post('/webhooks/stripe', (req, res) => {
const signature = req.headers['stripe-signature']
//verify using req.rawBody and the signature
})
If you use express.json() instead of requiring body-parser yourself, it accepts the same verify option, since it uses body-parser under the hood.
What’s the cost?
From the body-parser GitHub I found that this doubles the RAM usage for every request, since we keep the raw buffer around next to the parsed object. But since I need this functionality, I have no other way.
If that worries you, an alternative is to apply the verify function only where you need it. You can mount a raw parser on the webhook route alone, and keep plain bodyParser.json() for everything else. That way the rest of the app pays no extra memory cost.
Except perhaps creating a different server just for the Stripe webhook I wanted to handle. For my case, the verify trick was enough.
Related posts about node: