Connect to mySql on VPS server eventhough works locally - javascript

I have a React front-end, with a Node back-end to connect to mySql for data. It works exactly how I want locally. However, now that I'm moving it to a VPS server, I can't seem to get my configuration correct.
The error I get is: create:1 Uncaught (in promise) SyntaxError: Unexpected token < in JSON at position 0. It's actually returning HTML, of the page that says it's can't find the page.
I setup an express server with this code:(I do realize I need to move login details to an ENV file... just haven't yet)
const express = require('express');
const mysql = require('mysql2');
const connection = mysql.createPool({
host : 'localhost:3306',
user : 'root',
password : 'xxxxx',
database : 'ppr'
});
const app = express();
app.use(express.json());
app.use(express.urlencoded({extended: false}));
app.get('/api/clients/all', function (req, res) {
// Connecting to the database.
connection.getConnection(function (err, connection) {
// Executing the MySQL query (select all data from the 'clients' table).
connection.query("SELECT * FROM clients", function (error, results) {
// If some error occurs, we throw an error.
if (error) throw error;
console.log(results);
res.json(results);
});
});
});
// Starting our server.
app.listen(3001, () => {
console.log('Listening on port http://localhost:3001');
});
I start this running on the server, and it runs. No errors.
But then my React app makes the first api call, and I get the error because it returns HTML instead of the data I'm expecting. Do I need to do something different to make it work in production? I have proxy setup in my local machine which probably makes it work... but what do I change for production?
Here's the API call that works locally, but not on the server if it helps:
componentDidMount() {
fetch('/api/clients/all')
.then(res => res.json())
.then((result) => {
this.setState({ clients: result });
console.log(result);
})
.then(
fetch(`/api/policy/all`)
.then(res => res.json())
.then((result) => {
this.setState({ policies: result });
console.log(result);
})
);
}

Related

How to send data (a url string) in express to backend from frontend?

I am trying to build a wikipedia web scraper api and this is my code:
const app = express()
const port = 3000
const url = "https://en.wikipedia.org/wiki/Yeti_Airlines_Flight_691"
axios.get(url).then(async (res) => {
try {
if (res.status == 200) {
const result = // Doing cheerio stuff here
app.get('/', (req, res) => {
res.status(200).send(result)
})
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
}
} finally {
//
}
});
How can I send url dynamically to backend using express and do some stuff then send result back to frontend?
Client side:
This is a function you define in your frontend. You set a request link, which must be known here on client side and server side. Thus take something like /request. Then use axios to send a request to the server. You can pass any parameters with „dynamic“ Information as you called it. The server will receive these informations and can handle them.
const getData = () => {
// insert your server url here instead, with the /request at the end
const requestLink = `http://localhost:3001/request`;
axios
.get(requestLink, {
params: { url: "wikipedia.de/test123" },
})
.catch((error) => {
// here you can implement error handling
console.log(error);
})
.then((res) => {
// print result, received from the server
console.log(res);
});
};
Server side:
The backend is going to wait for a request to the defined link /request.
If he receives such a request, he is executing the code. The req variable contains your dynamic data, such as the wiki url.
Use res.json to send data back to your frontend.
app.get(`/request`, (req, res) => {
// do something with the request here
console.log(req.query);
// send result to the frontend
res.json({
status: "This could be an answer to the frontend.",
});
});

Modify sent text in express.js

I'm trying to make a discord command that stores the user's data in an API. The system looks like this: User runs command -> User's tag gets stored in the API and from there I would be able to handle it from another place. My problem is that after the data is being saved once, it doesn't modify it when another user runs the command.
I have tried doing res.send() to update it and searched on the web for solutions but none of them worked.
Here is my code:
const express = require('express');
const app = express();
app.use(express.json());
const { Client } = require('discord.js');
const client = new Client({ intents: 32767 });
client.on('ready', () => {
console.log('client is now ready')
})
client.on('messageCreate', (msg) => {
if (msg.author.bot) return;
if (msg.content === 'hey') {
app.get('/', (req, res) => {
res.send(`User interacted: ${msg.author.tag}`);
})
}
});
client.login(token)
PS: I do not want to use any programs like Postman etc.
To get the most previous author to show up in the get request, you need to store that value. The app.get/app.post/etc.. methods are defining what the sever should send when particular route is hit. They are not used for storing any data. To solve this particular issue you can simply do something like this:
const express = require('express');
const app = express();
app.use(express.json());
const { Client } = require('discord.js');
const client = new Client({ intents: 32767 });
let previousUser = '';
app.get('/', (req, res) => {
res.send(`User interacted: ${previousUser}`);
})
client.on('ready', () => {
console.log('client is now ready')
})
client.on('messageCreate', (msg) => {
if (msg.author.bot) return;
if (msg.content === 'hey') {
previousUser = msg.author.tag;
}
});
client.login(token)
This code will save the previous messages author to a variable previousUser ever time a message is received that has the content 'hey'. From there, anytime you run a get request on the '/' route, it will display that user.
There are many different ways to store data, be it in memory (like above), in a database, or written to a file. I suggest you read up on express, rest apis, and NodeJS before adding more complicated logic to this program

How to fix err_http_headers_sent

I tried fix an error: [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client but I haven't idea how to do it. I've tried many possibilities, but they haven't worked, or I have wrong used that solutions.
server.js
const express = require('express')
const mysql = require('mysql')
const cors = require('cors')
const app = express()
const parser = express.urlencoded({extended:false})
app.use(cors())
app.set('view engine', 'ejs')
app.use(express.static('public'));
const con = mysql.createConnection({
host: "localhost",
user: "root",
password: "",
database: "expenseapp"
})
con.connect(err=>{
if(err)
throw err;
console.log('connected!');
})
let array = []
app.get('/',(req,res)=>{
res.render('index')
let queryName = "SELECT * from `expenses`";
con.query(queryName, (err,res)=>{
if(err)
throw err
res.forEach(element => {
array.push(element)
});
})
res.json(array)
})
app.get('/add', (req,res)=>{
res.render('add')
})
app.post('/add', parser, (req,res)=>{
let array = [req.body.product, req.body.cost]
let sqlquery = "INSERT INTO `expenses` (name, cost) VALUES (?)";
con.query(sqlquery, [array], (err,res)=>{
if(err)
throw err
console.log("saved new product");
})
res.render('add')
})
app.listen(PORT, ()=>console.log(`Server's running on PORT ${PORT}`))
app.js
.then(response => {return response.json()})
.then(data => console.log(data))
.catch(err => console.log(err))
directory order:
node_modules
public:
___javascripts
___app.js
___styles
___style.css
views:
___add.ejs
___index.ejs
package-lock.json
package.json
server.js
Give me answer how to fix that trouble please. Thanks :)
This request handler:
app.get('/',(req,res)=>{
res.render('index')
let queryName = "SELECT * from `expenses`";
con.query(queryName, (err,res)=>{
if(err)
throw err
res.forEach(element => {
array.push(element)
});
})
res.json(array)
})
is calling both res.render() and res.json(). Each of those tries to send a response to the request and the second one will trigger the error you report because you only get to send one response per request. It's not clear exactly what you want this route to be. If you want to pass the query results to the template, then you would do something like this:
app.get('/',(req,res)=>{
const queryName = "SELECT * from `expenses`";
con.query(queryName, (err,res)=>{
if (err) {
console.log(err);
res.sendStatus(500);
return;
}
res.render('index', res); // if res isn't already an array, convert it to an array
});
});
Note, several things being done differently here:
Add error handling on the query that logs the error and sends an actual error response. throw err will not be useful here.
Remove res.json() so we're only sending one response instead of two.
Call res.render() with your template and pass it the array of results so the template index can use that data in generating the page.
Move the res.render() inside the database callback where we actually have the data available.
If you intend for this route to accomplish something different than I've coded it for here, then please describe what this route is supposed to do.
FYI, you should not be using if(err) throw err; in any asynchronous callback. It's not doing you any good as none of your code can actually catch any of those asynchronously thrown exceptions and do something intelligent with them. You need real error handling in all your asynchronous operations. Don't skip that step when writing code. Don't leave it for later. Think about error handling as a primary concept when designing and first writing your code.

What is the correct nodejs architecure for database connection?

I am generally connecting to a database before listening a port like this:
//server.js
MongoClient.connect(process.env.mongo_url, { useNewUrlParser: true }, (err, client) => {
if(err) throw err
console.log('db connected')
global.db = client.db(database_name);
app.listen(process.env.port || 3000, ()=>{
console.log(`Server listening on http://localhost:${process.env.port || 3000}`)
})
});
And using it through the connection from the global variable. Lately, I started to add service layers in order to use the same service from several other places. I also integrated make-runnable lib to my services so that I can execute service functions from the terminal. Ex. node usersService.js register <email> <password> for below service.
// usersService.js
exports.register = (email, password)=>{
// business logic to register the user
}
require('make-runnable');
// usersController.js
import usersService = require('./services/usersService')
router.post('/register',async (req, res)=>{
usersService.register(req.body.email, req.body.password)
...
})
Since the service needs a db connection, I created a db module and edited the service:
// db.js
const {MongoClient} = require('mongodb')
function connect(){
return new Promise((resolve, reject)=>{
console.log(`Trying to connect to ${process.env.mongo_url}`)
MongoClient.connect(process.env.mongo_url, { useNewUrlParser: true }, (err, client) => {
if(err) return reject(err)
console.log('db connected')
resolve(client.db(database_name))
});
})
}
exports.connect = connect
// usersService.js
exports.register = (email, password)=>{
// connect to db if executed from terminal
if (require.main === module)
var db = await require('../../db.js').connect()
}
// business logic to register the user
}
require('make-runnable');
This structure works. But code snippet that I added to service for db connection in case of executing from terminal seems unpleasant. I need to add it to all service functions. How can I structure the project so that I can call each service function from the terminal that requires a db connection? Any architectural suggestions are welcome.

How to read data from POST, test it with a condition and send a response back

I'm looking for an easy solution to front-end and back-end communication.
I want to write simple JS front-end client where a user can put a number between 1 an 10 000 to guess the number that server has generated.
So the client job is to send number that user is guessing. The server should test if secretNumber is higher or lower then that provided by the user and it should send back that info.
For now, my server only sends that secret number. I'm getting it inside my client console, so the connection is working.
My question is how should I modify my server code to read the number value from request, test it and then send the right response (example -> your number is higher than the secretNumber)?
This is my server:
const express = require('express');
const app = express();
const cors = require('cors');
app.use(cors());
app.use((request, response, next) => {
console.log(request.headers);
next();
});
app.use((request, response, next) => {
request.secretNumber = Math.floor(Math.random() * 10000) + 1;
next();
});
app.get('/', (request, response) => {
response.json({
secretNumber: request.secretNumber
});
});
app.listen(3001, () => console.log("Listening on 3001"));
Here is my front-end JS code (I'm using axios):
export function guessNumber(guessValue) {
return dispatch => {
dispatch({ type: GUESS_NUMBER });
axios
.post('/guess', {
isNumber: guessValue,
})
.then(response => {
console.log(response);
})
.catch(error => {
console.log(error);
});
};
}
And I was here looking for answer, but maybe I'm to inexperiened and I need some real example...
First you need to persist the secretNumber between requests. At the moment you are generating a new value on each request.
Assuming just one client using the backend concurrently, you can do this by generating the secretNumber when the server starts and keep it in memory (assign it to a variable).
Then you can simply use route params to capture the client's guess:
app.get('/guess/:guess', (request, response) => {
const guess = params.guess;
// compare guess with secretNumber and respond accordingly
});
Alternatively you can use the request's body (https://expressjs.com/en/4x/api.html#req.body) instead of route params.

Categories

Resources