I can't connect to my Express server. I'm trying to use Axios to connect from my front end but it never reaches the endpoint. Also when I attempt to connect directly from the browser it just spins. When I start the server, I do see the console log message from the listen function, so it appears to be running. But the Axios.post never gets tot he /login route.
Here is my index.js on the Server
const express = require('express');
const app = express();
const mysql = require('mysql');
const cors = require('cors');
app.use(cors);
app.use(express.json());
const db = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'root',
databaseName: 'ncaa'
});
app.post("/login", (req, res) => {
const userName = req.body.userName;
const password = req.body.password;
db.query("SELECT * from user where username = ? and password = ?", [userName, password], (err, result) => {
if(err){
res.send({err: err});
}
if (result){
res.send(result);
}
else {
res.send({message: "Username or password is incorrect"});
}
});
});
app.listen(3001, () => {
console.log('App running on 3001');
});
Here is my app.js on the client
import React from 'react';
import { useState } from 'react';
import Axios from 'axios';
import './App.css';
function App() {
const [userName, setUserName] = useState("");
const [password, setPassword] = useState("");
const authenticateLogin = () => {
Axios.post("http://localhost:3001/login", {
userName: userName,
password: password
}).then((response) => {
console.log(response);
});
}
return (
<div className="App">
<div className="login">
<h1>Login</h1>
<label>Username:</label>
<input type="text" onChange={(event) => { setUserName(event.target.value) }}/>
<label>Password:</label>
<input type="password" onChange={(event) => { setPassword(event.target.value) }}/>
<button onClick = {authenticateLogin}>Login</button>
</div>
</div>
);
}
export default App;
const express = require('express');
const app = express();
const cors = require('cors');
app.use(cors()); // cors is a function, you have to call that function
app.use(express.json());
Related
I am trying to send data input in my registration page to my mongoDB database through an express.js route but I keep getting a 404: not found error even though I have created this specific route.
server2.js (Setting up server, connecting to mongoDB, and create schema)
const express = require('express');
const app = express();
const cors = require("cors");
app.use(cors());
require("dotenv").config({path: "./config.env"});
const mongoose = require('mongoose');
//URI key
const mongoURI = process.env.ATLAS_URI;
console.log(mongoURI);
// Connect to the database
mongoose.connect(mongoURI, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(console.log("Connected to MongoDb"))
.catch(err => console.log(err));
// Define a schema for the data in the "accounts" collection
const accountSchema = new mongoose.Schema({
name: {
type: String,
required: true,
unique: true,
min: 2,
max: 24,
},
email: {
type: String,
required: true,
unique: true,
max: 200,
lowercase: true,
},
password: {
type: String,
required: true,
min: 8,
max: 30,}
});
//we're going to validate the json
// Define a model for the "accounts" collection using the schema
const Account = mongoose.model('Account', accountSchema);
// Example route that finds all accounts in the collection and sends them as JSON
// Start the server
const server = app.listen(4000, () => {
console.log('Server started on port 4000');
});
server.on("listening", () => {
console.log("Server is listening");
});
server.on("error", () => {
console.error("Error starting server", error.message);
});
module.exports = Account;
records2.js (creating routes)
const express = require("express");
import Account from "../server2";
// recordRoutes is an instance of the express router.
// We use it to define our routes.
// The router will be added as a middleware and will take control of requests starting with path /record.
const accountsRoutes = express.Router();
import Account from "../server2";
import accountModel from "../server2";
// This route adds a new account
accountsRoutes.post("http://localhost:4000/accounts/add", async (req, res) => {
try {
const dePackage = JSON.parse(req);
console.log("Route has started");
// Checks if there's an account with the same username or email address
const existingAccount = await accountModel.findOne({
$or: [{email:dePackage.email}, {username: dePackage.username}]
});
if (existingAccount) {
return res.status(400).json({message: "An account with that email/username already exists"});
}
const newAccount = new Account({
email: dePackage.email,
username: dePackage.username,
password: dePackage.password}
);
newAccount.save();
//find all users
const allUsers = await User.find();
console.log(allUsers);
} catch (err) {
console.log(err);
return res.status(500).json({ message: "Internal server Error"})
}
})
registerPage.js (frontend that fetches route on submit)
import React, {useState} from "react";
function RegisterPage() {
// create states to be managed
const [email, setEmail] = useState("");
const [userName, setUserName] = useState("");
const [password, setPassword] = useState("");
// create routes to handle changes in form
const handleEmail = (event) => {
setEmail(event.target.value);
}
const handleUsername = (event) => {
setUserName(event.target.value);
}
const handlePassword = (event) => {
setPassword(event.target.value);
}
const handleSubmit = async (event) => {
event.preventDefault();
const response = await fetch("http://localhost:4000/accounts/add", {
method: "POST",
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({email, userName, password}),
});
console.log(response.body);
const result = await response.json();
console.log(result);
}
return (
<div>
<form onSubmit={handleSubmit}>
<label htmlFor="email">email:</label>
<input name="email" id="email" type="text" onChange={handleEmail}/>
<label htmlFor="username">username: </label>
<input name="username" id="password" type="text" onChange={handleUsername} />
<br/>
<label htmlFor="password">password: </label>
<input name="password" id="password" type="text" onChange={handlePassword}/>
<br/>
<input type="submit" name="submit" value="register" />
</form>
</div>
)
}
export default RegisterPage;
I have tried to see if the server accepts the route, which it clearly didn't and I tried to see if there was a problem with json but it didn't seem to be that. I'm new with backend so help is greatly appreciated :).
There's a problem with your Express POST route.
Change this from:
accountsRoutes.post("http://localhost:4000/accounts/add", async (req, res) => {});
To this:
accountsRoutes.post("/accounts/add", async (req, res) => {});
Additionally, on the frontend you probably should proxy your React requests to Express in development. Otherwise, React is not aware of Express and is trying to fetch the frontend. Plus your current frontend fetch won't work on a staging or production environment.
For example, run npm i --save-dev http-proxy-middleware, then inside your React app's src folder create:
setupProxy.js
const { createProxyMiddleware } = require('http-proxy-middleware');
const proxy_urls = ['/api'];
const target = 'http://localhost:4000';
module.exports = function (app) {
proxy_urls.forEach((url) => {
app.use(url, createProxyMiddleware({ target }));
});
};
This reserves the /api suffix for React and funnels all of those /api calls to the backend or better known as a proxy. This file is telling React "all requests to /api should go to http://localhost:4000 and not http://localhost:3000.
Once that's in place your frontend component fetch can be modified:
const response = await fetch("/accounts/add", {});
So I have a login form that currently looks like that :
import React, { useState, useEffect} from "react";
import { Form, Button, Row, Col } from "react-bootstrap";
import { Link } from "react-router-dom";
import "./LoginScreen.css";
import axios from 'axios';
function LoginScreen() {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [error, setError] = useState(false);
const [loading, setLoading] = useState(false);
const submitHandler = async (e) => {
e.preventDefault();
try {
const config = {
headers: {
"Content-type": "application/json",
},
}
setLoading(true)
const { data } = await axios.post(
'/api/users/login',
{
email, password,
},
config);
console.log(data);
localStorage.setItem("userInfo", JSON.stringify(data));
setLoading(false);
} catch (error) {
setError(error.response.data.message);
}
}
return (
<div className="login_outer">
<h1>Login Here</h1>
<div className="loginContainer">
<Form onSubmit={ submitHandler }>
<Form.Group controlId="formBasicEmail" >
<Form.Label>E-mail: </Form.Label>
<Form.Control size="lg" type="email" value={email} placeholder="Enter Email" className="input" onChange={(e) => setEmail(e.target.value)}/>
</Form.Group>
<Form.Group controlId="formBasicPassword">
<Form.Label>Password: </Form.Label>
<Form.Control size="lg" type="password" value={password} placeholder="Enter Password" className="input" onChange={(e) => setPassword(e.target.value)}/>
</Form.Group>
<Button className="login_button" variant="primary" type="submit">
Submit
</Button>
</Form>
<Row className="py-3">
<Col>
New User ? <Link to="/register">Register Here</Link>
</Col>
</Row>
</div>
</div>
);
}
export default LoginScreen;
When I click the submit button I get the error:
POST http://localhost:3000/api/users/login 404 (Not Found)
In my server.js I have:
const userRoutes = require('./routes/userRoutes.js');
const dotenv = require('dotenv');
const express = require('express');
const connectDB = require('./config/db');
const { notFound, errorHandler } = require('./middlewares/errorMiddleware');
dotenv.config();
connectDB();
const app = express();
app.use(express.json());
app.get("/", (req, res) => {
res.send("API is running..");
});
app.use('/api/users', userRoutes);
app.use(notFound);
app.use(errorHandler);
const PORT = process.env.PORT || 5000;
app.listen(PORT, console.log(`Server started on PORT ${PORT}`));
and in my routes I have:
const express = require('express');
const { registerUser, authUser } = require('../controllers/userControllers');
const router = express.Router();
router.route('/').post(registerUser);
router.post("/login", authUser);
module.exports = router;
Any idea why this is happening and how to fix it ? I think it is something to do with the server file.
UPDATE!: I have fixed the error by getting a proxy, but now I when I try to login I get 401 unauthorized. Anyone know how to fix that?
Delete "proxy": "http://localhost:3000". Install package http-proxy-middleware with command:
npm install http-proxy-middleware --save
Create a file setupProxy.js inside your src folder or the root of your folder. Add these lines inside:
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
createProxyMiddleware({
target: 'http://localhost:5000',
changeOrigin: true,
})
);
};
I am new to react and mariaDB and this is my first attempt. I have created a sign up and sign in form in a single page. I used reactjs for frontend and node for backend and used mariaDB as database. I was able to insert username and password to databse when sign up. Now I want to check whether user has signed up when user try to login. I want to display an error as Wrong combination when username and password is not matched with registered users. I tried to display it, but it doesn't work.
here is my app.js in client side ,
import React, { useState } from 'react';
import './App.css';
import Axios from "axios";
function App() {
const [usernameReg,setUsernameReg]= useState("");
const [passwordReg,setPasswordReg]= useState("");
const [username,setUsername]= useState("");
const [password,setPassword]= useState("");
const [loginStatus,setLoginStatus]= useState("");
const register = () => {
Axios.post("http://localhost:3001/register", {
username:usernameReg,
password:passwordReg,
}).then((response) => {
console.log(response);
});
};
const login = () => {
Axios.post("http://localhost:3001/login", {
username:username,
password:password,
}).then((response) => {
if(response.data.message){
setLoginStatus(response.data.message);
}
else{
setLoginStatus(response.data[0].username);
}
});
};
return (
<div className="App">
<div className='registration'>
<label>Username</label>
<br/>
<input type="text" onChange={(e)=>{
setUsernameReg(e.target.value)
}}>
</input>
<br/>
<label>Password</label>
<br/>
<input type="text" onChange={(e)=>{
setPasswordReg(e.target.value)
}}>
</input>
<br/>
<button onClick={register}>Register</button>
<br/>
</div>
<div className='login'>
<br/>
<label>Username</label>
<br/>
<input type="text"
onChange={(e)=>{
setUsername(e.target.value)
}}
></input>
<br/>
<label>Password</label>
<br/>
<input type="text"
onChange={(e)=>{
setPassword(e.target.value)
}}
></input>
<br/>
<button onClick={login}>Login</button>
</div>
<h1>{loginStatus}</h1>
</div>
);
}
export default App;
here is my index.js in server side
const express = require("express");
const mariadb = require("mariadb");
const cors = require("cors");
const bodyParser = require("body-parser");
const app = express();
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.json());
const db = mariadb.createPool({
user: "root",
host: "localhost",
password: "NishR",
database: "pedro",
});
app.post("/register", async (req, res) => {
const username= req.body.username;
const password = req.body.password;
db.query(
"INSERT INTO user (username,PASSWORD) VALUES(?,?)",
[username,password],
(err,result)=>{
console.log(err);
}
);
}
);
app.post("/login", async (req, res) => {
const username= req.body.username;
const password = req.body.password;
db.query(
"SELECT * FROM user WHERE username=? AND password=?",
[username,password],
(err,result)=>{
if (err){
res.send({err:err});
}
if(result.length>0){
res.send(result);
}else{
res.send({message:"wrong combination"});
}
}
);
}
);
app.listen(3001, () => {
console.log("Server is running");
});
please help me to find the error.
So I am using a nodejs server to post contact form information from my react app into nodemailer so that I can send emails to my gmail account (this works fine and the emails come through) My question is I want to get React to respond to the response from the post request. (IE change state and then compile a message depending on that state). However when I send an email the page redirects to show just the plain json message sent from node. How can I stop this from happening? (Beginner here so please go easy!)
FORM FILE:
import React from 'react';`enter code here`
import './form.scss';
import axios from 'axios'
class Form extends React.Component{
constructor(){
super();
this.state= {
email: "",
topic: "",
query: "",
result: ""
}
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleSubmit = (event)=> {
const {email, topic, query, error, success} = this.state;
const data ={
email,
topic,
query
};
event.preventDefault();
axios
.post('http://localhost:5000/', data)
.then((res) => {
this.setState({result: "success"})
})
.catch(err => {
console.error(err)
this.setState({result: "fail"})
})
}
handleChange = (event) => this.setState({
[event.target.name]: event.target.value
});
render(){
const {result, topic, email, query} = this.state;
if(result === "success"){
return(<div>YES</div>);
}
if(result === "fail"){
return(<div>NO</div>);
}
else{
return(
<div>
<form action="/" method="POST" className="contact-form" >
<label className="contact-label">Email
<input type="text" name="email" value={email} onChange={this.handleChange} />
</label>
<label className="contact-label">Topic
<input type="text" name="topic" value={topic} onChange={this.handleChange}/>
</label>
<label className="contact-label">Query
<textarea name="query" value={query} onChange={this.handleChange} id="" cols="30" rows="10"></textarea>
</label>
<button type="submit" className="submit-button" onSubmit={this.handleSubmit}>Send Email</button>
</form>
</div>
)
}
}
}
export default Form;
NODEJS FILE:
const express = require('express')
const path = require('path');
const PORT = process.env.PORT || 5000;
const { body,validationResult } = require('express-validator');
const nodemailer = require("nodemailer");
const bodyParser = require('body-parser');
const app = express();
const cors = require('cors');
const { google } = require("googleapis");
const { reseller } = require('googleapis/build/src/apis/reseller');
const OAuth2 = google.auth.OAuth2;
require('dotenv').config()
app.use(express.static('public'));
app.use(bodyParser.json());
app.use(express.urlencoded({
extended: true
}))
if (process.env.NODE_ENV === 'production'){
app.use(express.static(path.join(__dirname, 'client/build')));
app.get('*', function(req,res){
res.sendFile(path.join(__dirname, 'client/build' , 'index.html'))
})
}
app.use(
cors({
origin: 'http://localhost:3000',
credentials: true,
})
);
app.route('/')
.post([body('email').isEmail()],(req,res) => {
const errors = validationResult(req);
const email = req.body.email
const topic = req.body.topic
const query = req.body.query
const body = `${email} sent a message with the topic: ${topic} and content: ${query} `
const myOAuth2Client = new OAuth2(
process.env.CLIENT_ID,
process.env.CLIENT_SECRET,
"https://developers.google.com/oauthplayground"
)
myOAuth2Client.setCredentials({
refresh_token: process.env.REFRESH_TOKEN
});
const myAccessToken = myOAuth2Client.getAccessToken()
const transport = nodemailer.createTransport({
service: "gmail",
auth: {
type: "OAuth2",
user: process.env.SECRET_EMAIL, //your gmail account you used to set the project up in google cloud console"
clientId: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET,
refreshToken: process.env.REFRESH_TOKEN,
accessToken: myAccessToken //access token variable we defined earlier
}});
const mailOptions = {
from: email,
to: process.env.SECRET_EMAIL,
subject: topic,
text: body
};
if (!errors.isEmpty()) {
console.log(error)
} else {
transport.sendMail(mailOptions, function(error, info){
if(error){
res.status(400).send({message: "failed"})
}else{
res.status(200).send({message: "success"})
};
});
}
});
app.listen(PORT, () => {
console.log(`Listening on port ${PORT}!`)
});
I'm new to the MERN stack and backend programming. I have a React form that I want to submit to an MLab database using Express. I am unable to successfully POST the form data to the database. I'm not sure if I'm taking the correct approach or not. My form is working and I am able to log the fields, I run into problems when trying to do a POST request to submit the form data.
Here is my form:
import React from 'react';
import { Button, Modal, ModalHeader, ModalBody, ModalFooter, Form, FormGroup, Label, Input } from 'reactstrap';
class AddBookModal extends React.Component {
constructor(props) {
super(props);
this.state = {
modal: false,
bookTitle: '',
author: '',
genre: ''
};
this.toggle = this.toggle.bind(this);
this.onSubmit = this.handleSubmit.bind(this);
}
toggle() {
this.setState(prevState => ({
modal: !prevState.modal
}));
}
handleSubmit = (event) => {
event.preventDefault();
const data = this.state;
//console.log("Data from form :" + data.bookTitle, data.author, data.genre);
}
handleInputChange = (event) => {
event.preventDefault();
this.setState({
[event.target.name]:
event.target.value
});
}
render() {
const {bookTitle} = this.state;
const {author} = this.state;
const {genre} = this.state;
return (
<div>
<Button id="add-book-button" onClick={this.toggle}>Add Book</Button>
<Modal isOpen={this.state.modal} toggle={this.toggle} className={this.props.className}>
<ModalHeader toggle={this.toggle}>Add Book</ModalHeader>
<ModalBody>
<Form method="POST" action="/profile" id="add-book-form" onSubmit={this.handleSubmit} >
<FormGroup>
<Label for="book-title-label">Book Title</Label>
<Input
value={bookTitle}
name="bookTitle"
onChange={this.handleInputChange}
placeholder="Enter name of book" />
</FormGroup>
<FormGroup>
<Label for="book-author-label">Author</Label>
<Input
value={author}
name="author"
onChange={this.handleInputChange}
placeholder="Enter author of book" />
</FormGroup>
<FormGroup>
<Label for="exampleSelect">Genre</Label>
<Input
onChange={this.handleInputChange}
value={genre}
type="select"
name="genre"
id="exampleSelect">
<option>1</option>
<option>2</option>
<option>3</option>
<option>4</option>
<option>5</option>
</Input>
</FormGroup>
<ModalFooter>
<Button color="primary" type="submit" onClick={this.toggle}>Submit</Button>{' '}
<Button color="secondary" onClick={this.toggle}>Cancel</Button>
</ModalFooter>
</Form>
</ModalBody>
</Modal>
</div>
);
}
}
export default AddBookModal;
Here is my Express route:
const router = require('express').Router();
const bodyParser = require('body-parser');
var urlencodedParser = bodyParser.urlencoded({ extended: false });
// localhost:3000/profile
// User Model
const User = require('../../models/user-model');
const Book = require('../../models/book-model');
// Checks if user is not logged in
const authCheck = (req, res, next) => {
if(!req.user) {
// If user is not logged in, redirect them to login page
res.redirect('/auth/login');
}
else {
// If user is logged in call next in router.get
next();
}
};
router.get('/', authCheck, (req, res) => {
res.send('you are logged in, this is your profile : ' + req.user);
});
router.post('/', urlencodedParser, (req, res) => {
console.log(req.body);
const newUser = new User({
name: req.body.name,
username: req.body.username,
githubID: req.body.githubID,
profileUrl: req.body.profileUrl,
avatar: req.body.avatar,
books: {
bookTitle: req.body.bookTitle,
author: req.body.author,
genre: req.body.genre
}
});
newUser.save()
.then(data => {
res.json(data)
})
.catch(err => {
res.send("Error posting to DB")
});
});
module.exports = router;
Here is my Express server:
const express = require('express');
const mongoose = require('mongoose');
const bodyParser = require('body-parser');
const authRoutes = require('./routes/api/auth');
const passportSetup = require('./config/passport-setup');
const cookieSession = require('cookie-session');
const keys = require('./config/keys');
const passport = require('passport');
const profileRoutes = require('./routes/api/profile-routes');
const bookRoutes = require('./routes/api/book-routes');
// Hooks up routes/api/items file
const items = require('./routes/api/items');
const app = express();
// Boderparser Middleware
app.use(bodyParser.json());
// sets up session cookies
app.use(cookieSession({
// Max age set to 1 day
maxAge: 24 * 60 * 60 * 1000,
// Uses cookieKey from keys file to encrypt
keys: [keys.session.cookieKey]
}));
// initialize passport
app.use(passport.initialize());
app.use(passport.session());
// DB Config
const db = require('./config/keys').mongoURI;
// Connect to mongodb
mongoose
.connect(db, { useNewUrlParser: true })
.then(() => console.log('MongoDB Connected'))
.catch(err => console.log(err));
// Use Routes, sets up routes/api/items to be used
app.use('/api/items', items);
app.use('/book', bookRoutes);
// Use auth.js's routes
app.use('/auth', authRoutes);
// Use profile-routes routes for profile page
app.use('/profile', profileRoutes);
const port = process.env.PORT || 5000;
app.listen(port, () => console.log(`Server started on port ${port}`))
I'm unable to make a POST request and not sure why. The Express route handles some OAuth stuff and displays the logged in user's profile. On that same page I have the form which allows the user to add data and submit it. Is the logic from authCheck interfering with POSTing the form data? The router.post in my Express route does not successfully console.log anything.
I've seen people use Axios in the React form component itself to do a POST request. Is it better to do form POST requests with Axios or should I be handling it in the Express route?
You should use the axios for making the api call.
In your handleSubmit function you are using "event.preventDefault()" which will prevent the default behavior of the form.