I'm current working on a web application using Node.js with Express in the back-end and React.js in the front end. In attempting to post user data to the Node server, through axios, I am running into an issue. When I make a post with the x-www-form-urlencoded content type, the front end will post to the server but the entire JSON of the posted data appears in the key field of the first element. When I change the content type to json it stops posting anything from the front end. I have tried cUrling to the server, and curling a JSON post will get accepted by the server.
React code to post to server
handleSubmit()
{
var form=this;
var axiosConfig = {
headers: {
'content-type': 'application/json; charset=utf-8'
}
}
axios.post('http://localhost:8080/api/login/', {
'username': form.state.username,
'password': form.state.password
}, {headers: {'content-type': 'application/json'}});
};
Server code for api endpoint
//From server.js
const express=require('express');
const session=require('express-session');
const bodyParser=require("body-parser");
const path = require('path');
var login = require('./routers/login')
var port = process.env.PORT || 8080;
var app=express();
app.use(session({'secret': 'thealphabetbackwardsiszyxwvutsrqponmlkjihgfedcba'}));
app.use(bodyParser.urlencoded({ extended: true}));
app.use(bodyParser.json());
//...
app.use('/api/login', login);
//from login.js
/* Router for login system
When user attempts to log in, check their credentials
If the user successfully logs in, create a session
If user enters invalid credentials prompt them
*/
const path = require('path');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
const user = require("./../models/UserSchema")
mongoose.connect('mongodb://localhost/newt');
const express = require('express');
const router = express.Router();
router.get('/', function (req, res)
{
console.log("Test");
})
router.post('/', function(req, res)
{
console.log(req.body);
res.end();
})
// To create test user use path localhost:8080/api/login/testing
router.get('/test', function (req, res)
{
var db = mongoose.connection;
var test = new user({
username: "joesephschomseph",
email: "testUser#test.com",
fname: "Joe",
lname: "Schmoe"
})
test.save();
console.log("Created test user!");
});
module.exports = router
npm install --save const body-parser
in app.js include const bodyparser = require('body-parser');
app.use(bodyparser.urlencoded({ extended: false }));
app.use(bodyparser.json());
remove the single quotes from your 'username' and 'password'
console.log(req.body);
Related
I am new to React and Node and I'm getting an undefined token in console when I add category I get undefined in the console. I am using cookie-parser.
server.js file:
const express = require('express');
const app = express();
const cors = require('cors');
const morgan = require('morgan');
const cookieParser = require('cookie-parser')
const connectDB = require('./database/db');
const authRoutes = require('./routes/auth');
const categoryRoutes = require('./routes/category');
//middleware
app.use(cors());
//dev specifies it is for development
app.use(morgan('dev'));
//express.json allows us to parse incoming request in json in the format of a json
app.use(express.json());
app.use(cookieParser());
app.use('/api/auth', authRoutes);
//route for category
app.use('/api/category', categoryRoutes);
connectDB();
app.get('/', (req,res) => {
res.send('Inside Server');
});
const port = process.env.PORT || 5000;
app.listen(port, ()=>console.log(`Listening on port ${port}`));
category.js (controller file)
exports.create = (req,res) => {
setTimeout(()=> {
res.json({
successMessage: `${req.body.category} was created!`
});
}, 5000);
};
category.js (routes file)
const express = require('express');
const router = express.Router();
const categoryController = require('../controllers/category');
const { authenticateJWT } = require('../middleware/authenticator');
router.post('/', authenticateJWT , categoryController.create);
module.exports = router;
authenticator.js (middleware file)
const jwt = require('jsonwebtoken');
const { jwtSecret } = require('../config/keys');
exports.authenticateJWT = (req, res, next) => {
const token = req.cookies.token;
console.log(token);
}
keys.js file
//it is gonna tell us/ signifying if we are live if in develoopment or in production
const LIVE = false;
if (LIVE) {
module.exports = require('./prod.js');
} else {
module.exports = require('./dev.js');
}
Console screen:
Instead of undefined i should be getting token.
Any help will be highly appreciated.
Thanks!
Is there a token Cookie available? (You can check using the inspector of your browser, normally in the „application“ tab. If you are sending the request using any tools like postman, curl, wget, …, you have to set the cookie first.)
Was the cookie available on any other routes? What’s the difference between these routes and the category route? Is it possible that your cookie is constrained to a specific path, e.g. to /api/auth? If so, adjust the path in res.cookie.
I've deployed my app to Heroku and it builds fine and my React app is rendering pages correctly. However, when I try to submit a POST request to sign up a user or log a user in, I get a 404 error. I do not, however, have this problem when submitting requests from Postman. My front end is using React and Axios for submitting requests. Server is using Nodejs and Express. I was thinking it had something to do with CORS, but I've tried configuring CORS and it hasn't resolved the issue.
Front-end code for POST request:
axios.defaults.withCredentials = true;
signUp: function(userInfo) {
userInfo = {
email: userInfo.email,
password: userInfo.password,
firstName: userInfo.firstName,
lastName: userInfo.lastName,
mobileNumber: userInfo.mobileNumber
}
return axios.post('/users/signup', userInfo);
Server file
const express = require('express');
const session = require('express-session');
const passport = require('./config/passport');
const path = require("path");
const cors = require('cors');
const cookieParser = require("cookie-parser");
const app = express();
const SequelizeStore = require('connect-session-sequelize')(session.Store);
const db = require('./models');
const sessStore = new SequelizeStore({
db: db.sequelize
});
const http = require('http').Server(app);
const routes = require('./routes');
const PORT = process.env.PORT || 3000;
const corsConfig = {
origin: "https://example.herokuapp.com/",
credentials: true
}
if (process.env.NODE_ENV === 'production') {
app.use(express.static('client/build'));
app.use(cors(corsConfig));
}
app.use(express.urlencoded({ extended: true }));
app.use(express.json());
app.use(session({
secret: process.env.SESSION_SECRET,
name: process.env.SESSION_NAME,
store: sessStore,
resave: false,
saveUninitialized: false }));
app.use(cookieParser());
app.use(passport.initialize());
app.use(passport.session());
app.use(routes);
app.get("*", function(req, res) {
res.sendFile(path.join(__dirname, "./client/build/index.html"));
});
db.sequelize.sync().then(() => {
http.listen(PORT, () => console.log(`Listening at http://localhost:${PORT}`));
});
Routes index file
const router = require("express").Router();
const usersRoutes = require('./users');
const isAuthenticated = require('../../config/middleware/isAuthenticated');
router.use("/users", usersRoutes);
Users Routes file
const router = require("express").Router();
const passport = require('../../config/passport');
const usersController = require("../../controllers/usersController");
router
.route('/signup')
.post(usersController.createNewUser);
router
.route('/login')
.post(passport.authenticate('local'), usersController.logUserIn);
Controller
createNewUser: function(req, res) {
db.User.create({
email: req.body.email,
password: req.body.password,
firstName: req.body.firstName,
lastName: req.body.lastName,
mobileNumber: req.body.mobileNumber
})
.then(() => res.sendStatus(200))
.catch((err) => res.send(err));
}
I resolved this. The url in the axios call was missing a piece. The reason this worked locally is because I had the proxy in React set to include the missing piece so axios calls done locally were always being sent to the right url, but they were not being sent to the right url in prod. Really relieved it was something so simple!
I'm trying to send a json to my nodeJs app through POST Method in body.
For that I'm using POSTMAN to create the request, with the proper consnt-type header and body JSON Rows. Tho the message back is "OK" in console the req.body is {} empty.
Would you have an idea what's wrong in my code?
const bodyParser = require('body-parser');
const { Client } = require('pg');
const express = require('express');
const app = express();
// create application/json parser
const jsonParser = bodyParser.json()
// create application/x-www-form-urlencoded parser
const urlencodedParser = bodyParser.urlencoded({ extended: false })
const hostname = '127.0.0.1';
const port = 3000;
const dbSchema = 'public';
const client = new Client({
user: 'postgres',
host: 'localhost',
database: 'postgres',
password: '123123',
port: 5432,
});
client.connect();
/* =========== Some Initialize staff =============== */
// parse various different custom JSON types as JSON
app.use(bodyParser.json({ type: 'application/*+json' }))
app.use(bodyParser.urlencoded({
extended: true
}));
app.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
/* =========== FROM HERE =============== */
app.post('/post-test', urlencodedParser, (req, res) => {
console.log('Got body:', req.body);
res.sendStatus(200);
});
app.get('/',(req,res)=>{
res.status(200).send('Get Ready for something awesome!\n');
});
enter image description here
You should use app.use(bodyParser.json());, in your code const jsonParser = bodyParser.json() this is not used.
Update: Or you can apply jsonParser middleware directly to the post route:
app.post("/post-test", jsonParser, (req, res) => {
console.log("Got body:", req.body);
res.json({ ...req.body });
});
Can't figure what is happening so, I am posting the code that works for me -
let express = require('express');
let app = express();
const authorRoute = express.Router();
authorRoute.use(express.json());
authorRoute.use(express.urlencoded({extended:true}));
authorRoute.post('/post-test', async (req, res) => {//req.body});
app.use(authorRoute);
Also, make sure to test with a well-formed JSON.
version "express": "^4.17.1",
I built an index.js file which sends SMS based on body input while posting with Postman. The code is working and looks like this (I have hidden my apiKey and apiSecret for this preview)
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
const Nexmo = require('nexmo');
const nexmo = new Nexmo({
apiKey: 'hidden.apiKey',
apiSecret: 'hidden.apiSecret'
});
app.post('/send', (req, res) => {
// Sending SMS via Nexmo
nexmo.message.sendSms(
'4542542445', req.body.toNumber, req.body.message, {type: 'unicode'},
(err, responseData) => {if (responseData) {console.log(responseData)}}
);
});
const server = app.listen(3000);
console.log("starting server")
It woks fine and I receive an SMS message when I run the file, and a post to the route using Postman.
I am trying to implement the same in my bigger project, where I have separate client and server folders representing my frontend and backend.
When I add the code to my app.js file, I run into Status code 404 not found error. Here is the code of my app.js:
const express = require('express')
const bodyParser = require('body-parser')
const cors = require('cors')
const morgan = require('morgan')
const {sequelize} = require('./models')
const config = require('./config/config')
const Nexmo = require('nexmo')
const app = express()
app.use(morgan('combined'))
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false}))
app.use(cors())
require('./routes')(app)
sequelize.sync()
.then(() => {
app.listen(config.port)
console.log(`Server started on port ${config.port}`)
})
const nexmo = new Nexmo({
apiKey: 'hidden.apiKey',
apiSecret: 'hidden.apiSecret'
}, {debug: true})
app.post('/send', (req, res) => {
// Sending SMS via Nexmo
nexmo.message.sendSms(
'4542542445', req.body.toNumber, req.body.message, {type: 'unicode'},
(err, responseData) => {if (responseData) {console.log(responseData)}}
);
});
I am asking for help to try figure out what is wrong and why it does not hit the route, instead returning status code 404.
I can share my github or we can talk on discord: soko#8667
I appreciate your thoughts and help.
Routes in express should be written :
let route = require('routes');
app.use('/', route);
I managed to make it work.
I was adding new route while my server was running.
I restarted my PC and ran server and client again and it seems work.
I am testing an express API with supertest. I am trying to pass in body parameters into the test, as can be seen in the code snippets below, but it appears that the body parameters don't get passed in correctly since I get an error message that the body parameters are undefined.
Running the test with command mocha --recursive returns the following error:
Cannot read property 'email' of undefined
Below is the code from file email-suite.js referencing supertest
'use strict';
var express = require("express");
var bodyParser = require('body-parser');
var mongoose = require("mongoose");
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
var supertest = require("supertest");
var chai = require("chai");
var should = chai.should();
var api = require("../server.js");
describe("Email Module", function() {
this.timeout(25000);
before(function(done){
mongoose.createConnection(/* connectionstring */);
mongoose.connection.on('open', function(err) {
if(err) console.log(err);
console.log('connected to server');
});
done();
});
it("Check Email Count", function(done) {
var body = { email: "email#email.com" };
supertest(api)
.post("/emailCount")
.set('Accept', 'application/json')
.send(body) // body is undefined
.expect(200)
.expect('Content-Type', /json/)
.end(function(err, res) {
if(err) return done(err);
res.body.count.should.equal(2);
done();
});
});
});
Below is the code from file email-api.js
'use strict';
var express = require("express");
var bodyParser = require('body-parser');
var router = express.Router();
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
router.post('/emailCount', function(req, res) {
var email = req.body.email; // req.body is undefined
}
module.exports = router;
Below is the code from the file server.js
var express = require("express");
var app = express();
app.set("port", process.env.PORT || 3000);
var router = require("./user/email-api");
app.use('/', router);
app.listen(app.get("port"), function() {
console.log("App started on port " + app.get("port"));
});
module.exports = app;
Put body-parser always after express object and before every routes in main server file like this
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
//Router task start from here
Other wise always will get undefined since router call first and body parsed later.
Thank you abdulbarik for your answer. I want to add some extra information to aid clarity in case people are still getting undefined values for the request body object, and if (as in my case) your routers and tests are setup differently.
Here is the router that we shall test:
// router.js
const express = require("express");
const router = express.Router();
router.post("/", (req, res) => {
res.json({ success: true, data: req.body });
});
module.exports = router;
The following test code will result in the request body being undefined, and thus the test failing:
// router.test.js
const express = require("express");
const request = require("supertest");
const bodyParser = require("body-parser");
// set up the test app - this will fail
const app = express();
app.use("/routerPath", require("./router")); // this will cause the test to fail, as the router should be setup after the body-paser
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// run the test
it("successful response", async () => {
const response = await request(app)
.post("/routerPath")
.send({
firstname: "John",
lastname: "Smith",
})
.set("Accept", "application/json");
expect(response.status).toEqual(200);
expect(response.body).toEqual({
success: true,
data: {
firstname: "John",
lastname: "Smith",
},
});
});
The reason why, as explained by abdulbarik, is that the body-parser code should always be before the router code, so that the parser runs before the router. To make the test pass, simply swap these lines around:
// set up the test app - this will work now
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use("/routerPath", require("./router")); // the router setup should happen after the body-parse setup
I hope that is a helpful clarification.