react axios cros body empty - node.js

Working on my first MERN app. When I'm trying to call my backend api, it seems that the body content is lost. But it works correctly using Postman. So I guess I have something wrong with my CORS.
Bellow my Frontend and Backend code:
Frontend - login.jsx
import axios from 'axios';
...
axios.get(process.env.REACT_APP_API_URL+'/auth/login'
, {username: 'demo', password: '1234567'}
).then(user => {
console.log(user);
}).catch(error =>{
console.log(error);
});
Backend - index.js
const express = require('express');
const bodyParses = require('body-parser');
const cors = require('cors');
const authRoute = require('./routes/auth');
const app = express();
app.use(bodyParses.json());
app.use(bodyParses.urlencoded({ extended: true }));
app.use(cors());
app.use('/api/auth', authRoute);
...
Backend - auth.js
const rooter = require('express').Router();
rooter.get('/login', async (req, res) => {
console.log('*** req.body:', req.body);
...
}
I got this message in the browser console:
GET http://localhost:5000/api/auth/login 401 (Unauthorized) xhr.js:210
And on the backend side I got this
*** req.body: {}
Any help would be appreciated.

GET requests with axios don’t support a body, change it to a POST:
rooter.post('/login', async (req, res) => {
console.log('*** req.body:', req.body);
axios.post(process.env.REACT_APP_API_URL+'/auth/login'

Related

Why is my post route not running properly in Express app?

I am trying to add a route to '/signup' in my express application. But, every time I am sending a post request to the server it is resolving in "No response". Whereas the '/' route is working. Where have I gone wrong with the code?
index.js
import dotenv from "dotenv";
import cors from "cors";
import morgan from "morgan";
import dbConnect from "./config/dbConnect.js";
import { authRoute } from "./routes/auth.js";
dotenv.config();
const port = process.env.PORT;
const DATABASE_URI = process.env.DATABASE_URI;
const app = express();
dbConnect();
app.get("/", (req, res) => {
res.sendStatus(200);
});
app.use(express.json());
app.use(cors());
app.use(morgan("combined"));
app.use("/api/v1", authRoute);
app.listen(port, () => {
console.log(`Server running at ${port}...`);
});
auth.js
import { Router } from "express";
const router = Router();
router.post("signup", (req, res) => {
const password = req.body.password;
console.log(password);
});
export { router as authRoute };
dbConnect.js
import mongoose from "mongoose";
import dotenv from "dotenv";
dotenv.config();
const DATABASE_URI = process.env.DATABASE_URI;
const dbConnect = () => {
mongoose.set("strictQuery", false);
mongoose
.connect(DATABASE_URI)
.then(() => {
console.log("connected");
})
.catch((error) => {
console.error(error);
});
};
export default dbConnect;
router.post("signup", (req, res) => {
const password = req.body.password;
console.log(password);
});
The client doesn't get a response because you haven't written any code to send a response.
You completely ignore the object passed to res.
You don't call res.json or res.render or res.send or any of the other methods that would send a response.
Seems like the problem was with my VSCode extension RapidApi client, tried using insomnia and it worked out fine. Sorry for the trouble!

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)

When I run the server, it gives me a message "Cannot GET /". What am I doing wrong?

I am trying to do a GET request in order to retrieve some images from my Cloudinary account. But when I run the server, I get a 400 status code on my UI with reading
Cannot GET /
How can I solve this issue?
const express = require('express');
const dotenv = require('dotenv');
const cors = require('cors');
const { json } = require('body-parser');
const axios = require('axios');
const app = express();
app.use(cors());
app.use(json());
const { parsed: config } = dotenv.config();
const BASE_URL = `https://api.cloudinary.com/v1_1/${config.CLOUD_NAME}/resources/image`;
const auth = {
username: config.API_KEY,
password: config.API_SECRET,
};
app.get('/photos', async(req, res) => {
const response = await axios.get(BASE_URL + '/resources/image', {
auth,
params: {
next_cursor: req.query.next_cursor,
},
});
return res.send(response.data);
});
app.get('/search', async (req, res) => {
const response = await axios.get(BASE_URL + '/resources/search', {
auth,
params: {
expression: req.query.expression,
},
});
return res.send(response.data);
});
const PORT = 7000;
app.listen(PORT, console.log(`Server running on port ${PORT}`));
If you open your server URL in browser you will get Cannot GET / because you don't have base route.
It's not needed in most cases, since you don't access your node server from browser, it just run's in the background.
You generally display your frontend (Angular, React) in browser.
But if you don't like the message you can add a base route.
app.get('/', (req, res) => res.send('Hello World'));
I'm not sure what are you trying to achieve, but at least you won't get this error.

Middleware that checks token, cannot redirect to login page

I am using node and express with vue. I try to implement a middleware for my node routes, to check the login token and if it is wrong, redirect to the login page.
This is my code so far.
Main app.js file
const express = require('express');
const path = require('path');
const cors = require('cors');
const http = require('http');
const bodyParser = require('body-parser');
const app = express();
app.use(cors());
app.use(express.static(path.join(__dirname,'public')));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended:false}));
app.use(express.json());
app.use(express.urlencoded({extended:false}));
app.use('/login', require('./routes/login'));
app.use('/performance', require('./routes/performance'));
const port = 4000;
http.createServer(app).listen(port, ()=>{
console.log('server runs on port ', port);
});
Then in my routes I have
const express = require('express');
const token = require('../../lib/token');
router.get('/:product/dataquality/', token.validate(), (req, res)=>{
const product = req.params.product;
db.dataquality(product)
.then((resolved)=>{
console.log('route dataquality result', resolved);
res.json({success:true, data:resolved});
})
.catch((error)=>{
console.log('route dataquality error', error);
res.json({success:false, data:false});
});
});
And this token.validate middleware is
const jwt = require('jsonwebtoken');
const config = require('../db/config');
const validate = ()=>{
return (req, res, next)=>{
const token = req.get('Authorization');
const key = config.key;
jwt.verify(token, key,function(err, decoded) {
if (err){
console.log('token error');
res.redirect('/login');
}
if (decoded){
console.log('token ok');
next();
}
});
}
}
exports.validate = validate;
This works fine and I see the token console logs when I login in my app. If I go to the browser and edit the token (delete a couple of characters, but not completely remove it) so the token is there but is the wrong token, it has the wrong value :
I see in my console token error and I get no data, but the redirect to login page never happens.
If I do res.redirect('http://localhost:8080/login'); I still get no redirect.
What am I missing? How can I fix this?
If you think this is a Vue issue, let me know, so I can provide Vue routing code.
Thanks
EDIT
This the file that handles routes in Vue - router.js
import Vue from 'vue'
import Router from 'vue-router'
import store from '#/components/store';
import Login from './components/Login.vue'
import Performance from './views/Performance.vue'
Vue.use(Router)
const router = new Router({
mode: "history",
base: process.env.BASE_URL,
routes: [
{
path: '/login',
name: 'login',
component: Login,
},
{
path: '/performance',
name: 'performance',
component: Performance,
beforeEnter: (to, from, next) => {
if (store.state.login.token == null || !store.state.login.token) {
next('/login');
}
else{next();}
}
},
{
path: '*',
redirect: '/login'
}
]
})
router.beforeEach((to, from, next) => {
store.dispatch('resetAccessToken');
if (to.fullPath === '/performance') {
if (!store.state.login.token) {
console.log('VUE route go to login');
next('/login');
}
}
if (to.fullPath === '/login') {
if (store.state.login.token) {
console.log('VUE route browse normally');
next('/performance');
}
}
next();
});
If I search for "route" in my browser console to find console.log('VUE route go to login'); or console.log('VUE route browse normally'); it says it found 160 but I cannot see none.
I still get no data, but I can browse normally to empty Vue pages. Node or Vue redirect should work and send me to login , but none works, so I still can browse around.
Thanks

Cannot GET /api/signup - Using Postman and mongodb

I am very new to mongoose and I made one signup api and while testing it using POSTMAN I'm getting these weird error as well when I refresh my http://localhost:8000/api/signup I get a message saying "Cannot GET /api/signup" and in my postman post request I am seeing an error message that says "Cannot POST /api/signup".
How would I get rid of these messages that are being displayed?
I am following a tutorial so I tried copying and pasting the code from the GitHub to make sure everything was perfect but I was still seeing these error messages.
My app.js file is:
const express = require("express");
const mongoose = require("mongoose");
const morgan = require("morgan");
const bodyParser = require("body-parser");
const cookieParser = require("cookie-parser");
require("dotenv").config();
// import routes
const userRoutes = require("./routes/user");
// app
const app = express();
// db
mongoose
.connect(process.env.DATABASE, {
useNewUrlParser: true,
useCreateIndex: true
})
.then(() => console.log("DB Connected"));
// middlewares
app.use(morgan("dev"));
app.use(bodyParser.json());
app.use(cookieParser());
// routes middleware
app.use('api', userRoutes);
const port = process.env.PORT || 8000;
app.listen(port, () => {
console.log(`Server is running on port ${port}`);
});
my routes/users.js file is:
const express = require("express");
const router = express.Router();
const { signup } = require("../controllers/user");
router.post("/signup", signup);
module.exports = router;
my controllers/users.js is:
const User = require("../models/user");
exports.signup = (req, res) => {
console.log("req.body", req.body);
const user = new User(req.body);
user.save((err, user) => {
if (err) {
return res.status(400).json({
error
});
}
res.json({
user
});
});
};
I am hoping to see a response in my browser that does not display an image that image that says Cannot GET api/signup and I am hoping that Postman is able to return data from my api
It means there is no corresponding router setting to /api/signup
I think router.post("/signup", signup); should be router.post("/api/signup", signup);
This should work fine on PostMan.
But the browser url is a get request, so the request would still fail. You will need to send the post request by javascript then.
For example, something like :
fetch('/api/signup', {
method: 'POST',
body: 'signup data here'
})
.then(response => response.json());
Please let me know if the error still exist.
There is a minor bug
app.use('api', userRoutes);
change to
app.use('/api', userRoutes);
My issue was that when I installed mongoDB locally I had not properly installed it and was not using a /data/db folder. I was able to fully uninstall my older version of mongoDB and reinstall everything following this youtube tutorial: https://www.youtube.com/watch?v=MIByvzueqHQ

Resources