Reciving empty file objects from frontend to backend React and NodeJS - node.js

Hi I'm trying to upload a file to a server send with axios. To send it I use react with Hooks and UseState, the thing is that when I do the console.log of the file in de frontend it shows all correctly but when I send it to backend I recive it empty.
Here is an example about what shows the frontend with console.log():
Here is the function I use to send the 3 files to backend and the differents things like react Hooks and that which I need:
const [weight, setWeight] = useState("");
const [frontPhoto, setFrontPhoto] = useState({});
const [sidePhoto, setSidePhoto] = useState({});
const [backPhoto, setBackPhoto] = useState({});
const JWT = new ClassJWT();
const axiosReq = axios.create();
const [uploadErrors, setUploadErrors] = useState([{}]);
const upload = async (e) => {
e.preventDefault();
await JWT.checkJWT();
console.log(frontPhoto);
axiosReq.post("http://localhost:3001/upload-progress", {
weight,
frontPhoto,
sidePhoto,
backPhoto,
token: JWT.getToken()
}).then((response) => {
console.log(response);
if (response.data.statusCode === '200') {
} else {
}
});
};
And then, in the backend de console.log() is like this:
{
weight: '70',
frontPhoto: {},
sidePhoto: {},
backPhoto: {},
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiaWF0IjoxNjI2NTk3Mjg1LCJleHAiOjE2MjY1OTgxODV9.njDz7BZX57NvAK399abQLhoelpTS4kStj4LBzjw5gR8'
}
Here is the router code I use to this upload:
routerProgress.post("/upload-progress", verifyJWT, async (req, res) => {
console.log(req.body);
}
And here is all the server configuration:
import express from 'express';
import sequelize from './db/db.js';
import cors from 'cors';
import fileUpload from 'express-fileupload';
// SERVER CONFIGURATION
const app = express();
const PORT = process.env.PORT || 3001;
app.listen(PORT, () => {
console.log(`Listening at ${PORT}`);
sequelize.sync({ force: false })
.then(() => console.log('Database Connected!'))
.catch(err => console.log(err));
});
// BODYPARSER
app.use(express.json({limit: '50mb'}));
app.use(express.urlencoded({ limit: '50mb', extended: true, parameterLimit: 50000}));
app.use(cors({
origin: ["http://localhost:3000"],
methods: ["GET", "POST"],
credentials: true
}));
app.use(fileUpload({
createParentPath: true
}));
// ROUTES
import { routerAuthentication } from './routes/authentication.js';
import { routerProgress } from './routes/progress.js';
app.use(routerAuthentication);
app.use(routerProgress);
I don't know how to solve it, I tried many things but anything doesn't word. Please if anyone know what can I do to solve it, I'll be very grateful with him. Thanks!

Related

Why does Heroku Node/Express site give CORS header error on all computers except development machine?

I'm trying to get a test React frontend and Node/Express backend to correctly set session cookies at Heroku.
This frontend/backend work locally.
This frontend/backend work at Heroku in every browser on my development machine.
But on every other machine I have tested (Windows, Ubuntu), I get this Cross-Origin-Request-Blocked error:
Here is the backend code, where I configure CORS origin correctly:
import express from 'express'
import cors from 'cors'
import morgan from 'morgan'
import session from 'express-session';
import dotenv from 'dotenv';
import cookieParser from 'cookie-parser';
dotenv.config();
const app = express();
app.use(morgan("dev"));
app.set('trust proxy', 1);
app.use(cors({
origin: process.env.FRONTEND_ORIGIN,
credentials: true
}));
app.use(cookieParser());
app.use(session({
name: 'testsession',
secret: 'h$lYS$cr§t!',
resave: true,
saveUninitialized: true,
cookie: {
httpOnly: true,
maxAge: 60 * 60 * 24,
sameSite: process.env.NODE_ENV === "production" ? "none" : "lax",
secure: process.env.NODE_ENV === "production"
}
}))
app.get('/', (req, res) => {
let user = req.session.user;
if (!user) {
res.json({ message: `${(new Date()).toISOString()}: nobody is logged in` })
} else {
res.json({ message: `${(new Date()).toISOString()}: ${user} is logged in` })
}
});
app.get('/login', (req, res) => {
req.session.user = "user001"
res.json({
message: `${(new Date()).toISOString()}: ${req.session.user} is now logged in`
})
})
app.get('/logout', (req, res) => {
req.session.destroy();
res.json({ message: `${(new Date()).toISOString()}: user logged out` })
});
const PORT = process.env.PORT || 3011
app.listen(PORT, () => {
console.log(`API listening on http://localhost:${PORT}`);
});
Here is my frontend code:
import { useState } from 'react';
import './App.scss';
function App() {
const [message, setMessage] = useState('click a button');
const backendUrl = process.env.REACT_APP_BACKEND_URL;
const handle_checkuser = async () => {
const requestOptions = {
method: 'GET',
credentials: 'include'
};
const response = await fetch(backendUrl, requestOptions);
const data = await response.json();
setMessage(data.message);
}
const handle_login = async () => {
const requestOptions = {
method: 'GET',
credentials: 'include'
};
const response = await fetch(`${backendUrl}/login`, requestOptions);
const data = await response.json();
setMessage(data.message);
}
const handle_logout = async () => {
const requestOptions = {
method: 'GET',
credentials: 'include'
};
const response = await fetch(`${backendUrl}/logout`, requestOptions);
const data = await response.json();
setMessage(data.message);
}
return (
<div className="App">
<div><button onClick={handle_checkuser}>checkuser</button></div>
<div><button onClick={handle_login}>login</button></div>
<div><button onClick={handle_logout}>logout</button></div>
<div>{message}</div>
</div>
);
}
export default App;
Why would it be getting this CORS error with some machines and not others?
Backend:
https://github.com/edwardtanguay/et-cookietest-backend
https://et-cookietest-backend.herokuapp.com
Frontend:
https://github.com/edwardtanguay/et-cookietest-frontend
https://et-cookietest-frontend.herokuapp.com
ADDENDUM
I also noticed that on every other machine except for my development machine, the HTTP connection is not secure. This seems to be the cause of the cookie-setting problem.
But how can that be? Why would one particular computer receive HTTPS connections from a website and others HTTP?

How to send React form data to backend express server

I have made this react form and want to send the candidate object to the backend express server where I want to console log the candidate object. I have checked that form is taking the input properly. I am using axios to send a post request to the express backend.
import React, { Fragment, useState } from "react";
import axios from "axios";
const Form = () => {
const [candidate, setCandidate] = useState({
fullName: "",
phoneNumber: 0,
email: "",
gitProfile: "",
linkToResume: "",
designation: "",
interest: "",
});
const onChange = e =>
setCandidate({ ...candidate, [e.target.name]: e.target.value });
const onSubmit = e => {
e.preventDefault();
axios
.post("http://localhost:5000/", {
candidate,
})
.then(res => {
console.log(res, candidate);
});
};
const designationOptions = [
"--select option--",
"Graphic Designer",
"Full Stack Developer",
"Project Manager",
"SEO and Digital Marketing",
];
return (
//form input code
);
};
export default Form;
This is the backend express server code.
const express = require("express"),
bodyParser = require("body-parser");
(app = express()), (port = process.env.PORT || 5000), (cors = require("cors"));
app.use(
cors({
origin: "http://localhost:3000",
credentials: true,
})
);
app.use(bodyParser.json());
app.use(
bodyParser.urlencoded({
extended: true,
})
);
app.get("/", function (req, res) {
console.log(req.body);
});
app.listen(port, () => console.log(`Backend server live on ${port}`));
I want to send the candidate object and console.log the object but I am getting a 404 error.
I have this setup in two different folders under a parent directory.
You are using app.get while sending request with axios as POST.
Try switching app.get to app.post

NodeJS/Express Server on Heroku, NextJS Client on Vercel, SocketIO Problem

I’ve got a problem with my NextJS + NodeJS + SocketIO setup and i wrap my head around it since days.
In development mode on my mac machine everything is fine but in production there is the problem.
The NodeJS server is hosted on Heroku and the NextJS client is hosted on Vercel.
Server:
require('dotenv').config()
// Packages
const express = require('express')
const mongoose = require('mongoose')
const passport = require('passport')
const cookie = require('cookie')
const jwtDecode = require('jwt-decode')
const cors = require('cors')
// App
const app = express()
// Models
const User = require('./models/User')
// App Settings
app.use(cors())
app.use(express.urlencoded({ limit: '10mb', extended: true }))
app.use(express.json({ limit: '10mb', extended: true }))
app.use(passport.initialize())
// App Routes
app.use('/_admin', require('./routes/_admin'))
app.use('/auth', require('./routes/auth'))
app.use('/profile', require('./routes/profile'))
app.use('/posts', require('./routes/posts'))
app.use('/comments', require('./routes/comments'))
app.use('/search', require('./routes/search'))
app.use('/users', require('./routes/users'))
require('./utils/passport')(passport)
const db = process.env.MONGO_URI
const port = process.env.PORT || 5000
mongoose
.connect(db, {
useNewUrlParser: true,
useFindAndModify: false,
useCreateIndex: true,
useUnifiedTopology: true
})
.then(() => {
console.log('MongoDB Connected') // eslint-disable-line no-console
const server = app.listen(port, () => console.log(`Server running on port ${port}`)) // eslint-disable-line no-console
const io = require('socket.io')(server)
io.on('connection', async socket => {
const decodedUser =
socket.handshake.headers.cookie && cookie.parse(socket.handshake.headers.cookie).jwtToken
? jwtDecode(cookie.parse(socket.handshake.headers.cookie).jwtToken)
: null
if (decodedUser) {
console.log(`${socket.id} -> ${decodedUser.username} -> connected`) // eslint-disable-line no-console
const user = await User.findById(decodedUser.id)
if (!user.sockets.includes(socket.id)) {
user.sockets.push(socket.id)
user.dateOnline = Date.now()
user.isOnline = true
user.save()
}
socket.on('disconnect', async () => {
console.log(`${socket.id} -> ${decodedUser.username} -> disconnected`) // eslint-disable-line no-console
const user = await User.findById(decodedUser.id)
const index = user.sockets.indexOf(socket.id)
user.sockets.splice(index, 1)
if (user.sockets.length < 1) {
user.isOnline = false
user.dateOffline = Date.now()
}
user.save()
})
} else {
console.log(`${socket.id} -> GUEST -> connected`) // eslint-disable-line no-console
socket.on('disconnect', async () => {
console.log(`${socket.id} -> GUEST -> disconnected`) // eslint-disable-line no-console
})
}
})
})
.catch(err => console.log(err)) // eslint-disable-line no-console
Client React Context:
import React, { createContext, useContext, useEffect, useState } from 'react'
import PropTypes from 'prop-types'
import io from 'socket.io-client'
const SocketContext = createContext()
export function useSocket() {
return useContext(SocketContext)
}
export function SocketContextProvider({ children }) {
const [socket, setSocket] = useState(null)
useEffect(() => {
setSocket(io(process.env.NOIZE_APP_SERVER_URL))
}, [])
const defaultContext = { socket }
return <SocketContext.Provider value={defaultContext}>{children}</SocketContext.Provider>
}
SocketContextProvider.propTypes = {
children: PropTypes.node
}
The hole React app is wrapped is this context-provider and as i said, on my localhost everything works fine.
The problem on the Heroku server is, that it is not receiving the cookie with my bearer jwt token from client in the SocketIO handshake. I’m lost right now and hope for help/hints/and so on…
Thank you very much =)
I solved the problem!
cookies.set('jwtToken', jwtToken, {
path: '/',
domain: process.env.NODE_ENV === 'development' ? 'localhost' : 'example.com'
})
The cookie needs the domain attribute in this case because the server runs on api.example.com and the client on www.example.com.

axios POST request is not sent

Faced such a problem and can no longer solve it 2 days, please help.
There is a server on the nodejs:
index.js
const mongoose = require("mongoose");
const keys = require("./config/keys");
const app = require("./app");
const port = process.env.PORT || 3001;
mongoose
.connect(keys.MONGO_URL, { useNewUrlParser: true })
.then(() => {
app.listen(port, () => console.log(`Server started on port ${port}`));
console.log("Connected to" + " MongoDB");
})
.catch((error) => console.log(error));
app.js
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const morgan = require("morgan");
const passport = require("passport");
const authRoutes = require("./routes/auth");
const restaurantRoutes = require("./routes/restaurant");
const app = express();
app.use(passport.initialize());
require("./middleware/passport")(passport);
app.use(morgan("dev"));
app.use("/uploads", express.static("uploads"));
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
app.use(cors());
app.use("/api/auth", authRoutes);
app.use("/api/restaurant", restaurantRoutes);
module.exports = app;
Nested Routes:
router.get(
"/",
passport.authenticate("jwt", { session: false }),
controller.getAll
);
router.get(
"/:id",
passport.authenticate("jwt", { session: false }),
controller.getById
);
router.post(
"/create",
passport.authenticate("jwt", { session: false }),
upload.single("image"),
controller.create
);
router.patch(
"/update",
passport.authenticate("jwt", { session: false }),
upload.single("image"),
controller.update
);
router.delete(
"/:id",
passport.authenticate("jwt", { session: false }),
controller.delete
);
There is a request from the front:
export function createNewRestaurant(restaurant, token) {
return {
type: CREATE_NEW_RESTAURANT,
payload: axios({
type: "POST",
url: "api/restaurant/create",
headers: {
Authorization: token,
},
data: JSON.stringify(restaurant),
})
.then((response) => {
console.log(response);
// return response.data;
})
.catch((error) => {
console.log({ error });
// return error.response.data;
}),
};
}
The problem is that POST doesn't even get from the server ...
There is no mention of it in the server console
If you remove the line from package.json client
"proxy": "http://localhost:3001/"
and write in the request
url: "http://localhost:3001/api/restaurant/create",
then in the server console we will see the OPTIONS request
OPTIONS /api/restaurant/create 204 0.135 ms - 0
I understand that the case is CORS, but I have it installed and in theory should work it all out, but how does this happen?
In postman, the request goes fine

React gives me Cannot GET / page_name While reloading (node/express)

I am trying to build a reactjs app and I am trying to pass data through from my front end (react) to my backend (node/express). However I am getting an error when I try and view the page I get this error. (Cannot GET /home).
const express = require("express");
const app = express();
const port = 5000;
const cors = require("cors");
app.use(cors());
var bodyParser = require("body-parser");
app.use(bodyParser.json()); // to support JSON-encoded bodies
app.use(
bodyParser.urlencoded({
// to support URL-encoded bodies
extended: true
})
);
app.post("/home", (req, res) => {
const data = [(generalDetail = req.body.generalDetail)];
console.log(generalDetail, "has been added to /home");
res.json(data);
});
app.listen(port, () => `Server running on port ${port}`);
here is my onSubmit function:
onSubmitForm = e => {
e.preventDefault();
let data = {
generalDetail: this.state.generalDetails,
firstName: this.state.firstName,
middleName: this.state.middleName,
lastName: this.state.lastName
};
axios.post("http://localhost:5000/home", data).then(() => {
//do something
}).catch(() => {
console.log("Something went wrong. Plase try again later");
});
You dont have a get route for home, that is why you are having trouble.
Add the following code above your post route.
app.get("/home", (req, res) => {
console.log("here");
});

Resources