POST request body not available in Express middleware 'req' - node.js

I have an odd query that has really stumped me.
I have created this Express middleware:
const express = require('express')
const bodyParser = require('body-parser')
var router = express.Router()
router.use(bodyParser.urlencoded({ extended: false }))
router.use(bodyParser.json())
app.use(router)
router.use((req, res, next) => {
console.log(req.body)
})
router.post((req, res) => {
...
})
Whever I try to log the body in the router.post, it logs the correct body. However, when I try to log it in the router.use (as shown above), it only returns an empty object. Any thoughts of how I can get the body in middleware? Thanks!

Only isssue I see according to the official documentation is that you've to set the router to the app after declaring all the middlewares as said in the below attached image,
which means you code should be changed to
const express = require('express')
const bodyParser = require('body-parser')
var router = express.Router()
router.use(bodyParser.urlencoded({ extended: false }))
router.use(bodyParser.json())
router.use((req, res, next) => {
console.log(req.body)
})
router.post((req, res) => {
...
})
//setting the router as a middleware after declaring all the routes and middleware functions.
app.use(router)
References:
Express Routing
Express Router API

Related

POST req body return empty array

i have a problem when POST some data in POSTMAN my problem is during "post" method /auth/login req.body return empty array.
Postman return empty object only if i use POST method with use form-data, if i change to xxx-www-form-urlencoded whatever works fine. I wanna know why it works so
const express = require('express');
const mongoose = require('mongoose');
const app = express();
require('dotenv').config();
const port = process.env.PORT || 5000;
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use("/static", express.static(__dirname + "/assets"))
app.post('/auth/login', (req, res) => {
res.status(200).json(req.body)
})
mongoose.connect("mongodb://localhost:27017")
.then(() => {
app.listen(port, () => {
console.log('port' + port)
})
})
I'm assuming you mean application/x-www-form-urlencoded instead of xxx-www-form-urlencoded and you mean multipart/form-data instead of form-data.
These 2 content-types are completely different encodings. When you called:
app.use(express.urlencoded({ extended: true }));
You added a middleware that can parse application/x-www-form-urlencoded, but that does not mean it automatically parses other formats too. It's only for that format, just like express.json() is only for the application/json format.
I solved this, i just created multer in my controller and it work how i wanted
const express = require('express');
const router = express.Router();
const { getUsers, createNewUser } = require('../controllers/newUser')
const path = require('path');
const multer = require('multer');
const upload = multer();
router.get('/', getUsers)
router.get('/:id', (req, res) => res.send('get single user'))
router.post('/', upload.none(), createNewUser)
module.exports = router;

Nodejs bodyParser.raw on one route

I have the following in my index.js:
app.use(bodyParser.json());
But Stripe webhooks want this:
Match the raw body to content type application/json
If I change my index.js to the following:
app.use(bodyParser.raw({type: 'application/json'}));
It works fine. But all my other API routes will not work anymore. Here is my route:
router.route('/stripe-events')
.post(odoraCtrl.stripeEvents)
How can I change to the raw body for only this api route?
You can access to both at the same time by doing this:
app.use(bodyParser.json({
verify: (req, res, buf) => {
req.rawBody = buf
}
}))
Now the raw body is available on req.rawBody and the JSON parsed data is available on req.body.
Divide them into two routers '/api' and '/stripe-events' and indicate bodyParser.json() only for the first one:
stripeEvents.js
const express = require('express')
const router = express.Router()
...
router.route('/stripe-events')
.post(odoraCtrl.stripeEvents)
module.exports = router
api.js
const express = require('express')
const router = express.Router()
...
router.route('/resource1')
.post(addResource1)
router.route('/resource2')
.post(addResource2)
module.exports = router
const stripeEventsRouter = require('./routers/stripeEvents';
const apiRouter = require('./routers/api';
apiRouter.use(bodyParser.json());
stripeEventsRouter.use(bodyParser.raw({type: 'application/json'}));
app.use('/api', stripeEventsRouter);
app.use('/api', apiRouter);

body parser logging empty object in express router

for some reason I can see my req.body in my express server on my route
req body is [Object: null prototype] { '{"password":"xxxxxxxx"}': '' }
but when I log req.body.password (the object key) I get
req body is undefined
here's my index router for reference in my express app
var express = require('express');
var router = express.Router();
var bodyParser = require('body-parser')
const path = require('path');
/* GET adminPanel. */
router.post('/authenticate', function(req, res, next) {
console.log('req body is',req.body.password)
res.send("passconfirmed");
});
module.exports = router;
To access the content of the body, Parse incoming request bodies in a middleware before your handlers, available under the req.body property.
You need to install a body-parser package.
npm i body-parser --save
Now import body-parser in your project.
It should be called before your defined route functions.
const express = require('express');
const router = express.Router();
const bodyParser = require('body-parser')
const path = require('path');
app.use(bodyParser.json());
app.use(bodyparser.urlencoded({ extended : true }));
/* GET adminPanel. */
router.post('/authenticate', function(req, res, next) {
console.log('req body is',req.body.password)
res.send("passconfirmed");
});
module.exports = router;
If you're using body-parser
You have to enable the body parser to work, before using parsed data in you routes.
In your main module where you import all your libs, you need to declare express to use body-parser middleware.
const express = require('express')
const bodyparser = require('body-parser')
const app = express()
app.use(bodyparser.json())
app.use(bodyparser.urlencoded({ extended : true }))
...
//here comes your routes
After including the bodyparser middleware you can use parsed data in your routes.
Notice that if you're using express version >= 4.16, body parser comes bundled with express. You just have to use change your code to:
const express = require('express')
const app = express()
app.use(express.json()); //this line activates the bodyparser middleware
app.use(express.urlencoded({ extended: true }));
Doing so you can safely remove body-parser package.

I cannot get /users json

I'm new to express and node js, I recently learned how to write API for express but at the end, I get some sort of problem which not resolved by me after several tries. I could not get a response on localhost:8080/users
src/routes/users.js
const { Router } = require("express");
const router = Router();
const getUsers = (req, res) =>
res.send(Object.values(req.context.models.users));
const getUser = (req, res) =>
res.send(req.context.models.users[req.params.userId]);
router.get("/users/", getUsers);
router.get("/users/:userId", getUser);
module.exports = router;
src/routes/index.js
const user = require("./user");
const message = require("./message");
module.exports = {
user,
message
};
src/index.js
const express = require("express");
const app = express();
// Custom Modules
const routes = require("./routes");
const models = require("./models");
// Application-Level Middleware Starts
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use((req, res, next) => {
req.context = {
models,
me: models.users[1]
};
console.log(req.context.models.users);
next();
});
// Used Routes
app.use("/users", routes.user);
app.use("/messages", routes.message);
// App Listning to HTTPS Module
app.listen(process.env.PORT);
You need to fix your endpoints in users.js:
router.get("/", getUsers);
router.get("/:userId", getUser);
The reason is because of app.use("/users", routes.user); in your index.js, where the endpoint for users is set. If you leave /users/ in users.js it would be localhost:8080/users/users/. Same problem might be with /messages.

Router.use() requires a middleware function but got a Object in my node file

New to Node, Please solve the error
Router.use() requires a middleware function but got a Object
const bodyParser = require('body-parser');
const express = require('express');
const app = express();
var productRoutes = require('./api/routes/product');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}))
app.use('/products', productRoutes);
module.exports = app;
api/routes/product.js:
const express = require('express');
const router = express.Router();
router.get('/', (req, res, next) => {
res.status(200).json({message: "Here we are handling the get request for the products"});
});
You change you api/routes/product code . will work fine.
const express = require('express');
const router = express.Router();
router.get('/', (req, res, next) => {
res.status(200).json({
message: "Here we are handling the get request for the products"
});
});
module.exports = router;
The reason was that you was not exporting your router to other file when you write module.exports = router; in file it will export.
app.use('/products', productRoutes);
productRoutes should be a function with this paramters (req, res, next). It could be something like this:
app.use('/products', function(req, res, next) {
// Do the things here
});
if you have any function like this in your productRoutes module, you could export that function and pass it as second parameter in app.use call
If you're refactoring your routes and controllers, it's possible that early in one of your controllers you may list all your routes
router.post('/', GetProducts);
router.post('/add', AddProduct);
followed by
module.exports = router; <-- middleware function
but you may have overlooked an existing module.exports (from before your refactoring) at the end of the controller, which exports all the controller's functions:
module.exports = { fxn1, fxn2, fxn3 }; <-- object
In that case, the later module.exports object would overwrite the earlier module.exports middleware function, and cause this error.

Resources