Next js/react Unable to set a cookie - javascript

so i am trying to get a cookie in next js and using express but the backend works fine with postman and get the cookie token but the problem is the frontend is not getting the cookie and here is my backend:
const express = require("express");
const cookieParser = require("cookie-parser");
const cors = require("cors");
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cors());
app.use(cookieParser());
app.post("/", (req, res) => {
res.cookie("token", req.body.token).send({ msg: "DONE" });
});
app.listen(5000, () => {
console.log("running on http://localhost:5000");
});
and here is the frontend:
import styles from "../styles/Home.module.css";
export default function Home({ cookies }) {
return (
<div className={styles.container}>
<h1>Cookies: {cookies}</h1>
<button
onClick={() => {
fetch(`http://localhost:5000/`, {
method: "post",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ token: "ACBD" }),
});
}}
>
Genrate Cookies
</button>
</div>
);
}
it is returning:
Unhandled Runtime Error
TypeError: Failed to fetch
is there a mistake here also i have tried to put this in a getServerSideProps() but it still does not work.

I use js-cookie. it works great
get and set Cookies in React.useEffect in the frontend

Related

Error: Request failed with status code 404, React, Axios

I have built a form which I want to be able to send emails, to do this I have attempted to follow this youtube tutorial: https://www.youtube.com/watch?v=_3-By9QfFa0
However I am running into an issue where I am getting the error in the question title which is coming up in my console web browser when trying to submit the form. I realize the issue might have something to do with one of the routes somewhere but I just cant figure it out (unless it's something completely different).
schoolForm.js
const handleSubmit = async(e) => {
e.preventDefault();
try { //I also tried using only: "/send_mail" here like I have in server.js but it didnt work
await axios.post("http://localhost:3000/send_mail", {
name
});
}
catch (error) {
console.log(error);
}
}
server.js
const express = require("express");
const app = express();
require("dotenv").config();
const bodyParser = require("body-parser");
const cors = require("cors");
const nodemailer = require("nodemailer");
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.use(cors());
app.post("/send_mail", cors(), async (req, res) => {
let {text} = req.body;
const transport = nodemailer.createTransport({
host: "smtp-mail.outlook.com",
port: 587,
auth: {
user: "someone#hotmail.com",
pass: "password"
},
tls: {
rejectUnauthorized: false
}
});
await transport.sendMail({
from: "someone#hotmail.com",
to: "someone#hotmail.com",
subject: "subject",
html: `<p>${text}</p>`
})
});
app.listen(4000, () => {
console.log("Server is listening on port 4000");
});
Edit: The error I get in the browser:
Is there anyone that can help me solve this issue? Help would be greatly appreciated!
Your server is listening on port 4000. // server.js
app.listen(4000, () => {
console.log("Server is listening on port 4000");
});
You should use below URL for Axios call. // schoolForm.js
await axios.post("http://localhost:4000/send_mail", { // use port 4000 not 3000
name
});
You've set up your server to listen to port 4000 but your axios request is to port 3000.
Make sure you send the request to the correct port:
await axios.post("http://localhost:4000/send_mail", {
name
});
Also note the body-parser is deprecated and you should use express built-in middleware. so instead of:
app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
you should have:
app.use(express.urlencoded({extended: true}));
app.use(express.json());
and you can remove body-parser dependency.
You can read here to learn more about express built-in middleware and their optional properties.
EDIT:
The reason it wasn't working is because body is an object created by the middleware itself. Therefore req.body is undefined since the body object doesn't exists

Why can't I call localhost localhost:5000 from localhost:3000 using axios in react

I have a react application running on localhost:3000 and in that I am making a GET request in my code using axios to http://localhost:5000/fblogin.
const Login = () => {
const options = {
method: "GET",
url: "http://localhost:5000/fblogin",
};
axios.request(options)
.then((response)=>{
console.log(response.data);
})
.catch((error)=>{
console.error(error);
});
};
But I'm getting a error having status (failed)net::ERR_FAILED initiator xhr177.
How can I resolve it
You'll need to 1. implement express cors, and 2. add a proxy from react to your server
[1] https://expressjs.com/en/resources/middleware/cors.html
npm install cors
var express = require('express')
var cors = require('cors')
var app = express()
app.use(cors())
[2] https://create-react-app.dev/docs/proxying-api-requests-in-development/
In your react's package.json, add
"proxy": "http://localhost:5000",
Note that this will work in development only.
For production, you'll need to serve the client from the server.
See https://create-react-app.dev/docs/deployment
const express = require('express');
const cors = require('cors')
const path = require('path');
const app = express();
app.use(cors());
/**
* add your API routes here to avoid them getting overtaken
* by the statically served client
*/
/**
* add this as the last handler
*/
if (process.env.NODE_ENV === "production") {
const pathToClientBuild = path.join(__dirname, '..', 'path', 'to', 'client', 'build');
app.use(express.static(pathToClientBuild));
/**
* experiment with '/' and '/*' and see what works best for you
*/
app.get('/*', function (req, res) {
res.sendFile(path.join(pathToClientBuild, 'index.html'));
});
}
app.listen(5000);
(and to make it work, you'll need to build the client first, and then serve the server with NODE_ENV=production node ./server.js).
const Login 9636634272 = () => {
const options = {
method: "GET",
url: "http://localhost:5000/fblogin",
};
axios.request(options)
.then((response)=>{
console.log(response.data);
})
.catch((error)=>{
console.error(error);
});
};
const Login = () => {
const options = {
method: "GET",
url: "http://localhost:5000/fblogin",
};
axios.request(options)
.then((response)=>{
console.log(response.data);
})
.catch((error)=>{
console.error(error);
});
};

Making a set by express server cookie be visible to client

I am new to Express and I have problems with sending cookies.
I made a simple express app that needs to set a cookie to the browser. This is the server:
const express = require('express');
const cookieParser = require('cookie-parser');
const cors = require('cors');
const app = express();
//app.use(cors());
app.use((req, res, next) => {
res.append('Access-Control-Allow-Origin', ['http://127.0.0.1:5500']);
res.append('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
res.append('Access-Control-Allow-Headers', 'Content-Type');
res.append('Access-Control-Allow-Credentials', 'true');
next();
});
app.use(cookieParser());
app.use(express.json());
const PORT = 9000;
app.get('/', (req, res) => {
res.setHeader('Content-Type', 'application/json');
res.cookie('testCookie', 'random value', {httpOnly: false, secure: false});
res.send({user: "test", password: "test123"});
})
app.listen(PORT, console.log(`Server started on port ${PORT}`));
So it successfully sends to the browser the testCookie on request with fetch:
let response = await fetch('http://localhost:9000/', {
method: 'GET',
mode: 'cors',
credentials: 'include',
headers: {
'Content-Type': 'application/json'
}
}).then(response => response.json());
console.log(response);
After the request the cookie is successfully send because is in the Chrome cookie tab but document.cookie returns an empty string. And also when i make request to a page the request doesnt contains the Cookie header.
How can I make the cookie to be visible to document.cookie and also to the browser to send his Cookie header?
I strongly suggest you to use an npm package: jsonwebtoken, https://www.npmjs.com/package/jsonwebtoken
This way it's much cleaner:
const jwt = require ('jsonwebtoken');
// Create login logic here (check password etc.);
const token = jwt.sign(user, secret, expiration);
res.status(201).json({
status: 'success',
token
});
Try using JSON format instead of res.send since you have a body parser in place already and it's a best practice in modern APIs.

req.body is empty whith fetch request

i'm trying to make a fetch request to my server.
but i keep getting an empty req.body.
client script:
const form = document.getElementById('form1')
form.addEventListener('submit', (e) => {
e.preventDefault();
const formData = new FormData(form);
const link = formData.get('link');
var payload = {
link
};
console.log(payload);
const options = {
method: "POST",
body: JSON.stringify(payload),
headers: {
'content-type': 'application/json'
}
}
console.log(options);
fetch('/api/gtmetriks', options)
.then(response => response.json()).then(result => console.log(result)).catch(err => console.log(err));
})
server code:
const bodyParser = require('body-parser');
const cors = require('cors')
const app = express()
//cors
app.use(cors())
app.use(bodyParser.urlencoded({
extended: true
}));
// parse application/json
app.use(bodyParser.json())
app.post('/api/gtmetriks', (req, res) => {
console.log(req.body);
})
so when i post the request i get in the console '{}'.
but no errors in the clients browser.
I think the problem is that you are using CORS but not specifying which URL to POST to. For example, your client is http://localhost:3000 but your server is http://localhost:3001. You are sending the fetch to http://localhost:3000/api/gtmetriks instead of http://localhost:3001/api/gtmetriks.
If you change your fetch to:
fetch('[YOUR SERVER URL]/api/gtmetriks', options)
.then(response => response.json())
.then(result => console.log(result))
.catch(err => console.log(err));
})
It should work.
EDIT #1:
This code worked for me using a React frontend (3000) and an Express backend (3001):
Client app.js
import React, { Component } from 'react';
export default class App extends Component {
handleSubmit = () => {
const payload = {
link: 'http://tesla.com',
};
const options = {
method: 'POST',
body: JSON.stringify(payload),
headers: {
'content-type': 'application/json',
},
};
fetch('http://localhost:3001/api/gtmetriks', options)
.then(response => response.json())
.then(result => console.log(result))
.catch(err => console.log(err));
};
render() {
return (
<button
onClick={() => {
this.handleSubmit();
}}>
Click Me
</button>
);
}
}
Server server.js
const express = require('express');
const logger = require('morgan');
const cors = require('cors');
const app = express();
//use cors to allow cross-origin resource sharing
app.use(
cors()
);
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.post('/api/gtmetriks', (req, res) => {
console.log(req.body);
res.sendStatus(200);
});
//start your server on port 3001
app.listen(3001, () => {
console.log('Server Listening on port 3001');
});

Error: Request failed with status code 404 (Node.js + Vue.js)?

I am little bit confused and need some help.
I write an HTTP server using Node.js, and make an HTTP request from Vue.js to the HTTP server. Somehow it always return error like this:
Error: Request failed with status code 404
at FtD3.t.exports (createError.js:16)
at t.exports (settle.js:18)
at XMLHttpRequest.f.(:3010/anonymous function) (http://localhost:3010/static/js/vendor.1dc24385e2ad03071ff8.js:1312:88758)
It seems like url address don't correct cause error is 404 in browser. I check url address several times but did't notice something wrong. What I miss?
P.S. The main task to load file from remote sftp server from website. I use to that task ssh2-sftp-client library as backend side.
When user click the button, application run getFile function where we send post request to HTTP server.
Code inside Vue.js component:
getFile (fileName) {
axios.post('http://localhost:3010/csv', {file_name: fileName}, {headers: {'Authorization': this.token}}).then(response => {
console.log(response)
this.showAlert('You download file successfully.', 'is-success', 'is-top')
}).catch((error) => {
console.log(error)
this.showAlert(error, 'is-danger', 'is-bottom')
})
}
app.js:
const express = require('express');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const cors = require('cors');
const path = require('path');
const bodyParser = require('body-parser');
const csvRouter = require('./server/routes/csv')
const app = express();
app.use(cors());
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(express.static(path.join(__dirname, 'dist')));
app.use(express.urlencoded({extended: false}));
app.use(cookieParser());
app.use('/csv', csvRouter);
module.exports = app;
routers/csv.js:
const express = require('express')
const router = express.Router()
const csvControllers = require('../controllers/csv')
router.get('/', csvControllers.getFile)
module.exports = router
controllers/csv.js:
const request = require('request')
const queryString = require('query-string')
let Client = require('ssh2-sftp-client')
let sftp = new Client()
const config = require('../config')
exports.getFile = (req, res) => {
console.log(req) // In console I don't notice nothing.
let data = {
file_name: req.query.file_name
}
let options = {
method: 'port',
json: true,
header: {'Authorization': req.header.token},
url: `http://localhost:3010/csv?` + queryString.stringify(data)
}
request(options, (error, response) => {
console.log('Message') // In console I don't notice nothing.
if (response) {
sftp.connect(config.sftpServer).then(() => {
return sftp.get('/reports/' + data.file_name)
}).then((chunk) => {
console.log(chunk)
}).catch((err) => {
console.log(err)
})
} else {
response.status(500).send(error)
}
})
}
It seems that app.listen(port) is missing in your app.js file:
app.listen(3000)
https://expressjs.com/en/starter/hello-world.html
In controllers/csv.js you never send a response. You should have a res.send or res.render or res.json somewhere.

Categories

Resources