1

I'm working with express + json body parser. For validation purposes I need to distinguish between

  • empty object request body was sent by the user ({})
  • no request body was sent by the user

as I'm trying to provide reasonable error messages, and in one case I need to instruct the user to add missing fields, while in the other case they might not even be aware that the request body should be sent, and the priority is warning them about this.

This to me seems impossible currently, as the json body parser sets request.body to {} in case no request body was provided, reference:

https://github.com/expressjs/body-parser/blob/master/lib/types/json.js#L72

My question is, while using the json body parser, is it possible to detect if the request body was actually sent by the client or not? So how would I implement a function like this:

import { Request } from 'express'

function didTheUserSendRequestBody(request: Request): boolean {
  // What do?
}

Which returns true when my endpoint is hit like this:

curl -X POST http://localhost:5000/foo 
   -H "Content-Type: application/json"
   -d '{}'  

And false for this:

curl -X POST http://localhost:5000/foo 
Balázs Édes
  • 13,452
  • 6
  • 54
  • 89
  • [add some middleware](https://stackoverflow.com/a/41956790/2487517) before the body parser to detect if the body property is missing – Tibrogargan Apr 01 '22 at 23:12
  • You could use `express.raw()` instead, get the raw body yourself, examine what's there, then if it's there and content-type is `application/json`, then call `JSON.parse()` on it to get the result and check if desired fields are there. If no body or not `application/json`, then configure appropriate error. – jfriend00 Apr 01 '22 at 23:20
  • It also seems like if no body is sent then some required fields in the body will be missing so just saying the fields are missing would suffice. – jfriend00 Apr 01 '22 at 23:21
  • @Tibrogargan - The standard body parsing middleware, checks to see if the content-type matches what it knows how to parse. If so, it reads the body from the incoming tcp stream and then parses it. So, there's no way to peek into the stream to see what is coming. You either read the stream and then parse the result or not. – jfriend00 Apr 01 '22 at 23:23
  • @jfriend00 "no way" seems awfully certain – Tibrogargan Apr 01 '22 at 23:26
  • @Tibrogargan - You are welcome to write an answer with your solution. – jfriend00 Apr 02 '22 at 04:33
  • So these 2 are both working solutions, the reason I'd like to avoid them is because I'm doing this as part of a framework, and I'd like to allow users to use standard express middlewares without funky workarounds. Is the information about the presence of the original body really lost, after the JSON body parser runs? – Balázs Édes Apr 02 '22 at 08:02

3 Answers3

1

Body-parser json has option verify . It can check raw data at here.

 app.use(express.json({ verify: (req, res, buf, encoding) => { 
// check buff is empty ? and attach result to req ? 
} }))

with verify is function with 4 argument : "where buf is a Buffer of the raw request body"

https://github.com/expressjs/body-parser#verify

Mòe
  • 269
  • 2
  • 7
  • Unfortunately this doesn't seem to be possible. Verify runs here: https://github.com/expressjs/body-parser/blob/master/lib/read.js#L111 and the middleware attaches the request body after verify, here: https://github.com/expressjs/body-parser/blob/master/lib/read.js#L128 so whatever I do in verify will be overwritten. – Balázs Édes Apr 04 '22 at 09:50
  • 1
    Your final purpose is distinguish Empty object or Nothing is sent via post data. I tried and get result at router . Just put "if (buf) req.noEmptyReqBody = true" in verify function. and use this property later – Mòe Apr 04 '22 at 11:02
  • I see, it's very hacky but could work. Thanks! – Balázs Édes Apr 04 '22 at 11:57
1

maybe you can just check the submitted content type, if the user doesn't attach it then the default value will be "undefined".

function didTheUserSendRequestBody(request: Request): boolean {
  if (!request.get('Content-Type')) {
    // return any message
  }
}
0

The easiest way I'm aware of is by checking if req.body is truthy

function didTheUserSendRequestBody(request: Request): boolean {
  if(req.body){
    // Do stuff
  }
}

According to https://developer.mozilla.org/en-US/docs/Glossary/Truthy MDN, an empty object '{}' is truthy. If there is no body sent, it should be undefined when you try to access req.body, which is falsy.

See https://expressjs.com/en/api.html#req for more details

Eric Webb
  • 361
  • 3
  • 10