Javascript Fetching failing for no reason - javascript

I'm trying to make a login form where it fetches from another website, although, it keeps erroring with Error: Failed to Fetch
I don't really notice anything wrong with the code, but maybe its something related to CORS
Here is my code (HTML, CSS, JavaScript)
// Values: UsernameVal is being tested as "Developer"
// PasswordVal is being tested as "AccessTest"
if (User.value != "") {
if (Password.value != "") {
setFormMessage(loginForm, "info", "Checking account credentials..") // Set form message is just a basic function to set a login status message
var UsernameVal = User.value
var PasswordVal = Password.value
function a(data) {
console.log(data)
if (data.success == true) {
setFormMessage(loginForm, "success", "Logging in..")
} else {
setFormMessage(loginForm, "error", "Invalid username or password")
}
}
try {
console.log(`https://mysite.repl.co/check?username=${UsernameVal}&password=${PasswordVal}/`)
fetch(`https://mysite.repl.co/check?username=${UsernameVal}&password=${PasswordVal}/`, {
method: 'GET',
headers: {
accept: 'application/json',
},
})
.then(data => {
a(data)
}).catch((error) => {
throw new Error(error)
})
} catch (e) {
throw new Error(`Error setting login form message: ${e}`)
}
} else {
setFormMessage(loginForm, "error", "No password input provided")
}
} else {
setFormMessage(loginForm, "error", "No username input provided")
}
});
This is the code on the other side (nodejs)
const express = require('express');
const app = express();
const router = express.Router();
const bodyParser = require("body-parser")
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
const fs = require('fs')
app.post('/user', function(req,res) {
res.set("Access-Control-Allow-Origin", "OriginForGettingData")
const username = req.body.username
const password = req.body.password
res.send(`Added to login (${username}: ${password}}) list`)
const table = require('./values.json').Logins;
table[username] = password;
const fileName = './values.json';
const file = require(fileName);
file.Logins = table;
fs.writeFile(fileName, JSON.stringify(file)).done(function writeJSON(err) {
if (err) return console.log(err);
});
console.log(`Post recieved from ${insert}. New table: ${table}`)
})
app.get('/check', function(req,res){
res.set("Access-Control-Allow-Origin", "OriginForGettingData")
const username = req.param("username")
const password = req.param("password")
const table = require('./values.json').Logins;
res.json({"success": table[username] === password})
})
app.listen(3000, () => {
console.log('server started');
});
/user and /check work fine, its just the fetching that fails

After modifying the CORS for Access-Control-Allow-Origin from OriginForGettingData to *, it allowed the request to go through

Related

How do I send form data from frontend to backend so when user is at login they can login

I'm very new to backend development and I'm trying to figure out how to send my form data from front to backend. I watched a youtube tutorial on how and this is my code for server.js:
const express = require("express");
const app = express();
const port = 2009;
app.use(express.static("public"));
app.use(express.json());
app.get("/", (req, res) => {
res.status(200).json({info: "something"});
});
app.post("/", (req, res) => {
const { parcel } = req.body;
if (!parcel) {
return res.status(400).send({status: "failed"});
}
res.status(200).send({status: "recieved"});
});
app.listen(port, () => console.log(`server.js running on port: ${port}`));
And here is the code for script.js for my form:
const submit = document.getElementById("submit");
const userName = document.getElementById("user");
const password = document.getElementById("pass");
const email = document.getElementById("mail");
const baseUrl = "http://localhost:2009/"
async function post(e) {
e.preventDefault();
const res = await fetch(baseUrl + "website?key=hello", {
method: "POST"
})
}
Like I said I basically have no clue what I am doing could someone help me?
I haven't tested it yet because I'm afraid it won't work if would be very helpful if someone could show me some code or point me to some documentation so that I can work in the right direction.
you seem to be on the right track just a few changes and additions.
const registerForm = document.getElementById('register_form');
async function post(e) {
const form = document.forms.register_form;
const email = form.email.value;
const password = form.password.value;
const username = form.username.value;
try {
const res = await fetch(baseUrl + "website?key=hello", {
method: "POST",
body: JSON.stringify({
email,
username,
password,
}),
headers: { "Content-Type": "application/json" },
});
// handle the response here
} catch (error) {
// handle error here
}
}
registerForm.addEventListener('submit', post, false);
on the backend, you will need a route to handle this request
app.post("/", (req, res) => {
const { username, email, password } = req.body;
// validate the data from the request
if (!username || !email || !password) {
return res.status(400).send({
status: "failed",
message: "fields are required"
});
}
res.status(201).send({status: "recieved"});
});
StatusCode 201 indicates a new resource has been created
References:Using Fetch Api statusCode
I hope this helps.

How to fix JsonWebTokenError in node.js using express and reactjs?

I am trying to show the page only if the Jsonwebtoken is verified and the user is logged on to the website, else show him the sign-in page.
However, I can see the token is generated in MongoDB, and also when I console log I can see that it is all good. But the issue is when I try to verify it using an already generated jwt token i.e.
req.cookies.signinToken
it shows an error.
Please the detail code below:
On app.js
const dotenv = require("dotenv");
const mongoose = require("mongoose");
const express = require("express");
const app = express();
const jwt = require("jsonwebtoken");
const cookieParser = require("cookie-parser");
dotenv.config({ path: "./config.env" });
require("./db/connection");
app.use(express.json());
app.use(cookieParser());
app.use(require("./router/route"));
const PORT = process.env.PORT;
app.listen(5000, () => {
console.log(`server running on ${PORT}`);
});
On route.js
const express = require("express");
const bcrypt = require("bcrypt");
const router = express.Router();
const jwt = require("jsonwebtoken");
require("../db/connection");
const User = require("../model/newUserSchema");
const auth = require("../middleware/auth");
// router.get("/", (req, res) => {
// res.send("hello am backend sever");
// });
//Signup or Register Part
router.post("/signup", async (req, res) => {
const { username, email, cpassword, retypePassword } = req.body;
if (!username || !email || !cpassword || !retypePassword) {
return res.status(422).json({ error: "please enter valid details" });
}
try {
const UserExist = await User.findOne({ email: email });
if (UserExist) {
return res.status(422).json({ error: "email already exist" });
} else if (cpassword !== retypePassword) {
return res.status(422).json({ error: "password incorrect" });
} else {
const user = new User({
username,
email,
cpassword,
retypePassword,
});
const userResgister = await user.save();
if (userResgister) {
return res.status(201).json({ message: "signup successfully" });
}
}
} catch (error) {
console.log(error);
}
});
//Login Part
router.post("/signin", async (req, res) => {
try {
const { email, cpassword } = req.body;
if (!email || !cpassword) {
return res.status(400).json({ error: " please enter valid credentials" });
}
const userLogin = await User.findOne({ email: email });
const token = userLogin.generateAuthToken();
res.cookie("signinToken", token, {
expires: new Date(Date.now() + 25892000000),
httpOnly: true,
});
if (userLogin) {
const isMatch = await bcrypt.compare(cpassword, userLogin.cpassword);
if (isMatch) {
return res.status(200).json({ message: "sigin in scuccessfully" });
} else {
return res.status(400).json({ error: " Invalid credentials" });
}
} else {
return res.status(400).json({ error: " Invalid credentials " });
}
} catch (error) {
console.log(error);
}
});
//watchlistpage
router.get("/watchlist", auth, (req, res) => {
console.log(" this is jwt token test " + req.cookies.signinToken);
res.send(req.rootuser);
console.log(req.rootuser);
});
module.exports = router;
On newUserSchema.js:
const mongoose = require("mongoose");
const bcrypt = require("bcrypt");
const jwt = require("jsonwebtoken");
const newUserSchema = new mongoose.Schema({
username: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
cpassword: {
type: String,
required: true,
},
retypePassword: {
type: String,
required: true,
},
tokens: [
{
token: {
type: String,
required: true,
},
},
],
});
newUserSchema.pre("save", async function (next) {
if (this.isModified("cpassword")) {
this.cpassword = await bcrypt.hash(this.cpassword, 12);
this.retypePassword = await bcrypt.hash(this.retypePassword, 12);
}
next();
});
newUserSchema.methods.generateAuthToken = async function () {
try {
let token = jwt.sign({ _id: this._id }, process.env.SECRETKEY);
this.tokens = this.tokens.concat({ token: token });
await this.save();
return token;
} catch (error) {
console.log(error);
}
};
const User = mongoose.model("newUser", newUserSchema);
module.exports = User;
On auth.js (this is also my middleware)
const jwt = require("jsonwebtoken");
const User = require("../model/newUserSchema");
const Auth = async (req, res, next) => {
try {
console.log(JSON.stringify(req.cookies.signinToken) + " this is jwt token test");
const token = req.cookies.signinToken;
const verifytoken = jwt.verify(token, process.env.SECRETKEY);
const rootuser = await User.findOne({ _id: verifytoken._id, "tokens.token": token });
if (!rootuser) {
throw new Error("user not found");
}
req.token = token;
req.rootuser = rootuser;
req.UserID = rootuser._id;
next();
} catch (error) {
res.status(401).send("Unauthorized access");
console.log(error);
}
};
module.exports = Auth;
The API call result in postman
The terminal error :
when I try to console log on route.js inside Signin page i see promise pending
const token = userLogin.generateAuthToken();
console.log(token);
res.cookie("signinToken", token, {
expires: new Date(Date.now() + 25892000000),
httpOnly: true,
});
Could you please help to correct the error also please let me know why is this error coming?
Thanks a million in advance for any tips or suggestions.
Hi Thanks for the help
I just saw that my token was returning a promise, I did not add the keyword await before the token other thing was I was trying to access it before the validation, hence it was showing me nodata and error.
Please see the correct code below:
//Login Part
router.post("/signin", async (req, res) => {
try {
const { email, cpassword } = req.body;
if (!email || !cpassword) {
return res.status(400).json({ error: " please enter valid credentials" });
}
const userLogin = await User.findOne({ email: email });
if (userLogin) {
const isMatch = await bcrypt.compare(cpassword, userLogin.cpassword);
const token = await userLogin.generateAuthToken();
console.log(token);
res.cookie("signinToken", token, {
expires: new Date(Date.now() + 25892000000),
httpOnly: true,
});
if (isMatch) {
return res.status(200).json({ message: "sigin in scuccessfully" });
} else {
return res.status(400).json({ error: " Invalid credentials" });
}
} else {
return res.status(400).json({ error: " Invalid credentials " });
}
} catch (error) {
console.log(error);
}
});
I hope this might help other learners too.
Thanks.

Test a POST Http request from a local node server in REACT

I need to make unit tests for some post requests but i dont understand how.I tried with mswjs but the test passes because i'm missing something and i dont know what.I tried to test the requests in an usual way but i wasnt able to put my conditions there and it was sending only 200 status code..
To start with,this is my folder structure:
+main folder
++nodeServer
+++public
+++routes
++public
++src
+++tests
This is my try for testing the post request to /subscribe endpoint,where i should send an email as a payload and get the response that the payload was received succesefully.
subscribeFetch.test.js:
import {setupServer} from 'msw/node'
import {rest} from 'msw'
const handlers = [
rest.post("/api/subscribe",(req,res,context)=>{
if (!req.body || !req.body.email) {
return res(context.status(400).json({ error: "Wrong payload" }));
}
if (req.body.email === 'forbidden#email.com') {
return res(context.status(422).json({ error: "Email is already in use" }));
}
return res(
context.status(200),
context.json({email:'gigi#gmail.com'})
)
})
]
const server = setupServer(...handlers)
beforeAll(()=>server.listen())
afterAll(()=>server.close())
afterEach(()=>server.resetHandlers())
test('should send post request to the server',async()=>{
server.use(
rest.post('/api/subscribe',(req,res,ctx)=>{
return res(
expect (ctx.status()).toBe(200)
)
}
)
)
})
//export {handlers,rest}
This is the subscribe post request function that i need to test:
import { validateEmail } from './email-validator.js'
export const sendSubscribe = (emailInput) => {
const isValidEmail = validateEmail(emailInput)
if (isValidEmail === true) {
sendData(emailInput)
}
}
export const sendHttpRequest = (method, url, data) => {
return fetch(url, {
method: method,
body: JSON.stringify(data),
headers: data
? {
'Content-Type': 'application/json'
}
: {}
}).then(response => {
if (response.status >= 400) {
return response.json().then(errResData => {
const error = new Error('Something went wrong!')
error.data = errResData
throw error
})
}
return response.json()
})
}
const sendData = (emailInput) => {
sendHttpRequest('POST', '/api/subscribe', {
email: emailInput
}).then(responseData => {
return responseData
}).catch(err => {
console.log(err, err.data)
window.alert(err.data.error)
})
}
Files from the server:
app.js:
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const indexRouter = require('./routes/index');
const communityRouter = require('./routes/community');
const analyticsRouter = require('./routes/analytics');
const app = express();
global.appRoot = path.resolve(__dirname);
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/community', communityRouter);
app.use('/analytics', analyticsRouter);
module.exports = app;
index.js from routes folder in the server folder:
const express = require('express');
const router = express.Router();
const FileStorage = require('../services/FileStorage');
/* POST /subscribe */
router.post('/subscribe', async function (req, res) {
try {
if (!req.body || !req.body.email) {
return res.status(400).json({ error: "Wrong payload" });
}
if (req.body.email === 'forbidden#email.com') {
return res.status(422).json({ error: "Email is already in use" });
}
const data = {email: req.body.email};
await FileStorage.writeFile('user.json', data);
await res.json({success: true})
} catch (e) {
console.log(e);
res.status(500).send('Internal error');
}
});
/* GET /unsubscribe */
router.post('/unsubscribe', async function (req, res) {
try {
await FileStorage.deleteFile('user.json');
await FileStorage.writeFile('user-analytics.json', []);
await FileStorage.writeFile('performance-analytics.json', []);
await res.json({success: true})
} catch (e) {
console.log(e);
res.status(500).send('Internal error');
}
});
module.exports = router;
Please guys,help me write unit test for subscribe endpoint to match the conditions from index.js file from routes folder in the server folder,thank you in advance!
So,i got the expected result without any library,but i dont know if its a good aproach,but at least it works :
const app = require('../../../personal-website-server/app')
const request = require('supertest')
describe('POST /subscribe', () => {
it('should give 400 status code when email is empty', async () => {
const email = { email: '' }
const response = await request(app).post('/subscribe').send(email)
if (!request.body || !request.body.email) {
expect(response.status).toBe(400)
}
})
it('should give 422 status code when email is forbidden', async () => {
const email = { email: 'forbidden#gmail.com' }
const response = await request(app).post('/subscribe').send(email)
if (request.body === 'forbidden#gmail.com') {
expect(response.status).toBe(422)
}
})
it('should give 200 status code when email is valid', async () => {
const email = { email: 'gigi#gmail.com' }
const response = await request(app).post('/subscribe').send(email)
expect(response.error).toBe(false)
expect(response.status).toBe(200)
expect(response.body.body).not.toBeNull()
})
})

Passport authentication is causing an issue with access to API call

Trying to create a login authentication system as an entry into web development but the fetch I have to access my login functionality doesn't work. Morgan shows "POST -- ms --". (Works through Postman). As far as I can see my cors system is set up as expected. The API will respond if the passport.authenticate('local') is removed.
authenticate.js
var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;
var User = require('./models/user');
var JwtStrategy = require('passport-jwt').Strategy;
var ExtractJwt = require('passport-jwt').ExtractJwt;
var jwt = require('jsonwebtoken'); // used to create, sign, and verify tokens
var config = require('./config.js');
exports.local = passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
exports.getToken = function(user) {
return jwt.sign(user, config.secretKey,
{expiresIn: 3600});
};
var opts = {};
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
opts.secretOrKey = config.secretKey;
exports.jwtPassport = passport.use(new JwtStrategy(opts,
(jwt_payload, done) => {
console.log("JWT payload: ", jwt_payload);
User.findOne({_id: jwt_payload._id}, (err, user) => {
if (err) {
return done(err, false);
}
else if (user) {
return done(null, user);
}
else {
return done(null, false);
}
});
}));
routes
var express = require('express');
var UserRouter = express.Router();
var passport = require('passport');
var User = require('../models/user')
var authenticate = require('../authenticate');
const cors = require('./cors');
const bodyParser = require('body-parser');
UserRouter.use(bodyParser.json());
UserRouter.route('/login')
.options(cors.corsWithOptions, (req, res) => { res.sendStatus(200); })
.post(cors.cors, passport.authenticate('local'), (req, res) => {
console.log(req.body);
var token = authenticate.getToken({_id: req.user._id});
res.setHeader('Content-Type', 'application/json');
res.json({success: true, token: token, status: 'You are successfully logged in!'});
res.status(200).send()
});
module.exports = UserRouter;
mongoose schema file
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var passportLocalMongoose = require('passport-local-mongoose');
var User = new Schema ({
firstname : {
type: String,
default: ""
},
lastname: {
type: String,
default: ''
},
admin: {
type: Boolean,
default: false
}
});
User.plugin(passportLocalMongoose);
module.exports = mongoose.model('User', User);
cors file
const express = require('express');
const cors = require('cors');
var whitelist = ['http://localhost:3000', 'http://localhost:3443']
var corsOptionsDelegate = (req, callback) => {
var corsOptions;
console.log("Validating origin");
console.log(req.header('Origin'));
if(whitelist.indexOf(req.header('Origin')) !== -1) {
corsOptions = { origin: true };
}
else {
corsOptions = { origin: false };
}
callback(null, corsOptions);
};
exports.cors = cors();
exports.corsWithOptions = cors(corsOptionsDelegate);
Front end API call
export const loginUser = (creds) => (dispatch) => {
console.log("test")
dispatch(requestLogin(creds))
console.log("attempting login")
return fetch('http://localhost:3443/users/login', {
method: 'POST',
headers: {
'Content-Type':'application/json',
},
body: JSON.stringify(creds)
})
.then(response => {
console.log("got response 1");
if(response.ok) {
return response
} else {
console.log("response errored");
var error = new Error('Error ' + response.status + ': ' + response.statusText);
error.response = response;
throw error;
}
},
error => {
console.log("errored")
throw error;
})
.then(response => response.json())
.then(response => {
console.log("got response 2");
if(response.success) {
// Successful login
localStorage.setItem('token', response.token);
localStorage.setItem('creds', JSON.stringify(creds));
// TODO dispatch success
dispatch(receiveLogin(response));
} else {
var error = new Error('Error ' + response.status);
error.response = response;
throw error;
}
})
.catch(error => dispatch(loginError(error.message)))
}
Does anyone know where I'm going wrong with this? I'm not really getting any useful error messages from my front-end so haven't included.
Terminal output upon login attempt
OPTIONS /users/login 204 3.287 ms - 0
POST /users/login - - ms - -

req.body is undefined after post request

I'm building a contact form using nodemailer.
To post it I'm using the fetch API.
But for some reason, I get req.body as undefined.
Here's the frontend code:
form.onsubmit = function (e) {
// Stop the regular form submission
e.preventDefault();
const name = document.querySelector("form#contactForm #name").value;
const email = document.querySelector("form#contactForm #email").value;
const textarea = document.querySelector("form#contactForm #textarea").value;
// Collect the form data while iterating over the inputs
var data = {};
data = { name, email, textarea };
console.log(data);
fetch("/mail", {
method: "POST", // or 'PUT'
headers: { "Content-Type": "application/json" },
body: JSON.stringify(data),
})
.then(async (response) => {
if (response.ok) {
return response.json();
} else {
const resJson = await response.json();
console.log(resJson);
if (typeof resJson.errors === "undefined") {
formStatus.className += " alert-danger";
formStatus.innerText =
"An error occured, Please refresh the page. Or email us at ravchesed#kehilasbelz.be";
return;
}
let ul = document.createElement("ul");
resJson.errors.forEach((err) => {
const li = document.createElement("li");
li.innerText = `${err.msg}: ${err.param} `;
ul.append(li);
console.log(`${err.msg}: ${err.param} `);
});
formStatus.className += " alert-danger";
formStatus.innerText = "";
formStatus.append(ul);
throw response;
}
})
.then((data) => {
console.log("Success:", data);
})
.catch((error) => {
console.error("Error:", error);
});
};
Here's the backend:
const express = require("express");
const app = express();
const bodyParser = require("body-parser");
const { check, validationResult } = require("express-validator");
const rateLimit = require("express-rate-limit");
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 10, // limit each IP to 100 requests per windowMs
});
//Here we are configuring express to use body-parser as middle-ware.
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());
const mail = express.Router();
// app.post("/mail", (req, res) => {
// console.log(req.body);
// const result = {
// hellop: 5
// };
// res.send(JSON.stringify(result));
// });
mail.post(
"/mail",
// limiter,
[
// username must be an email
check("email").trim().isEmail(),
check("textarea").trim().isLength({ max: 6000 }),
check("name").trim().isLength({ min: 2, max: 20 }),
],
(req, res) => {
console.log(req.body); //undefined
// Finds the validation errors in this request and wraps them in an object with handy functions
const errors = validationResult(req);
if (!errors.isEmpty()) {
console.log(errors); //this returns empty values.
return res.status(422).json({ errors: errors.array() });
}
const mailInfo = {
name: req.body.name,
email: req.body.email,
message: req.body.testarea,
};
main(mailInfo).catch(console.error);
res.json({ success: true });
}
);
const nodemailer = require("nodemailer");
// async..await is not allowed in the global scope, must use a wrapper
async function main(data) {
// create reusable transporter object using the default SMTP transport
let transporter = nodemailer.createTransport({
host: "xxx.xxx.com",
port: 587,
secure: false, // true for 465, false for other ports
auth: {
user: "email#example.com", // generated ethereal user
pass: "abc123456", // generated ethereal password
},
});
// send mail with defined transport object
let info = await transporter.sendMail(
{
from: '"John Doe 👍" <robot#Doe.dev>', // sender address
to: "Doe#gmail.com", // list of receivers
subject: `📧 Mail from ${data.name}`, // Subject line
html: `
<b>${data.name}, ${data.email}</b><br>
Phone: ${data.phone}<br>
<br>
Message:
<br>
${data.message}
`, // html body
},
function (err, info) {
if (err) console.log(err);
else console.log(info);
console.log("Message sent: %s", info);
}
);
}
module.exports = mail;
Looked at a lot of posts, but this seems to be a different problem.
after looking at everything again I know where my mistake was but don't understand why.
My file structure is like this:
app.js
mail.js
mail.js was imported to app.js like this:
//handle mail
const mail = require("./mail");
app.use(mail);
in app.js I didn't import body-parser and the middleware because it was already imported in mail.js.
but looks like for some reason that I also have to import it in app.js before mail.js.

Categories