body undefined on axios post request - node.js

I have this endpoint on backend (node, express):
router.post('/createUser', (req, res, next) => {
try{
const { user } = req.body;
if(!user) next(createError(401))
data.push(user);
res.status(200).json(user)
} catch(e) {
next(e)
}
})
and this on front (service)
class EmployeeService {
constructor() {
this.api = axios.create({
baseURL: process.env.REACT_APP_BACK_DOMAIN || 'http://localhost:4000',
withCredentials: true
})
}
getPaginated = (page, size) => this.api.get(`/?page=${page}&size=${size}`).then(({data}) => data)
createUser = user => this.api.post('/createUser', user).then(({data}) => data)
}
When i receive createUser Request, i take body from req, but it is undefined, i console log "req" and this returned me an incoming message object Why? i need to receive body for push on array :(
the object that i create on front:

It seems to me that you are sending the user object wrong, Try this:
user = {id:1,name:"nombre"}
createUser = this.api.post('/createUser', user).then(({data}) => data)
And check if the body arrives to backEnd

This is let answer but...
As you mention you are receiving an object but not able to excess data though req.body
server API and Axios working fine then the problem is parser
try adding parser as shown below and make sure it is before app.use("/", router)
const express = require('express');
const app = express();
var router = express.Router();
// create application/x-www-form-urlencoded parser
app.use(express.urlencoded({ extended: false }));
// parse application/json
app.use(express.json());
app.use("/", router);
for more information check this
Express.js req.body undefined

Related

How to pass request body object to other routes?

Anyone know the solution? When I console log the variable it shows undefined. I need to pass the req.body (name and email) element to second post route which is "/company" route. I have two forms and I want to pass the first form data to second form the "/company" route form. then the two form data will be stored in mongoDb. I tried everything but I got only undefined in second route the "/company" route
import express from "express";
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
//Assign the name and email to variable and sent to last route
const middleware = (req, res, next) => {
const { name, email } = req.body;
let nameNew = name;
let emailNew = email;
// add nameNew and emailNew to req object
// so that it can be access in other routes
req.nameNew = nameNew;
req.emailNew = emailNew;
// console.log(nameNew);
// console.log(emailNew);
next();
};
//Get name email from user input and sent it middleware
app.post("/", middleware, (req, res, next) => {
const { name, email } = req.body;
res.send("Home route");
});
//Get the name and email from middleware
app.post("/company", middleware, (req, res) => {
// console.log(nameNew);
// access req.body without middleware
// console.log(req.body);
// access req.body using middleware
console.log(req.nameNew);
console.log(req.emailNew);
res.send("Company route");
});
//Server running
app.listen(4000, () => {
console.log(`Server Started `);
});
When your request gets into your app.post("/") it sets the nameNew variable inside your middleware scope. You cannot access this variable in your other routes.
If you want to access variables shared from your middleware you can use res.locals : https://expressjs.com/en/api.html#res.locals
You can't pass data from route 1 to route 2 through middleware.
It passes through the middleware and sets the variables but on your res.send theses variable will disappear. These are just set for the "instance" of the incoming request and on res.send will be destroyed.
You would need to send back data to the front-end to pass it back to your API for route 2.
You can call functions from your route definition :
app.get('/getUserInfos', isLoggedIn, (req, res) => {
return getUserInfos(res);
});
This way you can process your data and save it however you want.
Also, looks like you can chain functions there : https://stackoverflow.com/a/62723674/12343548
I use req.app.locals to send the data in first route to second route. Anyone want to do this type of program in future Here is the solution.
const express = require("express");
const app = express();
const path = require("path");
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
const middleware = (req, res, next) => {
const { name, email } = req.body;
req.app.locals.nameNew = name;
req.app.locals.emailNew = email;
next();
};
app.get("/", (req, res) => {
res.sendFile(path.join(__dirname + "/index.html"));
});
app.post("/", middleware, (req, res) => {
const { name, email } = req.body;
res.send("Home Route");
});
app.get("/company", (req, res) => {
res.sendFile(path.join(__dirname + "/company.html"));
console.log(req.app.locals.nameNew);
console.log(req.app.locals.emailNew);
});
app.post("/company", (req, res) => {
console.log(req.app.locals.nameNew);
console.log(req.app.locals.emailNew);
res.send("Company Route");
});
//Server running
app.listen(4001, () => {
console.log(`Server Started `);
});

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)

Cannot GET a post request in node js with axios

i get a Cannot GET /api/auth/signup error every time i try to POST i cant figure it out why
can someone help me with this thanks very much i dont understand what im missing im tryning to post the register in the node js but it keeps telling me Cannot GET /api/auth/signup
auth.js
import axios from "axios";
const API_URL = "http://localhost:8080/api/auth/";
class AuthService {
async login(username, password) {
console.log(username, password);
return axios
.post(API_URL + "signin", {
username,
password,
})
.then((response) => {
if (response.data.accessToken) {
localStorage.setItem("user", JSON.stringify(response.data));
}
return response.data;
});
}
async logout() {
localStorage.removeItem("user");
}
async register(username, email, password) {
return axios.post(API_URL + "signup", {
username,
email,
password,
});
}
getCurrentUser() {
return JSON.parse(localStorage.getItem("user"));
}
}
export default new AuthService();
server.js
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const app = express();
var corsOptions = {
origin: "http://localhost:8080",
};
app.use(cors(corsOptions));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// simple route
app.get("/", (req, res) => {
res.json({ message: "it works." });
});
// set port, listen for requests
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}.`);
});
It appears you are attempting to POST to a route that doesn't exist. You will need to build out your /api/auth/signup route in order to send a request to it from axios.
// simple example of post route
app.post("/api/auth/signup", (req, res) => {
const { username, email, password } = req.body;
// Your logic to register user in your database
// Send response after database interaction
res.status(201).json({ message: 'User signed up for service' })
});
For each Specific route you need to implement respective route in your application.
In your application, if you need to have access to two post request of different url, you need to handle two post route.
For`/api/auth/signin`
app.post('/api/auth/signin', (req, res)=>{
//Your Implementation here
res.status(201).json({message: 'Your Message'})
})
For`/api/auth/signup`
app.post('/api/auth/signup', (req, res)=>{
//Your Implementation here
res.status(201).json({message: 'Your Message'})
})

req.body return empty object when i send my formdata in express.js

My problem is a bit tricky one. I know everyone will say bodyparser for solution but i used bodyparser as well but I get still same error.
this is my back end server.js
const fs = require('fs')
const path = require('path')
const express = require('express') // We import express module in our project.
const app = express() // We assign express's functions to app variable.
const bodyParser = require('body-parser') // BodyParser catches data from the http request(POST,PATCH,PUT) and parsing this data to JSON object.
const HttpError =require('./models/HttpError')
const mongoose = require('mongoose')
const userRouter = require('./routes/user-routes')
const recipeRouter = require('./routes/recipe-routes')
const mealPlanRouter = require('./routes/mealplan-routes')
app.use(bodyParser.json())
app.use(
bodyParser.urlencoded({
extended: true
})
);
// We catch data from request and turn this data to json object with BodyParser.
app.use('/uploads/images', express.static(path.join('uploads','images'))) // We create middleware for uploading images and we called this middleware here.
app.use((req, res, next) => { // We need to write this middleware. Because We decide to how to get a request from the client.This is like protocol between server and client for the communication.
res.setHeader('Access-Control-Allow-Origin','*')
res.setHeader('Access-Control-Allow-Headers',
'Origin, X-Request-With, Content-Type, Accept, Authorization'
)
res.setHeader('Access-Control-Allow-Methods','GET, POST, PUT, DELETE')
next()
})
app.use('/api/users',userRouter)
app.use('/api/recipes',recipeRouter)
app.use('/api/mealplans',mealPlanRouter)
app.use((req, res, next) => { // When the client try to access wrong routes. We need to say the client is going wrong way.
const error = new HttpError('Could not find this route', 404)
throw error
})
app.use((err,req,res,next) => { // We check if user pick file for importing an image.
if(req.file){
fs.unlink(req.file.path, err => {
console.log(err)
})
}
if(res.headerSent){
return next(err)
}
res.status(err.code || 500)
res.json({message:err.message || 'Unknown error occured'})
})
// We connect our project with database. Mongoose communicate with database and we communicate with mongoose. This way is more secure.
mongoose
.connect(`mongodb+srv://${process.env.DB_USER}:${process.env.DB_PASSWORD}#cluster0-vvtq0.mongodb.net/${process.env.DB_NAME}?retryWrites=true&w=majority`,{ useNewUrlParser: true, useUnifiedTopology: true})
.then(() => {
app.listen( process.env.PORT || 5000, () => {
console.log('The Server is running')
})
})
.catch(err => {
console.log(err)
})
this is where i send formdata. I check my formdata from network tab. It seems fine. when i check my formdata with req.body in my server.js returns empty object.
const handleSubmit = async e => {
e.preventDefault()
const datestr = (new Date(startDate)).toUTCString();
try{
const formData = new FormData()
formData.append('title',formState.inputs.title.value)
formData.append('date',datestr)
formData.append('timeFrame',formState.inputs.timeFrame.value)
formData.append('targetCalories',formState.inputs.targetCalories.value)
formData.append('diet',formState.inputs.diet.value)
formData.append('exclude',excludeData.join())
formData.append('creator',auth.userId)
const responseData = await axios.post(
process.env.REACT_APP_BACKEND_URL+'/mealplans/new',
formData,{
headers: {Authorization : `Bearer ${auth.token}`} })
console.log(responseData)
}
catch(err){
console.log(err.message)
}
}
Thanks from now for your helps.
FormData objects get converted to Multi-part request bodies.
You need a body parser capable of handling that data format. You only have body parsers for JSON and URL encoded data.
The body-parser module homepage recommends 4 modules which support Multi-part bodies.

Getting back empty response body when making a POST request using Angular + Express

I'm trying to make a simple POST request but I'm getting an empty response back from the server. I've sifted through all the SO questions regarding this topic and tried the solutions posted but to no avail.
I've tried changing the request header options to use 'application/x-www-form-urlencoded' and set bodyParser in my express app as app.use(bodyParser.urlencoded({ extended: true })); but that didn't work either.
auth-service.service.ts
login(loginInfo: object) {
return this.http.post<loginInfo>(this.loginUrl, { "test": "test" })
.pipe(
catchError(this.handleError)
);
}
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
console.log('An error occured:', error.error.message);
} else {
console.log(`Backend returned code ${error.status}, ` +
`body was ${error.error}`);
}
return throwError('Something bad happened; please try again later.')
}
login.component.ts (calls the login service method)
onSubmit() {
const loginInfo = { username: this.username.value, password: this.password.value };
this.authService.login(loginInfo).subscribe(
resp => { console.log(resp); },
err => { console.log(err); }
)
}
server.js (I've defined routes here but they're not relevant)
const express = require('express');
const bodyParser = require('body-parser');
const api = require('./routes/api');
const app = express();
const port = process.env.port || 3000;
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
next();
})
app.use(bodyParser.json());
app.use('/api', api)
app.get('/', function (req, res) {
res.send(JSON.stringify('Hello from server'));
})
app.post('/login', (req, res) => {
let userData = req.body
res.send('Request body: ' + JSON.stringify(userData));
})
app.listen(port, function () {
console.log('Server running on localhost: ' + port);
});
I'm console logging the following:
Backend returned code undefined, body was undefined
Something bad happened; please try again later.
When I try using Postman, however, I get the response I expect (i.e. Request body: {})
I'm not sure as to why a response is retrieved when done through Postman but not when done through the app.
Any help is appreciated. Thanks!
You need to set body for POST request in auth-service.service.ts:
import { HttpParams } from '#angular/common/http';
login(loginInfo: object) {
const body = new HttpParams()
.set('test', 'test');
return this.http.post<loginInfo>(this.loginUrl, body)
.pipe(
catchError(this.handleError)
);
}
try using express.json its missing
app.use(express.json());
and
app.use(bodyParser.urlencoded({
extended: true
}));

Resources