I'm trying to setup a NodeJS express JSON REST API for the first time, but I'm facing some troubles while trying to retrieve the JSON data coming from the requests (both GET and POST requests)
Here's the code:
var bodyParser = require("body-parser");
const express = require("express");
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.get("/prova", (req, res)=>{
console.log(req.headers["content-type"]);
console.log(req.body);
res.status(200).json(req.body);
});
Here's the console.log();
When trying to make a request with Postman with some parameters:
application/json
{}
And here are the Postman request's details
You should avoid sending body with HTTP GET methods as per MDN web docs. As for the shown GET method this line res.status(200).json(req.body); is giving you an empty object, change it for example to res.status(200).json({message:"Hello world!"}); to see the message. For the POST method you can access the body as you do with req.body.
Related
I'm just trying to pass the simplest data possible (at the moment, for test purposes) from client to server with a POST request, but I keep getting empty or undefined logs on req.body.
Server:
//jshint esversion:6
const express = require("express");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const app = express();
app.set('view engine', 'ejs');
app.use(bodyParser.urlencoded({extended: true}));
app.use(express.static("public"));
mongoose.connect("mongodb://localhost:27017/sandbox", {useNewUrlParser: true});
app.get("/", function(req, res){
res.render("home", {});
})
app.post("/filter", function(req, res){
console.log(req.body);
res.redirect("/");
})
app.listen(3000, function() {
console.log("Server started on port 3000");
});
Client (version 1):
var yourdata = { "name": "The pertinent data"};
console.log(document.body)
$.ajax({
url : "/filter",
type: "POST",
dataType:'text',
data : yourdata,
contentType: "application/json",
});
Client (version 2):
var payload = {data: "The pertinent data"};
var req = new XMLHttpRequest();
req.open('POST', '/filter' , true);
req.send(JSON.stringify(payload))
I added both attempts at a code client-side, but I'm happy with whichever method works. Ideally I'll eventually tap into the payload or data with req.body.payload or something, but at the moment that's just giving me an undefined.
I've looked into quite a few similar posts and usually they were missing the "app.use(bodyParser.urlencoded({extended: true}));" or "app.use(bodyParser.json());" I've tried adding and removing those, changing from true to false, still empty.
The console.log(document.body) on the client script does work, giving me the expected body on the browser console, and the server route is working too, eventually redirecting to home.
I can't see how the issue is something I'm doing wrong on the client side, but oddly enough, if I create a form, with an action to that route, and submit, it seems to send the req.body normally. E.g.:
<form class="form" action="/filter" method="post">
<input name="newName" placeholder="Name">
<button type="submit">Submit</button>
</form>
That does indeed log a JSON object e.g.: { newName: 'John'}
In case it might be relevant, the HTML is the simplest one possible, almost empty, only really doing the pertinent links.
Thanks all in advance!
You need three things:
A request body encoded in some data format
A content-type request header which says which data format you are using
Body parsing middleware that can process that data format
When you submit a form, with no enctype attribute, it will submit the data in URL encoded format with the right content type. This matches the body parsing middleware you have (bodyParser.urlencoded({extended: true})).
1, 2, and 3 are all good.
Note that it does not create a JSON object. The client produces URL encoded data. The server parses that into a JavaScript object. There is no JSON.
Client (version 1):
Here you are passing an object to jQuery so it will URL encode the data in it and would normally set the correct content type.
It is failing because you have contentType: "application/json",.
Since you are falsely claiming that you are sending JSON, bodyParser.urlencoded ignores it.
If you had a JSON body parser in place, it would error because the data is not JSON.
1 and 3 are good, but 2 is a lie.
Remove the contentType property.
Client (version 2):
Now you are JSON encoding the data, but you aren't setting the content type request header, and you don't have body parsing middleware that can handle JSON.
3 is bad, and either 1 or 2 is too.
For the server-side part of your application, you need something that moves the body of the request out of the request string itself to a clear, easy-to-read, and use variable. The express json() method (middleware) does that exactly.
Use the express JSON parser middleware as follows:
app.use(express.json())
Code:
const express = require("express");
// const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const app = express();
app.use(express.json()); // 👈 here
// ... the rest of your code
Just few notes about the middleware you're using
app.use(bodyParser.urlencoded({extended: true}));
We usually use this middleware to parse the HTML forms data, in other words, it's just like the express middleware express.json(), but the difference here is that it parses the requests which have the content type of HTML forms, while the express.json() converts the ones which have the content-type of application/json.
If you're using express v +4, you don't need the bodyParser package, express has the .urlencoded() and the .json() methods built into the express package itself, you can use them just as express.json() and express.urlencoded().
Tip, you can have both middlewares, the JSON parser, and the HTML form content type parser, when the server receives a content-type JSON, the express.json() middleware will parse the request body, and if the server receives an HTML form content-type the urlencoded middleware will fire:
code example:
const express = require("express");
// const bodyParser = require("body-parser"); ❌ not needed
const mongoose = require("mongoose");
const app = express();
app.use(express.json()); // 👈 here
app.use(express.urlencoded({ extended: true })) // 👈 here
// ... the rest of your code
const express = require('express');
const cors = require('cors');
const app = express();
app.use(express.json())
app.use(cors());
app.post('/', (req,res) => {
console.log(req.body);
res.send('received')
})
app.listen(5000, console.log('Server is running on port 5000'));
I am trying to send data to the back-end but always getting undefined
I tried to you a parser but seems like just wrapping void into an object
Posting as answer from my comment.
In the second image in postman you need to change the type dropdown from text to JSON, express.json() only parses the body when the header Content-type is set to "application/JSON" and changing that dropdown will automatically include that header.
Here are the docs if it helps explain why you get the empty object in the second image
I'm getting this error when I try to send a Base64 string in a POST request.
POST /saveImage 413 10.564 ms - 1459
PayloadTooLargeError: request entity too large
Already tried
--> app.use(bodyParser.urlencoded({ limit: "50mb", extended: true, parameterLimit: 50000 }))
--> app.use(bodyParser.urlencoded({limit: '50mb'}));
--> app.use(bodyParser({limit: '50mb'}));
Here's my code (api.js class)
const express = require('express');
var app = express();
const router = express.Router();
var Connection = require('tedious').Connection
var Request = require('tedious').Request
var TYPES = require('tedious').TYPES
var multer = require('multer');
....
....
....
router.post('/saveImage', (req, res) => {
request=new Request('SAVE_IMAGE',(err, rowCount, rows)=>{
if(err){
console.log(err);
}
});
request.addParameter("Base64Image", TYPES.Text, req.body.IMG)
connection.callProcedure(request);
});
API CALL (Image class contains a Base64 format image and other fields, but I guess the problem occurs because of the Base64 string length. Small images don't cause any trouble)
create(image: Image) {
return this._http.post('/saveImage', image)
.map(data => data.json()).toPromise()
}
I was having the same error. I tried what you tried it did not work.
I guess you are uploading a file. The simple way to solve this is to not set a Content-Type.
my problem was that I was setting on my headers: Content-Type: application/json and I am [was] using multer (expressjs middle for uploading files).
I have the error whenever I try uploading a file.
So when using postman or making such requests using any tools or libraries like axiosjs or fetch() API do not set content-type.
Once you remove the Content-type it will work. That is what I did
on my code, I have:
const express = require('express');
...
const app = express();
app.use(express.json());
...
...And it is working because I removed Content-Type on my postman headers.
Make sure you are not using Content-Type on the headers.
I would recommend you to use express instead of body-parser, as body-parser got merged back in express a long ago.
I am using this code and it seems to work fine, setting the limit option to 200mb, of both express.json and express.urlencoded
app.use(express.json({ limit: "200mb" }));
app.use(express.urlencoded({ extended: true, limit: "200mb" }));
Source: express.json vs bodyparser.json
Here's my app.js file.
var express = require('express'),
bodyParser = require('body-parser'),
oauthServer = require('oauth2-server'),
oauth_model = require('./app_modules/oauth_model')
const app = express()
app.use(bodyParser.urlencoded({ extended: true }));
var jsonParser = bodyParser.json();
app.oauth = oauthServer({
model: oauth_model, // See below for specification
grants: ['password', 'refresh_token'],
debug: process.env.OAUTH_DEBUG,
accessTokenLifetime: 172800,
refreshTokenLifetime: 172800,
authCodeLifetime: 120,
});
// Oauth endpoint.
app.all('/oauth/token', app.oauth.grant());
// User registration endpoint.
app.post('/users', jsonParser, require('./routes/register.js'));
// Get user details.
app.get('/users', app.oauth.authorise(), require('./routes/users.js'));
app.post('/', app.oauth.authorise(), require('./routes/test.js'));
app.use(app.oauth.errorHandler());
app.listen(3000, function () {
console.log('Mixtra app listening on port 3000!')
})
When I send an invalid json body with POST request to localhost:3000/users the request goes to register.js and the validation code works there.
but strangely when I send valid JSON body, it says "Cannot POST /users" with a 404 Not Found HTTP status code and nothing in terminal log.
Note: I'm using postman to send the api requests.
It would be really great if someone could help me with this.
Thanks,
Joy
I don't see you using the jsonParser
You should use it before sending any json to it
app.use(jsonParser);
I have the following code:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }));
app.post('/rasp', function(req, res) {
res.send("received");
res.send(req.body.data);
});
app.listen(process.env.PORT || 5000);
I used POSTMAN to see if it worked and apparently the "received" text is sent back, but the data parameter is blank. What could be the problem?
Basically, the client sends a request and waits for a single response from your server. Once the client receives that response, it stops waiting for another. Furthermore, Express only allows you to send one response per request (going along with the client stuff explained above). You may be able to change this setting, but I've never dealt with it, so my answer will be limited to that knowledge.
Your server is executing res.send('received'); and the response is handled. You cannot call res.send again. You should be getting an error on your server when you attempt the second call.
You should send all data that the client needs in the first (and only) res.send().
Server responses should not be handled like logging (ex: sending 'received', 'analyzing', etc). Keep the logging separate. The client doesn't want to know all that extra info, it just wants the expected data response.
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }));
app.listen(process.env.PORT || 5000);
app.post('/rasp', function(req, res) {
res.send({received:true,data:req.body});
});
can you try this one and writing the response here
I believe your post body is "data=Some Value".
If you want to send multiple chunks of data, you should use res.write, and res.end. In your code change the following lines
res.send("received");
res.send(req.body.data);
to
res.write("received");
res.end(req.body.data);