Request body is empty in Express route - node.js

I am building an API with Node.js, Express.js, and MongoDB. When I submit the form and use the req object in the route, the req.body object is empty.
req.body returns {} when I call the get_user function through the browser using postman at https://localhost:3000/users/0.
app.js:
var express = require('express'),
app = express(),
port = process.env.PORT || 3000,
bodyParser = require('body-parser');
var mongo_server = require('./server')
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
var routes = require('./routes/users')
routes(app);
app.use(function(req, res) {
res.status(404).send({url: req.originalUrl + ' not found'});
});
app.listen(port);
mongo_server.mongo_connection
module.exports = app;
userController.js:
var mongoose = require('mongoose'),
user = mongoose.model('users');
exports.get_user = function(req, res) {
console.log(req.body.id);
user.findById(req.body.id, function(err, user) {
console.log(req.body);
if(err)
res.send(err);
res.json(user);
});
};
userRoutes.js:
module.exports = function(app) {
var users = require('../controllers/userController');
app.route('/users/:userid')
.get(users.get_user);
}

I think you're confusing request parameters and request bodies. A request body is when you send information with the request like a payload, such as in a POST request when you send JSON to the server to, for example, create a new user:
{
"username": "jd123",
"email": "jd#example.com",
"name": "John Doe"
}
But in your case, you're looking for parameters, things passed through the URL like you've set up:
/users/:userid
That allows you to navigate to with a GET request:
/users/0
And then you can get the 0 as a string from req.params.userid not req.body.id. Request parameters and bodies are different. Parameters are for navigating to a varying route such as a user profile page, where the URL varies and reflects which route you want to go to by a user's ID.
Bodies are used for the payload of a request such as POSTing, PATCHing, and PUTing, giving information on what to update or create on the server.

Related

How do I grab json from an external api (serp api) from my backend and then make that same data available for my front end application?

Right now I have a front end react application using axios and and a backend server using node.js and express. I cannot for the life of me get my serp api data to post so that my front end can get it through axios and display the json data. I know how to get data to the front end but I am not a backend developer so this is proving to be incredibly difficult at the moment. I'm able to get the data from the the external api, I just don't know how to post it once I get it. Also I would not like to have all these request running on server.js so I created a controller but I think that is where it is messing up. Any help is appreciated
//pictures controller
const SerpApi = require('google-search-results-nodejs');
const {json} = require("express");
const search = new SerpApi.GoogleSearch("674d023b72e91fcdf3da14c730387dcbdb611f548e094bfeab2fff5bd86493fe");
const handlePictures = async (req, res) => {
const params = {
q: "Coffee",
location: "Austin, Texas, United States",
hl: "en",
gl: "us",
google_domain: "google.com"
};
const callback = function(data) {
console.log(data);
return res.send(data);
};
// Show result as JSON
search.json(params, callback);
//res.end();
}
// the above code works. how do i then post it to the server so that i can retrieve it to the backend?
module.exports = {handlePictures};
//server.js
const express = require('express');
const app = express();
const path = require('path');
const cors = require('cors');
const corsOptions = require('./config/corsOptions');
const { logger } = require('./middleware/logEvents');
const errorHandler = require('./middleware/errorHandler');
const cookieParser = require('cookie-parser');
const credentials = require('./middleware/credentials');
const PORT = process.env.PORT || 3500;
// custom middleware logger
app.use(logger);
// Handle options credentials check - before CORS!
// and fetch cookies credentials requirement
app.use(credentials);
// Cross Origin Resource Sharing
app.use(cors(corsOptions));
// built-in middleware to handle urlencoded form data
app.use(express.urlencoded({ extended: false }));
// built-in middleware for json
app.use(express.json());
//middleware for cookies
app.use(cookieParser());
//serve static files
app.use('/', express.static(path.join(__dirname, '/public')));
// routes
app.use('/', require('./routes/root'));
app.use('/pictures', require('./routes/api/pictures'));
app.all('*', (req, res) => {
res.status(404);
if (req.accepts('html')) {
res.sendFile(path.join(__dirname, 'views', '404.html'));
} else if (req.accepts('json')) {
res.json({ "error": "404 Not Found" });
} else {
res.type('txt').send("404 Not Found");
}
});
app.use(errorHandler);
app.listen(PORT, () => console.log(`Server running on port ${PORT}`));
//api/pictures.js
const picturesController= require('../../controllers/picturesController');
const express = require('express')
const router = express.Router();
// for POST request use app.post
router.route('/')
.post( async (req, res) => {
// use the controller to request external API
const response = await picturesController.handlePictures()
// send the response back to client
res.json(response)
})
module.exports = router;
You just need to return the result from SerpApi in your handlePictures function. To do this make a new Promise and when search.json runs callback do what you need with the results and pass it in resolve.
Your picturesController.js with an example of returning all results.
//pictures controller
const SerpApi = require("google-search-results-nodejs");
const { json } = require("express");
const search = new SerpApi.GoogleSearch(process.env.API_KEY); //your API key from serpapi.com
const handlePictures = async (req, res) => {
return new Promise((resolve) => {
const params = {
q: "Coffee",
location: "Austin, Texas, United States",
hl: "en",
gl: "us",
google_domain: "google.com",
};
const callback = function(data) {
resolve(data);
};
search.json(params, callback);
});
};
module.exports = { handlePictures };
Output:
And I advise you to change your API key to SerpApi to prevent it from being used by outsiders.
Since I don't have the full context of your App I can just assume the context. But given the fact that you already have wrapped the logic of calling the external API into a dedicated controller you can use it in the following way in an express app (used the hello world example from express):
// import your controller here
const express = require('express')
const app = express()
const port = 3000
// for POST request use app.post
app.get('/', async (req, res) => {
// use the controller to request external API
const response = await yourController.method()
// send the response back to client
res.json(response)
})
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
Here's an example how to execute the http request from the frontend:
const response = await fetch('http://localhost:3000') // result from res.json(response)

Unable to access the variable sent in POST

I sent a POST in my function to my server side (NodeJS), with the variable 'name'. 'name' is a string. However, I am unable to use this variable that I sent in the server-side.
I tried using req, req.body and req.body.name to access the variable I sent through POST. req gave me IncomingMessage {..}, req.body gave me {}, and req.body.name gave me undefined.
------Client Side------
var request = new XMLHttpRequest();
request.open("POST", "http://localhost:3000/addvoted", true);
request.send(name);
------Server Side------
app.post('/addvoted', function (req, res) {
var postBody = req.body;
console.log(postBody);
}
I expect the value of the variable name, which is a string, to be accessed in my server-side program.
I think this function send parameters via url,
try this code
req.query.name
replace name with variable name that you are sending
use npm body-parser
// create application/x-www-form-urlencoded parser
var bodyParser = require('body-parser')
var app = express()
var urlencodedParser = bodyParser.urlencoded({ extended: false })
// POST /login gets urlencoded bodies
app.post('/login', urlencodedParser, function (req, res) {
res.send('welcome, ' + req.body.username)
}``
Thank you.

req.body will not return a response

I've searched and tried other results, but none seem to render any results.
I'm trying to post data to the backend using postman as a test. The response is sending the 'success' message, but req.body returns an empty array every time I try. I'm using a node backend, with express and I'm trying to use routes. I've had success before, but for some reason I can't get it this time and my old code doesn't seem to work for this one. If I just log req, rather than req.body, I can see that the body is empty, the params are empty, but the url includes the params. I can post it, but it's rather long and I don't know if it's useful.
Here's the url I'm trying to hit: localhost:3000/?testParam=test&test=boop
app.js
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/blogTest', { useNewUrlParser: true });
mongoose.Promise = global.Promise;
const postsRoute = require('./routes/post');
app.use(postsRoute);
module.exports = app;
post.js
const express = require('express');
const router = express.Router();
const postModel = require('../models/post'); //not using this yet
router.get("/", function(req, res){
console.log("Getting Posts...");
postModel.find({}, function(err, posts){
if(err){
res.send("{'status': 'error', 'response': "+err+"}");
}
else if(posts.length < 1){
res.send("{'status': 'null', 'response': {}}");
}
else{
res.send("{'status': 'success', 'response': "+posts+"}");
}
});
});
router.post("/", function(req, res){
console.log(req.body);
res.send('success');
});
module.exports = router;
I'm expecting the console to log {'testParam': 'test','test':'boop'}
also, I've tried parsing req.body as json and stringifying it, but it causes the server to crash.
I think you are confused about http methods and how they work.
req.body is the POST request body, it is the data passed by the client when he sends a POST request to your api endpoint. If you are not sending any data in your POST request, then req.body will be empty.
In your example, to get the data from a request like localhost:3000/?testParam=test&test=boop you would need to look in req.params instead of req.body.
You need to try accessing the params variable of the request by code, trying to go through a log to find params might not be accurate therefore try
router.post("/", function(req, res){
console.log(req.params);
res.send('success');
});

Axios post request.body is empty object

I am trying to post data from my react. Backend - express.
Here is backend code:
var express = require('express');
var app = express();
var bodyParser = require("body-parser");
var methodOverride = require("method-override");
var mongoose = require("mongoose");
var expressSanitizer = require("express-sanitizer");
mongoose.connect("mongodb://localhost/blog-react");
//app config
app.set("view engine", "ejs");
app.use(express.static("public"));
app.use(bodyParser.urlencoded({extended: true}));
//must be after parser
app.use(expressSanitizer());
app.use(methodOverride("_method"));
//schema config
var blogSchema = new mongoose.Schema({
title: String,
image: String,
body: String,
//it should be date. With default value now.
created: {
type: Date, default: Date.now
}
});
var Blog = mongoose.model("Blog", blogSchema);
function handle500(response, error){
console.log(error.stack);
response.status(500);
response.json({error: "error: internal server error"});
}
app.post("/api/blogs", function(request, response){
var blog = {
title: request.sanitize(request.body.title),
image: request.sanitize(request.body.image),
body: request.sanitize(request.body.body)
};
console.log(request.body);
Blog.create(blog, function(error, newBlog){
if(error){
console.log("inside post handler ERROR")
handle500(response, error);
}
else{
console.log("inside post handler OK")
response.json({status: "success"});
}
});
});
React code:
var requestUrl = "/api/blogs";
var blog = {
title: "a",
image: "b",
body: "c"
}
axios.post(requestUrl, blog)
.then(function(response){
console.log("success",response.data)
})
.catch(function(response){
console.log("error", response);
});
When I post data via axios - request.body is always {}
But if I post data via regular form - all is correct - request.body contains all expected data.
What am I doing wrong with axios?
You are missing one middleware, bodyParser.json(). Add it to your configuration.
mongoose.connect("mongodb://localhost/blog-react");
app.set("view engine", "ejs");
app.use(express.static("public"));
app.use(bodyParser.json()); // <--- Here
app.use(bodyParser.urlencoded({extended: true}));
For people using Express>=4.16, bodyParser has been changed to the following:
app.use(express.json());
For me the issue was valid JSON format including double quotes on the variables.
This did not work
const res = await axios.post(serverPath + "/user/login", {
email: email,
password: password,
});
This DID work (with double quotes around email and password)
const res = await axios.post(serverPath + "/user/login", {
"email": email,
"password": password,
});
It looks like you only have two points left to make it work :
one : the http method should be set to POST instead of GET since you want to send something.
two : you can then add the http header (like what you did with the authorization header) Content-Type: 'application/json`
On the back-end don't forget to use some kind of body parser utility package like this one : body-parser and set it up with your app.
I suppose your server is using express, here is how you will do it with express :
const express = require('express');
const app = express();
const bodyParser = require('body-parser')
const jsonParser = bodyParser.json();
app.use(jsonParser); // use it globally
app.get('your_route', jsonParser, otherMiddleware, (req, res) => ...); // use it for specific routes
/* ... rest of your code */

How to capture (or log) the data of the Response object in Express?

I need to capture de sended data. I know how to set a middleware and capture the request and the response header.
I'm asking for capture the sent data.
I'm trying this:
var express = require('express')
var app = express();
var onFinished = require('on-finished')
app.listen(3000);
function logRes(res){
console.log('* captured response *')
console.log(res._header)
console.log(res.statusCode)
console.log(res.statusMessage)
console.log(res.body) // THIS DOES NOT WORKS!
}
app.use(function(req,res,next){
onFinished(res, function (err, res) {
logRes(res)
})
console.log('= captured request =');
console.log(req.method)
console.log(req.path)
console.log(req.query)
next();
});
app.get('/example',function(req,res){
res.header('Content-Type','text/plain');
res.end('example data');
});
Can any says to me how to look at the sent data in the line with the // THIS DOES NOT WORKS! comment?
You first need to include the third party middleware body-parser:
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.listen(3000);
app.use(bodyParser.json({ type: 'application/*+json' }));
app.use(function(req,res,next) {
console.log('= captured request =');
console.log(req.method);
console.log(req.path);
console.log(req.query);
console.log(req.body);
next();
});
app.get('/example',function(req,res) {
res.header('Content-Type','text/plain');
res.end('example data');
});
Check the repo and documentation here.

Resources