Trouble with posting JSON data (with node request)

2019-03-06 09:50发布

问题:

I use MongoDB as the back-end database for my node/Express application. To summarize the problem I am facing, I don't know how to set up the body-parser configuration in my Express app, because the server side application is not receiving the full JSON posted by the client application (also a node.js app). For the most part, the client is sending JSON in the request body to RESTful endpoints. The exception being a single case where a file needs to be uploaded and since that is a multipart body, I am using request and form-data to build that type of request and using multer on the server side to process the multipart request, since body-parser does not process such requests.

On the server-side (Express), I have the following configuration of the Express app:

let app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

On the node client, I am using the following code to build up a JSON-style JavaScript object and post it to a RESTful endpoint:

I am having difficulty composing the request on the client side, with node-request:

// class is a JavaScript/JSON object within scope of this code
let req = request.post({
  //headers: { 'Content-Type': 'application/json' },
  url: 'http://localhost:3000/classes',
  //form: class
  form: JSON.stringify(class)
}, function (err, resp, body) {
  if (err) {
    throw err;
  }
});

Note that I attempted multiple versions of the above code by explicitly specifying the content type as application/JSON, as well as using JSON.stringify to convert the JavaScript object into a JSON string. The MongoDB collection (class) stores the following type of document, which contains foreign keys to two other collections (subject and student):

{
  "_id" : ObjectId("57758f15f68da08c254ebee1"),
  "name" : "Grade 5 - Section A",
  "scores" : [{
    "studentId" : ObjectId("5776bd36ffc8227405d364d2"),
    "performance": [{
      "subjectId" : ObjectId("577694ecbf6f3a781759c54a"),
      "score" : 86,
      "maximum" : 100,
      "grade" : "B+"
    }]
  }]
}

In the server logs, I see the following error:

Tue, 05 Jul 2016 04:34:46 GMT classReportApp:routes:classes class received from client: { _id: 577b38e65967097c25876764, scores: [] }
RangeError: Invalid status code: 0
    at ServerResponse.writeHead (_http_server.js:192:11)
    at ServerResponse.writeHead (C:\Development\classReportApp\node_modules\morgan\node_modules\on-headers\index.js:55:19)
    at ServerResponse._implicitHeader (_http_server.js:157:8)
    at ServerResponse.OutgoingMessage.end (_http_outgoing.js:566:10)
    at ServerResponse.send (C:\Development\classReportApp\node_modules\express\lib\response.js:205:10)
    at ServerResponse.json (C:\Development\classReportApp\node_modules\express\lib\response.js:250:15)
    at C:\Development\classReportApp\server-process\app.js:80:26
    at Layer.handle_error (C:\Development\classReportApp\node_modules\express\lib\router\layer.js:71:5)
    at trim_prefix (C:\Development\classReportApp\node_modules\express\lib\router\index.js:310:13)
    at C:\Development\classReportApp\node_modules\express\lib\router\index.js:280:7
    at Function.process_params (C:\Development\classReportApp\node_modules\express\lib\router\index.js:330:12)

which is strange because scores array of sub-documents is empty (scores: []), whereas on the client side, I am sending a non-empty array with some students' performances elements in it.

Have I violated the right way to post JSON to Express apps? How do I fix this?

Edited: 7/5/2016 I changed the body parser middle-ware configuration to use extended: true instead.

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

The node.js is still using the node-request module to compose and send the POST request, using the following code:

let req = request({
  url: 'http://localhost:3000/classes',
  method: 'POST',
  json: class
}, function (err, resp, body) {
  if (err) {
    throw err;
  }
  else {
    // process response
  }
});

This works now, but what confuses me is that since the content type is application/json, how does the bodyParser.urlencoded({ extended: true }) (or false) matter?

回答1:

Issue is with form: JSON.stringify(class) in your first request. form takes url encoded form input, stringified json won't work. check content-type header (application/x-www-form-urlencoded)

json: class in your 2nd snippet works as this handles json data and sets correct content type header correctly.



回答2:

Try .toJSON() method over class before sending.