Node / Express Post request using a function to send data - javascript

I am using a function that prevents the default submit of a form and want to use a second function that posts this so i can work / modify the data in the fist function before submitting.
the first function
const Test = document.querySelector('.test')
Test.addEventListener('submit', (e) => {
e.preventDefault()
const username = CreateUser.querySelector('.username').value
const password = CreateUser.querySelector('.password').value
post('/about', { username, password })
})
i found the following the function that submits the Post request. It works fine when the destination is another function without leaving the actual page.
function post (path, data) {
return window.fetch(path, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
}
I use the following routing in my index.js
const express = require('express')
const bodyParser = require('body-parser')
const store = require('./store')
const app = express()
app.use(express.static(__dirname + '/public'))
app.use(bodyParser.json())
var path = require('path')
app.post('/createUser', (req, res) => {
store
.createUser({
username: req.body.username,
password: req.body.password
})
.then(() => res.sendStatus(200))
})
app.get('/about',(req, res) => {
res.sendFile(path.join(__dirname, './public', 'about.html'));
})
app.post('/about',(req, res) => {
res.sendFile(path.join(__dirname, './public', 'about.html'));
})
app.listen(7555, () => {
console.log('Server running on http://localhost:7555')
})
When i make a post to /createUser i works fine and i can insert the data to a mysql table using a function.
I now want to make a post to /about using a function and eventually pass the data.
Why does it not work? I dont get any error.
The about.html, index.html and the js file with my functions are all in the public folder.
thanks for helping

Your route for the post function
app.post('/about',(req, res) => {
res.sendFile(path.join(__dirname, './public', 'about.html'));
})
is just returning the about.html page from your public folder. So there wouldn't be an error, you should just be getting back that HTML after posting to that endpoint with how it is currently configured.
The problem is that you'll only be getting this back as the body of your fetch() request. If you're wanting to see the about.html page, you'll want to actually redirect to http://localhost:7555/about.html. If you want to see the result of your fetch() request, you should be able to see the payload in the Networks tab of your DevTools (or your browser of choice's equivalent).

Related

how to get cookie in react passed from express js api (MERN stack)

I have an api in express js that stores token in cookie on the client-side (react). The cookie is generated only when the user logins into the site. For example, when I test the login api with the postman, the cookie is generated as expected like this:
But when I log in with react.js then no cookie is found in the browser. Looks like the cookie was not passed to the front end as the screenshot demonstrates below:
As we got an alert message this means express api is working perfectly without any error!!
Here is my index.js file on express js that includes cookie-parser middleware as well
require("dotenv").config();
const port = process.env.PORT || 5050;
const express = require("express");
const app = express();
const cors = require("cors");
const authRouter = require("./routes/auth");
var cookieParser = require('cookie-parser')
connect_db();
app.use(express.json());
app.use(cookieParser())
app.use(cors());
app.use("/" , authRouter);
app.listen(port , () => {
console.log("Server is running!!");
})
Code for setting up the cookie from express api only controller
const User = require("../models/user");
const jwt = require("jsonwebtoken");
const bcrypt = require('bcrypt')
const login = async (req, res) => {
const { email, password } = req.body;
try {
const checkDetails = await User.findOne({ email });
if (checkDetails) {
const { password: hashedPassword, token, username } = checkDetails;
bcrypt.compare(password, hashedPassword, function (err, matched) {
if (matched) {
res.cookie("token", token, { expires: new Date(Date.now() + (5 * 60000)) , httpOnly: true }).json({ "message": "You logged in sucessfully!" });
} else {
res.status(500).json({ "message": "Wrong password" });
}
});
} else {
res.status(500).json({ "message": "Wrong email" });
}
} catch (error) {
console.log(error.message);
}
}
Here is the react.js code that I am using to fetch data from api without using a proxy in package.json file
if (errors.length === 0) {
const isLogin = await fetch("http://localhost:5000/api/login", {
method: "POST",
body: JSON.stringify({ email, password }),
headers: {
"Content-Type": "application/json"
}
});
const res = await isLogin.json();
if(res) alert(res.message);
}
I want to get to know what is the reason behind this "getting cookie in postman but not in the browser". Do I need to use any react package?
The network tab screenshot might help you.
If I see in the network tab I get the same cookie, set among the other headers
To my understanding, fetch doesn't send requests with the cookies your browser has stored for that domain, and similarly, it doesn't store any cookies it receives in the response. This seems to be the expected behaviour of fetch.
To override this, try setting the credentials option when making the request, like so:
fetch(url, {
// ...
credentials: 'include'
})
or, alternatively:
fetch(url, {
// ...
credentials: 'same-origin'
})
You can read more about the differences between the two here.
I got my error resolved with two changings in my code
In front end just added credentials: 'include'
fetch(url, {
method : "POST"
body : body,
headers : headers,
credentials: 'include'
})
And in back end just replaced app.use(cors()); to
app.use(cors({ origin: 'http://localhost:3000', credentials: true, exposedHeaders: ['Set-Cookie', 'Date', 'ETag'] }))
That's it got resolved, Now I have cookies stored in my browser!!! Great. Thanks to this article:
https://www.anycodings.com/2022/01/react-app-express-server-set-cookie-not.html
during development i also faced same things, let me help you that how i solve it,
Firstly you use proxy in your react package.json, below private one:-
"private": true,
"proxy":"http://127.0.0.1:5000",
mention the same port on which your node server is running
Like:-
app.listen(5000,'127.0.0.1',()=>{
console.log('Server is Running');
});
above both must be on same , now react will run on port 3000 as usual but now we will create proxy to react So, react and node ports get connected on same with the help of proxy indirectly.
Now, when you will make GET or POST request from react then don't provide full URL, only provide the path on which you wants to get hit in backend and get response,
Example:-
React side on sending request, follow like this:-
const submitHandler=()=>{
axios.post('/api/loginuser',
{mobile:inputField.mobile,password:inputField.password})
.then((res)=>{
console.log(res);
})
.catch((err)=>{
console.log(err);
})
}
Node side where it will hit:-
app.post('/api/loginuser', async(req,res)=>{
//Your Code Stuff Here
res.send()
}
on both side same link should hit, it is very important
it will 100%.
don't forget to mention
on node main main where server is listening

getting error 405 'Method not Allowed' When trying to send request to my node server

Its my first time using Express and MongoDB, i have created my Node server and connected it to my mongoDB database, but when i try to send an request from my html page to the server i get Error 405 method not allowed, following is my node.js server code
mongoose.connect('mongodb://localhost/userdatabase' ,{
useNewUrlParser: true,
useUnifiedTopology: true
})
const app = express()
app.use('/', express.static(path.join(__dirname, 'static')))
app.use(bodyParser.json())
const port = 5500
app.listen(port, () => {
console.log(`server is up at ${port}`)
})
app.post('/api/register', async(req, res) => {
const {username, password} = req.body
res.json({status: 'ok'})
try{
const response = await User.create({
username,
password
})
console.log('User created succesfully' , response)
}catch(error){
console.log(error)
}
})
and here is the function im trying to call to do the post request
const form = document.querySelector('#register')
form.addEventListener('submit', registerUser)
async function registerUser(event){
event.preventDefault()
const username = document.getElementById('username').value
const password = document.getElementById('password').value
const result = await fetch('/api/register', {
method: 'POST',
headers: {
'Content-Type' : 'application/json'
}, body: JSON.stringify({
username,
password
})
}).then(res => res.json())
}
basically i am creating an login system and try to register users, but for some reason i keep getting the error 405 when trying to call the Server, Note that for some reason it worked 3 times when i was trying earlier, I havent changed almost anything in the code but it just wont work, what it can be ? thanks in advance
You should tell in which port mongoDB would run.
const mongoose = require('mongoose');
main().catch(err => console.log(err));
async function main() {
await mongoose.connect('mongodb://localhost:27017/test');
}
I think you have to declare the server and port while calling the axios. The axios call should be - await fetch('localhost:5500/api/register'). It's searching for '/api/register' but didn't find anything. Hope this will solve your issue.
Issue solved : the html file wasn't in the folder 'static' 😅 probably i have moved it and didn't noticed, sorry for the question guys, if anyone have the same problem make sure to check it

How do I make a live search result in node.js and mongoDb

I am trying to implement a feature where I have an input on this route to make a live search of employees in the database
app.get('/delete' , isLoggedIn , (req , res) => {
res.render('pages/delete')
})
This route serves the search input. How do I create a live search based on a keyup event listener that sends the data to mongoDb/mongoose to search and return the results on the page?
I know how to do the event listener to get what is typed like so which is in the delete.js file
const deleteSearchInput = document.querySelector('#search-input');
deleteSearchInput.addEventListener('keyup' , (e) => {
let search = e.target.value.trim()
})
How do I send the value "e" to a post route to do the search and return it to the page
AJAX (using the JavaScript fetch API). AJAX allows JavaScript to send requests to the server without reloading.
const deleteSearchInput = document.querySelector('#search-input');
deleteSearchInput.addEventListener('keyup' , (e) => {
let search = e.target.value.trim();
fetch('/delete', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({search})
}).then(res =>
res.json()
).then(data => {
console.log(data.result); // <-- success!
}).catch(err => {
alert('error!');
console.error(err);
});
});
Then you have changes to make to the server side. Since you're sending a POST request, you need to create a handler to POST:
app.post('/delete', isLoggedIn, (req, res) => {
res.send('success!');
});
This will handle post requests, and only post requests. Now to get the value of whatever you sent to the server, we need to use an npm package called body-parser, which parses the incoming request. Run the following command in shell:
npm i body-parser
Then at the top of your server file before declaring your routes import and use the body-parser library:
const bodyParser = require('body-parser');
app.use(bodyParser.json()); // <-- add the JSON parser
Finally change your handler again:
app.post('/delete', isLoggedIn, (req, res) => {
const { search } = req.body;
console.log(search);
// ... do whatever you want and send a response, e.g.:
const result = 'my awesome message';
res.json({ result });
});
And that's how you do it.

Empty body at server side when using fetch

I am trying to send html form data to server via a fetch 'POST' request but at server side I am getting Empty request body. I have already tried different solutions provided on stack overflow but none of them is working at my end. could anyone please help me identify where I am going wrong.
I have the form with id 'signup-form' in my html file
client side JavaScript the code goes like below:
const myForm = document.getElementById('signup-form')
myForm.addEventListener('submit', (e) => {
e.preventDefault()
const myForm = document.getElementById('signup-form')
const data = new FormData(myForm)
const option= {
method: 'POST',
headers: {
'Content-type': 'application/json'
},
body:JSON.stringify(data)
}
fetch('/login', option).then(
response => response.json()
).then(
data => console.log(data)
).catch(
error => console.log(error)
)
})
Server side express js code goes like below
app.use(express.urlencoded({ extended: false}))
app.use(express.json())
app.post('/login', (req, res) => {
console.log('url is', req.url)
const info = req.body;
console.log('info is:', info)
res.status(201).json({ 'submitted': true })
})
app.listen(3000, () => {
console.log('listening on port 3000')
})
With FormData you cannot POST application/json, because that is not on the list of content types supported by a form element.
Instead, write something like
const data = {element1: "value", element2: "value2", ...};

How to send data to the client and save it as a cookie

I know the basics of coding but I'm trying to understand API's, at the moment I'm trying to make an API that authorizes a user so I can see their information in a game.
Essentially I need to send data to my client from my server which is running Node.js and Express. I have managed to get the user authenticated but I then need to save that information as a cookie for later use.
The webapp starts on index.html and the API redirects the user back to auth.html.
Server Side Code
require('dotenv').config();
const express = require('express');
const {
addAsync
} = require('#awaitjs/express');
const app = addAsync(express());
const path = require('path');
const url = require('url');
const fetch = require("node-fetch");
const base64 = require('base-64');
const http = require('http');
// config libraries
const client_secret = process.env.CLIENT_SECRET;
// get env variables
function getCode(req) {
var ru = url.format({
protocol: req.protocol,
host: req.get('host'),
pathname: req.originalUrl
});
return ru.split("code=")[1];
}; // parse url to get auth code
const port = process.env.PORT || 4645;
app.listen(port, () => {
console.log(`listening on port ${port}`);
}); // set http server
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'index.html'));
}); // set '/' as index.html
app.getAsync('/auth', async (req, res) => {
res.sendFile(path.join(__dirname, 'auth.html'));
const code = getCode(req);
const options = {
method: 'POST',
headers: {
'Authorization': `Basic ${base64.encode(`35544:${client_secret}`)}`,
'Content-Type': 'application/x-www-form-urlencoded'
},
body: `grant_type=authorization_code&code=${code}`
}
const obj = await fetch('https://www.bungie.net/platform/app/oauth/token/', options); // response
const data = await obj.json(); // json response = data
console.log(data);
// send json to client
res.json(data);
res.end();
});
app.get('/logout', async (req, res) => {
res.redirect('/');
});
Client Side Code (index.html)
<head>
<script>
// code
</script>
</head>
<body>
index.html <br>
<a href='https://www.bungie.net/en/OAuth/Authorize?client_id=35544&response_type=code'>log in</a> <br>
</body>
Client Side Code (auth.html)
<head>
<script>
// catch json from server
const options = {
url: '/auth',
method: 'POST',
headers: {
'Content-Type': 'application/json'
}
};
fetch(options).then(response => {
console.log(response);
})
</script>
</head>
<body>
auth.html <br>
<a href='/logout'>log out</a>
</body>
I know it's a lot but I hope someone can help me on this...
Thanks.
Edit:
I forgot to say that currently the client does not recieve the information at any point, and if it did i am unsure how to catch the response at the right time...
Thanks to everyone who already responded.
Without bothering to puzzle-out your code ... "never trust the client."
Never try to send the client any meaningful data as the content of a cookie. The cookie's value should always be a perfectly-meaningless value – a "nonce" – which you can then refer to in order to look up anything you need to know from your server-side database. "You can never trust the client-side."

Categories