Sending Data from React to MySQL - mysql

I am creating a publishing application that needs to use communication between React and MySQL database to send information back and forth. Using Express as my JS server. The server code looks as follows:
const express = require('express');
const bodyParser = require('body-parser');
const mysql = require('mysql');
const cors = require('cors');
const connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : '',
database : 'ArticleDatabase',
port: 3300,
socketPath: '/Applications/XAMPP/xamppfiles/var/mysql/mysql.sock'
});
// Initialize the app
const app = express();
app.use(cors());
appl.post('/articletest', function(req, res) {
var art = req.body;
var query = connection.query("INSERT INTO articles SET ?", art,
function(err, res) {
})
})
// https://expressjs.com/en/guide/routing.html
app.get('/comments', function (req, res) {
// connection.connect();
connection.query('SELECT * FROM articles', function (error, results,
fields) {
if (error) throw error;
else {
return res.json({
data: results
})
};
});
// connection.end();
});
// Start the server
app.listen(3300, () => {
console.log('Listening on port 3300');
});
And my React class looks as follows:
class Profile extends React.Component {
constructor(props) {
super(props);
this.state = {
title: '',
author: '',
text: ''
}
}
handleSubmit() {
// On submit of the form, send a POST request with the data to the
// server.
fetch('http://localhost:3300/articletest', {
body: JSON.stringify(this.state),
cache: 'no-cache',
credentials: 'same-origin',
headers: {
'content-type': 'application/json'
},
method: 'POST',
mode: 'cors',
redirect: 'follow',
referrer: 'no-referrer',
})
.then(function (response) {
console.log(response);
if (response.status === 200) {
alert('Saved');
} else {
alert('Issues saving');
}
});
}
render() {
return (
<div>
<form onSubmit={() => this.handleSubmit()}>
<input type = "text" placeholder="title" onChange={e =>
this.setState({ title: e.target.value} )} />
<input type="text" placeholder="author" onChange={e =>
this.setState({ author: e.target.value} )} />
<textarea type="text" placeholder="text" onChange={e =>
this.setState({ text: e.target.value} )} />
<input type="Submit" />
</form>
</div>
);
}
}
So fairly standard stuff that I found in online tutorials. I can search my database and display fetched info no problem, but not the other way around. When I try to take input from the <form> tag nothing is inserted into my database but instead I get this error:
[Error] Fetch API cannot load
http://localhost:3000/static/js/0.chunk.js due to access control
checks.
Error: The error you provided does not contain a stack trace.
Unhandled Promise Rejection: TypeError: cancelled
I understand that this has something to do with access control but since I am already using cors and can successfully retrieve data from the database, I am not sure what I am doing wrong. Any suggestions will be greatly appreciated. Thank you in advance.

You'll need to isolate the problem by first verifying that your service point is CORS Enabled. In order to focus solely on CORS functionality, I would remove the MySQL code temporarily.
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const app = express();
app.use(cors());
app.get('/', function(req, res){
var root = {};
root.status = 'success';
root.method = 'index';
var json = JSON.stringify(root);
res.send(json);
});
app.post('/cors', function(req, res) {
var root = {};
root.status = 'success';
root.method = 'cors';
var json = JSON.stringify(root);
res.send(json);
})
// Start the server
app.listen(3300, () => {
console.log('Listening on port 3300');
});
One you have server listening on port 3300, run the following PREFLIGHT command at the terminal.
curl -v \
-H "Origin: https://example.com" \
-H "Access-Control-Request-Headers: X-Custom-Header" \
-H "Acess-Control-Request-Method: POST" \
-X OPTIONS \
http://localhost:3300
If the preflight request is successful, the response should include Access-Control-Allow-Origin, Access-Control-Allow-Methods, and Access-Control-Allow-Headers
Now run the POST method.
curl -v \
-H "Origin: https://example.com" \
-H "X-Custom-Header: value" \
-X POST \
http://localhost:3300/cors
If the post request is successful, the response should include
Access-Control-Allow-Origin
If everything looks good, your server is okay. You then need to try the post method from your iOS app.
NOTE. I would also be suspicious of using cors on localhost. I would map 127.0.0.1 to a domain and then have the app use that domain instead. If you are on Linux or Mac, you modify /etc/hosts. For Windows it's c:\windows\system32\drivers\etc\hosts

Try explicitly whitelisting the server that is making the request:
const whitelist = ['http://localhost:3000']; // React app
const corsInstance = cors({
origin: (origin, callback) => {
if (!origin || whitelist.indexOf(origin) !== -1) {
callback(null, true);
} else {
callback(new Error('Not allowed by CORS'));
}
}
});
application.use(corsInstance);
https://expressjs.com/en/resources/middleware/cors.html#configuring-cors-w-dynamic-origin

You need to add event.preventDefault() at the end of your handleSubmit method (check this example https://stackblitz.com/edit/react-forms).
You have to do it for the reason for preventing form default behavior on submit: it tries to synchronously send data to the url it loaded from (since there is no action attribute on it).

For those who may have run into a similar problem, I was able to fix it by dumping express server altogether. I simply used the .php file on the Apache server to insert data into database. Hope it helps somebody.

Related

How can I retrieve data from mysql upon clicking on a button by react-native

I'm currently having an error on my code on retrieving MySQL data upon clicking a button.
Here is my 'route.js'.
const express = require('express');
const bodyParser = require('body-parser');
const mysql = require('mysql');
const connection = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'password!',
database: 'mydb'
});
// Starting our app.
const app = express();
// Creating a GET route that returns data from the 'users' table.
app.get('/user', function (req, res) {
// Connecting to the database.
connection.getConnection(function (err, connection) {
// Executing the MySQL query (select all data from the 'users' table).
connection.query('SELECT * FROM user', function (error, results, fields) {
// If some error occurs, we throw an error.
if (error) throw error;
// Getting the 'response' from the database and sending it to our route. This is were the data is.
res.send(results)
});
});
});
// Starting our server.
app.listen(3000, () => {
console.log('Go to http://localhost:3000/user so you can see the data.');
});
async function test(){
await fetch('http://mylocalpcIP:3000/user',{
method: 'POST', // Here you're saying that you want to make a POST request. Could be any method, like a GET, for example.
headers: '', // You can specify your requisition headers here. That line is optional.
body: { // Here's the fun part. Put your data here.
"name": this.state.name,
"age": this.state.age,
"phone_number": this.state.phone_number
}
})
.then(response => response.json())
.then(user => console.warn(user))
};
export {test};
Then, I've called test function as such:
import React from 'react';
import { View, Text, StyleSheet, TouchableOpacity } from 'react-native';
import {test} from "./db/routes.js";
const MyScreen = ( {navigation} ) => {
return (
<View style={styles.container2}>
<TouchableOpacity
style = {[styles.mid_box, styles.pbox]}
onPress={() =>{
test();
navigation.navigate("Dating_to_Profiles")
}}>
<View>
<Text style = {styles.textstyle}>1st Introduced Profile</Text>
</View>
</TouchableOpacity>
And I'm getting this scary message when I reload the emulated Android.
Well.. It's very likely that I've messed up somewhere since I don't know much about anything yet.
I'd appreciate a lot if someone can teach me how to retrieve data via POST method.
Thanks a lot in advance!
Express is a NodeJS framework and thus obviously not compatible with react-native.
If you wanted to create an API where your data that was queried from MYSQL is served as JSON so it can be fetched by your app, I recommend this tutorial for you.

Post an array into MySQL Workbench with Express.js api and mysql package

I'm working with Express.js and mysql package to create my apis, but i can't make a post.
This is my code so far:
const express = require('express');
const mysql = require('mysql');
const config = mysql.createConnection({
host: theHost,
port: thePort,
user: theUser,
password: thePass,
database: theDB,
});
const app = express();
config.connect(function(err){
if(!err) {
console.log("Success");
} else {
console.log("Error trying to connect");
}
});
app.get("/api/InternalAccess", function(req, res){
config.query('SELECT * from InternalAccess', (error, result) => {
if (error) throw error;
res.send(result);
});
});
app.post("/api/internalAccess", function(req, res){
var info = { User: req.body.User, Password: req.body.Password, CreationDate: req.body.CreationDate };
config.query('INSERT INTO InternalAccess SET ?', info, (error, result) => {
if (error) throw error;
res.send(result);
});
});
app.listen(3000);
I have no problems with get, it works fine, but to make post from postman, i get the error: " Cannot read property "User" of undefined". Am i avoiding something? I'm really new using mysql package.
My db is MySQL Workbench, and as i said, i'm using Node.js, Express.js and mysql package.
Hope you can help me. Thanks in advance
In order to have req.body populated automatically, you have to use some body-parser middlewares, like:
app.use(express.json()) // for parsing application/json
app.use(express.urlencoded({ extended: true })) // for parsing application/x-www-form-urlencoded
Of course, there can be multiple other causes (like, you're not constructing the request properly in postman), but the lack of setting the middlewares is the first place I'd fix.
Seems like req.body is null. I think you might just be missing the body-parser in your app.js.
var bodyParser = require('body-parser');
var app = express();
// parse application/json
app.use(bodyParser.json())
see other examples here: https://expressjs.com/en/resources/middleware/body-parser.html

Angular HTTPClient (HTTP) requests pending forever

I have recently started working with MySQL as the database for my Angular/NodeJS project (I have been using MongoDB all along). Nonetheless, I'm encountering issues when handling HTTP Requests. I have experimented with GET and POST requests as of now, and GET is forever pending, until failure and POST doesn't post to backend and to the database, likewise. I really hadn't changed the backend configuration from the one I used with MongoDB database, except for the queries, of course.
I have tried debugging the backend to check whether the server is actually running and everything was okay. It just came to requests reaching the specified endpoints that they're always pending. I also tried to log to console if a request gets at a certain endpoint, but nothing was being logged, unfortunately.
server.js
const app = require("./backend/app");
const debug = require("debug")("node-angular");
const http = require("http");
const normalisePort = setPort => {
const port = parseInt(setPort, 10);
if (isNaN(port)) return setPort;
if (port >= 0) return port;
return false;
};
const port = normalisePort(process.env.PORT || "8000");
const server = http.createServer(app);
const error = error => {
if (error.syscall !== "listen") {
throw error;
}
const bind = typeof port === "string" ? "pipe " + port : "port " + port;
switch (error.code) {
case "EACCES":
console.error(bind + " requires elevated privileges");
process.exit(1);
break;
case "EADDRINUSE":
console.error(bind + " is already in use");
process.exit(1);
break;
default:
throw error;
}
};
const listening = () => {
const address = server.address();
const bind = typeof port === "string" ? "pipe " + address : "port " + port;
debug.enabled = true;
debug("Listening on " + bind);
};
app.set("port", port);
server.on("error", error);
server.on("listening", listening);
server.listen(port, "localhost");
app.js
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const users = require("./routes/users");
const app = express();
app.use(cors);
app.use(bodyParser.json());
app.use(
bodyParser.urlencoded({
extended: false
})
);
app.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader(
"Access-Control-Allow-Headers",
"Origin, X-Requested-With, Authorization, Content-Type, Accept"
);
res.setHeader(
"Access-Control-Allow-Methods",
"GET, POST, PATCH, DELETE, OPTIONS"
);
next();
});
app.get("/api/users", users);
module.exports = app;
users.js
const express = require("express");
const router = express.Router();
const db = require("../sql-connection");
router.get("", (req, res, next) => {
db.query("select * from users;", (error, results, fields) => {
if (results.length > 0) {
return res.status(200).send(results);
} else {
return res.status(404).send();
}
});
});
module.exports = router;
sql-connection.js
const mysql = require("mysql");
const sqlConnection = mysql.createConnection({
host: "localhost",
user: "root",
password: "",
database: "payroll"
});
sqlConnection.connect(error => {
if (error) throw error;
console.log("connected to database");
});
module.exports = sqlConnection;
auth.service.ts
export class AuthService {
private _BASE_URL: string = "http://localhost:8000/api";
constructor(private http: HttpClient) {}
public get users(): Observable<any> {
return this.http.get(this._BASE_URL + "/users");
}
}
signup.component.ts
export class SignUpComponent {
constructor(private _authService: AuthService) {}
public onSignUp(): void {
this._authService
.users()
.subscribe(data => (data ? console.log(data) : console.log("no data")));
}
}
When subscribed to the users observable data from backend should logged to console if present, otherwise, 'no data' is logged on the console. Unfortunately, this request takes forever (pending). However, if I don't subscribe to users no request is sent/seen under network tab in dev tools.
I've been using MYSQL database and I would recommend using mysql2 over mysql
mysql2 provides promise based syntaxes over conventional callback methods.
Here's the documentation for Mysql2 for nodejs.
Coming to the problem, I guess it might be because Nodejs is asynchronous while you're using a synchronous approach in setting up the API.
Also when you're working with Asynchronous programming you have to use try-catch-finally instead of conventional if-else statements to log the errors.
So you can use async (req, res, next)=>{ //your code here } rather than just using (req, res, next)=>{ //your code here }.
Also you have to await before calling the sql query, i.e;
await db.query
or
rather in mysql2 it is easier to use const [data] = await pool.execute(query, [params]).

Node.js + body-parser object format changes when it reaches backend

I'm trying to send an object inside an another object from React frontend to Node/express backend using jquery ajax. The problem the data is received at the backend, it no longer looks follows the syntax of an object. Instead, it looks something like this:
{ 'data[name]': 'test name',
'data[size][height]': '123',
'data[size][weight]': '50' }
Here is the front end ajax call...
lendItem(){
let id = "5af3348742afc60ab71d7d80"
$.ajax({
url: '/api/items/' + id,
method: 'put',
data: {
'data': {
name: "test name",
size: {
height: 123,
weight: 50
}
}
},
success: (res) => {console.log(res)}
});
}
backend server...
const express = require('express');
const bodyParser = require('body-parser');
const mongoose = require('mongoose');
// connect to mongodb
mongoose.connect('mongodb://localhost/promedical');
mongoose.Promise = global.Promise;
const app = express();
const port = process.env.PORT || 5000;
// parsing data that was received
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// initialize routes
app.use('/api', require('./routes/api'));
// error handling
app.use((err, req, res, next)=>{
res.status(422).send({error: err.message});
});
app.listen(port, () => {
console.log(`Listening on port ${port}`)
});
...and here is the route I'm interested in.
router.put('/items/:id', (req, res, next)=>{
console.log(req.body);
res.send("success");
});
I think this problem might have something to do with that body-parser. Is is possible to send objects inside an object via jquery ajax and have it keep it's form once it reaches the backend? If not, should I just send all the data inside one object and then parse it at the backend?
It turns out that the object called 'data' becomes a string after the backend has accepted the ajax call. Is there any way to prevent this from happening? I need to store that object into a database as an object, not as a string.

not able to connect my React application to MySql

I am trying to connect my react application to MySql database using nodejs but on clicking the submit button it throws me the following error:
POST http://localhost:3000/login 500 (Internal Server Error)
Failed to load http://localhost:3000/login: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access. The response had HTTP status code 500. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Uncaught (in promise) TypeError: Failed to fetch
Below is my code for my login component and my nodejs file.
Login.js:
import React from "react";
import {Header} from './Header';
export class Login extends React.Component{
constructor() {
super();
this.state = { user: {} };
this.onSubmit = this.handleSubmit.bind(this);
}
handleSubmit(e) {
e.preventDefault();
//const proxyurl = "https://cors-anywhere.herokuapp.com/";
var self = this;
// On submit of the form, send a POST request with the data to the server.
fetch('http://localhost:3000/login', {
method: 'POST',
body: {
name: self.refs.name,
job: self.refs.job
}
})
.then(function(response) {
return response.json()
}).then(function(body) {
console.log(body);
});
}
render(){
return(
<div>
<div id="fm">
<form onSubmit={this.onSubmit} >
<div >
<label>
Username:
<input id="uname" type="text" placeholder="Name" ref="name"/>
</label>
</div>
<div >
<label>
Password:
<input id="upass" type="password" placeholder="Jo b" ref="job"/>
</label>
</div>
<input id="sub" type="submit" value="Submit" />
</form>
</div>
</div>
);
}
}
Connection.js:
var mysql = require('mysql');
var express = require('express');
var app = express();
var con = mysql.createConnection({
host: "localhost",
user: "root",
password: "",
database: "react"
});
con.connect(function(err) {
if (err) throw err;
console.log("Connected!");
//var sql = "INSERT INTO users (name, job) VALUES ('e211', 'Highway 37')";
//con.query(sql, function (err, result) {
//if (err) throw err;
//console.log("1 record inserted");
//});
});
app.post('/login', function(req, res) {
// Get sent data.
var user = req.body;
// Do a MySQL query.
var query = con.query('INSERT INTO users SET ?', user, function(err, result)
{
// Neat!
});
res.end('Success');
});
app.listen(3000, function() {
console.log('Example app listening on port 3000!');
});
On running Connection.js it connects to my database and if I try to insert data directly by writing an insert statement in the Connection.js file and running it, then it inserts into database but if I try to click on submit button on my UI it throws the above error.
Can someone tell me where I have gone wrong and guide me on the same?
You will need to enable CORS on the server this is to avoid any unwanted calls to your server API'S
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With,
Content-Type, Accept");
next();
});
app.get('/', function(req, res, next) {
// Handle the get for this route
});
app.post('/', function(req, res, next) {
// Handle the post for this route
});