7

I'm actually developping an Angular webform with a file upload and some data. Here are the request headers:

POST /tests/add HTTP/1.1
Host: localhost:3000
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate
Content-Type: application/json;charset=utf-8
Referer: http://localhost:8000/
Content-Length: 2033

I build the request this way:

var formData = new FormData();
formData.append('file', $scope.test.file);
$http({
  method: 'POST',
  url: backUrl + '/tests/add',
  data: { 'file': $scope.file,
          'token': 'test'},
  contentType: false,
  processData: false,
  transformRequest: function (data, headersGetter) {
      var formData = new FormData();
      angular.forEach(data, function (value, key) {
          formData.append(key, value);
      });
      var headers = headersGetter();
      delete headers['Content-Type'];
      return formData;
  }

But it always return a 400 bad request with this error:

Unexpected token -
400

SyntaxError: Unexpected token -
    at parse (/home/me/projects/www/node_modules/body-parser/lib/types/json.js:83:15)
    at /home/me/projects/www/node_modules/body-parser/lib/read.js:116:18
    at invokeCallback (/home/me/projects/www/node_modules/raw-body/index.js:262:16)
    at done (/home/me/projects/www/node_modules/raw-body/index.js:251:7)
    at IncomingMessage.onEnd (/home/me/projects/www/node_modules/raw-body/index.js:307:7)
    at emitNone (events.js:86:13)
    at IncomingMessage.emit (events.js:185:7)
    at endReadableNT (_stream_readable.js:974:12)
    at _combinedTickCallback (internal/process/next_tick.js:74:11)
    at process._tickCallback (internal/process/next_tick.js:98:9)

This is the only reference to bodyParser I have in my backend:

app.use(bodyParser.json());       // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({     // to support URL-encoded bodies
  extended: true,
  defer: true
}));

What am I doing wrong ?

Papotitu
  • 407
  • 1
  • 4
  • 16

2 Answers2

7

Are you positive you're sending JSON?

Most likely you are using invalid JSON which forces error with bodyParser.json().

Make sure you are using valid JSON. You can also swap bodyParser.json with bodyParser.raw for middleware.

defaultcheckbox
  • 739
  • 2
  • 5
  • 16
  • I'm not sure what you mean, I'm not sending a JSON file if that's wjat you're asking – Papotitu Nov 02 '16 at 13:51
  • 1
    Okay so I swapped from .json to .raw and the error doesn't occur anymore. However, req.body is always empty now, so how do I acces request param after a bodyparser.raw ? – Papotitu Nov 02 '16 at 14:22
  • Sorry, I was saying to use it so you could confirm what you're sending. I recommend making sure you are sending JSON properly by checking what you're actually sending in the header and the body. But here is a goog link on bodyparser.raw: http://stackoverflow.com/questions/18710225/node-js-get-raw-request-body-using-express – defaultcheckbox Nov 03 '16 at 13:29
  • Just ran into an issue where in my post request i wasn't sending in valid JSON, but was sending in just the a string value. – Diego Oct 18 '21 at 20:06
  • in other words. `someResource.post("123456").then()...` as opposed to `someResource.post({"id": "123456"}).then()...` This is what i believe @defaultcheckbox was referring to. – Diego Oct 18 '21 at 20:08
2

Make sure your request body JSON is valid & if you want to prevent it from backend use following code.

NodeJS can't handle the invalid JSON body by default, if you put wrong JSON body raw JSON then you'll encounter following error.

SyntaxError: Unexpected token } in JSON at position 75
   at JSON.parse

To prevent the error we can use middleware to solve the issue for all APIs.

 app.use((err, req, res, next) => {
   // This check makes sure this is a JSON parsing issue, but it might be
   // coming from any middleware, not just body-parser:

   if (err instanceof SyntaxError && err.status === 400 && 'body' in err) {
       console.error(err);
       return res.status(400).json({status: false, error: 'Enter valid json body'}); // Bad request
   }

   next();
});
Swapon
  • 409
  • 6
  • 16