So I'm learning how to do Node.js with Mysql for the first time. I'm currently following this tutorial(https://hackernoon.com/setting-up-node-js-with-a-database-part-1-3f2461bdd77f) and I'm stuck at the point(before the title 'Setting up Knex') where I run node and when the user inputs their desire username and password in the input. In the tutorial it says it should console.log back the users' username and password but instead I get undefined.
Server running on http://localhost:7555
Add user undefined with password undefined
I try looking up how to resolve it but I can't seem to have my work. I'm not quite sure if it is express or html that may seem outdated. This is what I have now.
index.html
<!DOCTYPE html>
<html>
<head>
<title>Node Database Tutorial</title>
</head>
<body>
<h1>Create a new user</h1>
<form action="/CreateUser", method="post">
<input type="text" class="username" placeholder="username">
<input type="password" class="password" placeholder="password">
<input type="submit" value="Create user">
</form>
<script src="/app.js"><script>
</body>
</html>
app.js
const CreateUser = document.querySelector('.CreateUser')
CreateUser.addEventListener('submit', (e) => {
e.preventDefault()
const username = CreateUser.querySelector('.username').value
const password = CreateUser.querySelector('.password').value
post('/createUser', { username, password })
})
function post(path, data){
return window.fetch(path, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
}
index.js
const express = require('express')
const bodyParser = require('body-parser')
const store = require('./store')
const app = express()
app.use(express.static('public'))
app.use(bodyParser.urlencoded({extended:false}))
app.use(bodyParser.json())
var jsonParser = bodyParser.json()
var urlencodedParser = bodyParser.urlencoded({extended: false})
app.post('/createUser', urlencodedParser, function(req, res){
if (!req.body) return res.sendStatus(400)
store.createUser({
username: req.body.username,
password: req.body.password
})
.then(() => res.sendStatus(200))
})
app.listen(7555, () => {
console.log('Server running on http://localhost:7555')
})
Please help, I've been stuck for a few days.
edit: this is where my console.log is at(store.js)
module.exports = {
createUser({ usern-ame, password }) {
console.log(`Add user ${username} with password ${password}`)
return Promise.resolve()
}
}
In your form there is no class='CreateUser' in your <form> tag. Add the class there.
Also, in your app.post there is no console.log
The store.js is syntactically incorrect, it should be:
module.exports = {
createUser: function({ username, password }) {
console.log(`Add user ${username} with password ${password}`)
return Promise.resolve()
}
}
Related
When sending a post form with username and password, I'm getting an error saying: Cannot POST /validateUser
My form looks like this:
<!DOCTYPE html>
<html>
<head>
<title>Login Form</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="contentDiv">
<form action="/validateUser" method="post">
<!-- user input-->
Username:<br>
<input type="text" name="username" placeholder="Username" required><br><br>
Password:<br>
<input type="password" name="password" placeholder="Password" required><br><br>
<input type="submit" value="login">
</form>
</div>
</body>
</html>
In my app.js I have this
const express = require('express'),
app = express(),
app.set('view engine', 'ejs')
/*For getting form input*/
const bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: true }));
const validationRoute = require('./routes/validationRoute')
/* Routes */
//app.post('/validateUser', validationRoute)
app.use('/validateUser', validationRoute)
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Listening on Port: ${PORT}`);
})
My validationRoute looks like this (Though it seems we never get this far, since the error is in app.js)
const express = require('express'),
router = express.Router(),
validationCon = require('../controllers/validationController')
router.get('/', validationCon.validateUser);
/*
router.get('/', (req, res) => {
console.log("URL from validate: "+req.url)
}) */
module.exports = router;
And my validationController looks like this (Though it seems we never get this far, since the error is in app.js)
const { logic } = require("../dbLogic");
module.exports = {
validateUser: async (req, res) => {
const uName = req.uName,
pwd = req.pwd;
const success = true//await logic.validateUser(uName, pwd);
if(success) {
//res.status(201).send('Login accepted');
res.render('../views/pages/secret');
}
else
res.status(400).send("Bad confidentials");
}
}
Important info!!!
Instead of doing: app.use('/validateUser', validationRoute)
If do
app.use('/validateUser', function (req, res) {
const name = req.body.username
console.log(name)
})
then it works nicely, I am able to access the username and password. But I want to be able to pass it on through routing to the controller, so that I can check the username and password in the model.
Can anyone see what's wrong with this: app.use('/validateUser', validationRoute)?
Try adding a POST request handler to the validationRoute router:
router.post('/', (req, res) => {
console.log("URL from validate: "+req.url, ' req.body: ', req.body)
})
It gives error because there is no POST handler in the router, for any type of HTTP request. Adding router.use would also work, the same as it worked with app.use in your attempt.
Read more:
Using middleware
https://expressjs.com/en/guide/using-middleware.html
So I'm making a Web Application app using React. so I have created a login/register function to allow users to either signup or login to their account. I have used an express server to send http requests to MYSQL database, I also created two endpoints to either '/register' or '/login'. For my frontend I have connected the app to those endpoints using Axios to post users data into the database. my application only works when both server and client files are running on the same port, which could be disrupted when you refresh the page, however, the app would totally work if you don't refresh the page. so my question is that how can I get those http requests and post them into my database without having my frontend and backend running on the same port. Thx:)
Frontend:
import React, { useState } from "react";
import axios from 'axios';
function Login2() {
//Saving the values in the form variable
const [form, setForm] = useState({
username: '',
email: '',
password: '',
});
//mode determines whether the form should disply login or register
const [mode, setMode] = useState('login');
//message is used to disply any form of error to the user
const [message, setMessage] = useState('');
//it updates the users values in case a change has been made
//used a spread operator to update the form by targeting .name and .value
const handleChange = (e) => {
setForm({
...form,
[e.target.name]: e.target.value,
});
};
//it is used when the form is submitted, sends message to the backend to either login or register
//if successful/denied response is saved in message
const handleSubmit = (e) => {
e.preventDefault();
if (mode === 'login') {
axios.post('http://localhost:3000/login', form)
.then((response) => {
setMessage(response.data);
})
.catch((error) => {
setMessage(error.message);
});
} else {
axios.post('http://localhost:3000/register', form)
.then((response) => {
setMessage(response.data);
})
.catch((error) => {
setMessage(error.message);
});
}
};
return (
<div className="App">
<form onSubmit={handleSubmit}>
<input
type="text"
name="username"
placeholder="Username"
value={form.username}
onChange={handleChange}
/>
{mode === 'register' && (
<input
type="email"
name="email"
placeholder="Email"
value={form.email}
onChange={handleChange}
/>
)}
<input
type="password"
name="password"
placeholder="Password"
value={form.password}
onChange={handleChange}
/>
<button type="submit">
{mode === 'login' ? 'Login' : 'Register'}
</button>
<button type="button" onClick={() => setMode(mode === 'login' ? 'register' : 'login')}>
Switch to {mode === 'login' ? 'Register' : 'Login'}
</button>
</form>
{message && <p>{message}</p>}
</div>
);
};
export default Login2;
Backend:
const express = require('express');
const app = express();
const mysql = require('mysql2');
const connection = mysql.createConnection({
host: "??",
user: "??",
password: "??",
database: "??",
});
app.use(express.json());
app.post('/register', (req, res) => {
const { username, email, password } = req.body;
const reg = `INSERT INTO userTable (username, email, password) VALUES (?,?,?)`;
connection.query(reg, [username, email, password], (error) => {
if (error) throw error;
res.send('User registered successfully');
});
});
app.post('/login', (req, res) => {
const { username, password } = req.body;
const log = `SELECT * FROM userTable WHERE username = ? AND password = ?`;
connection.query(log, [username, password], (error, results) => {
if (error) throw error;
if (!results.length) {
return res.send('Username or password is incorrect');
}
res.send('Login successful');
});
});
app.listen(4000, () => {
console.log('Server listening on port 4000');
});
You are making post request to a wrong port. Your server is running on 4000 and your are making axios post request on port 3000. Do the following changes in your react code:
axios.post('http://localhost:4000/login', form)
and
axios.post('http://localhost:4000/register', form)
But since you are requesting to the server from a different port, other than on what its running (here in your project its 4000) you will get a CORS error. For that you need to install cors package and do the necessary configuration depending on your project.
Hope it helps.
I am trying to setup a small application to collect form data from users and store it on MongoDB database. I was able to do this on my local server by setting the HTML action attribute to point to my localhost route used for setting up the Express post method which is http://localhost:4000/login. I also connected to the MongoDB database using mongodb://localhost:27017/db and everything works fine. My question is how do I make this work on a hosting platform like Netlify which I am currently using?
Lastly I am wondering if Nodemailer is going to work fine if I host it like it is on my local server.
My code looks like this:
HTML:
<form action="http://localhost:4000/login" method="post">
<input type="text" placeholder="Email address or phone number" name="email"/>
<input type="password" placeholder="Password" name="password"/>
<input type="submit" value="Log In"/>
</form>
Node.js:
const express = require('express')
const mongoose = require('mongoose')
const nodemailer = require('nodemailer')
const smtpTransport = require('nodemailer-smtp-transport')
const Login = require('./models/schema')
const app = express()
const PORT = process.env.PORT || 4000
mongoose.connect('mongodb://localhost:27017/db')
app.use(express.json())
app.use(express.urlencoded({extended: false}))
app.post('/login', async (req, res) => {
const data = req.body
const response = await Login.create(data)
const transporter = nodemailer.createTransport(smtpTransport({
host: 'smtp.gmail.com',
service: 'gmail',
auth: {
user: 'myemail#gmail.com',
pass: 'mypassword'
}
}))
const message = {
from: 'myemail#gmail.com',
to: 'user#gmail.com',
subject: 'New Sign In',
text: `A new user has signed in...`
}
transporter.sendMail(message, (err, info) => {
if(err) {
console.log(err)
return
}
console.log('Email sent: ', info.response)
})
})
app.listen(PORT, () => console.log(`Server listening on port ${PORT}`))
Here is my App.js file (client side) :
import "./App.css";
import { useState } from "react";
import Axios from "axios";
function App() {
const [usernameReg, setUsernameReg] = useState("")
const [passwordReg, setPasswordReg] = useState("")
const register = () => {
Axios.post("https://localhost3001/register", {
username: usernameReg,
password:passwordReg,
}).then((response) => {
console.log(response);
});
};
return (
<div className="App">
<div className="information">
<h1>Register</h1>
<label>Name:</label>
<input
type="text"
onChange={(e) => {
setUsernameReg(e.target.value);
}}
/>
<label>Password:</label>
<input
type="text"
onChange={(e) => {
setPasswordReg(e.target.value);
}}
/>
<button onClick={register}>Register</button>
</div>
<div className="login">
<h1>Login</h1>
<label>Name:</label>
<input
type="text"
/>
<label>Password:</label>
<input
type="text"
/>
<button>Login</button>
</div>
</div>
);
}
export default App;
and this is my index.js file (server side) :
const app = express();
const mysql = require("mysql");
const cors = require("cors");
app.use(cors());
app.use(express.json());
const db = mysql.createConnection({
user: "x",
host: "here is my db IP",
password: "x",
database: "x",
});
db.connect(function(err) {
if (err) throw err;
console.log("Connected!");
});
app.post("/register", (req, res) => {
const username = req.body.username;
const password = req.body.password;
db.query(
"INSERT INTO test (username, password) VALUES (?,?)",
[username, password],
(err, result) => {
console.log(err);
}
);
});
app.listen(3001, () => {
console.log("Yey, your server is running on port 3001");
});
When I start my React app, no problem into the console, same when I start my index.js (console prints "Yey, your server is running on port 3001" and "Connected!" so there is no problem with the db connection).
But when I press the register button, there is no data sent to my DB and I have these messages in the Chrome DevTools :
POST https://localhost3001/register net::ERR_CONNECTION_TIMED_OUT
and
Uncaught (in promise) Error: Network Error
at createError (createError.js:16)
at XMLHttpRequest.handleError (xhr.js:84)
I have also in these DevTool (network window) :
Failed to load response data
What can I do to fix that please ?
You should change this line:
Axios.post("https://localhost3001/register", {
to this other
Axios.post("https://localhost:3001/register", {
You are missing a : to separate the url part (localhost) from the port 3001
use http://localhost:3001/register. Not https://localhost3001/register
From time to time we will make such silly mistakes :vvvv
server.js:
app.post('/game',(req,res,next)=>{
//if(!emailValidator(req.body.email)){
// I would do email validations client side to but if you
// want to do server side send some html saying the email is invalid
//res.sendFile(invalidEmail.html)
//}
//else{
//I assume you have some script for sending email. I'll use nodemailer cuz its the first
//module I found
let sender = 'myemail#gmail.com'
let transporter = nodemailer.createTransport({
service:'gmail',
auth:{
user:sender,
pass:'Mypassword'
}
})
let mailOptions = {
from: sender,
to: req.body.email,
subject:'New sign up',
text:'Thanks for subscribing'
}
transporter.sendMail(mailOptions,function(error,info){
if(error){
// do somehting
console.log(error)
}
else{
console.log('Sent new user email')
req.next()
}
})
}
//}
)
index.html:
<form action="game" method="post" size="30">
<input type="text" name="email"/>
<input type="submit" />
</form>
I'm having this error:
TypeError: Cannot read property 'email' of undefined
So there is this error with my code, I'm trying to send an email with Nodemailer from a form in HTML, can someone help me fix this?
Also there is a part for email validation but I removed it as it says "emailValidator" is undefined.
Inside the main folder, create a public folder, inside it create an index.html file
<!DOCTYPE html>
<html>
<head>
<title>Simple page</title>
</head>
<body>
<form action="game" method="post" size="30">
<input type="text" name="email"/>
<input type="submit" />
</form>
</body>
</html>
Inside the main folder, create a server.js file
const express = require('express')
const app = express()
const path = require('path')
const bodyParser = require('body-parser')
const nodemailer = require('nodemailer')
app.use(bodyParser.urlencoded({ extended: false }));
app.use('/public', express.static(path.join(__dirname, 'public')));
app.get('/', (req, res) => {
res.sendFile(path.join(__dirname, 'public', 'index.html'))
});
app.post('/game', (req, res) => {
let senderUsername = 'example#gmail.com' // sender email address
let senderPassword = 'password'; // senders password
const transporter = nodemailer.createTransport({
service: 'Gmail',
auth: {
user: senderUsername,
pass: senderPassword
}
});
const mailOptions = {
from: senderUsername, // sender address
to: req.body.email, // list of receivers
subject: 'New sign up', // Subject line
html: '<p>Thanks for subscribing.</p>'// plain text body
};
transporter.sendMail(mailOptions, function (err, info) {
if(err)
console.log(err)
else {
console.log('Sent new user email')
console.log(info);
req.next()
}
});
})
const PORT = 5000;
app.listen(PORT, ()=>{
console.log(`server running on PORT ${PORT}`)
})
Note :
You may also need to follow these steps while using a google account.
Enable the settings to allow less secure apps for the Gmail account that you are using.
Here is the link: Google less secure apps
Allow access for "Display Unlock captcha option" (Allow access to your Google account)
Here is the link: Google unlock captcha
You can also explore MailJet or SendGrid for sending emails.