I have declared mysql, and my connection in app.js like so:
var mysql = require('mysql');
var connection = mysql.createConnection({
host: '192.168.1.75',
user: 'dev',
password: 'devaccount',
database: 'PugIt'
});
app.set('connection', connection);
And in my User.js for registration I have:
router.route('/register/steam/finish')
.get(function(req, res) {
res.render('user/register_steam');
})
.post(function(req, res) {
var connection = req.app.get('connection');
connection.connect();
// Look For Users
connection.query("SELECT * FROM Users", function(err, rows, fields) {
console.log('We Found Something!');
});
connection.end();
});
When the page first loads and I hit register, it works fine, but if I hit the button a second time I get a 500 error on my server.
But if I manually declare var connection inside each route file, this does not happen.
How come I cannot use req.app.get with MySQL, I used this method when I used to use MongoDB which worked great that way I had one main config in app.js I could alter to change in all route files if I needed. Not sure why I'm getting a 500 error on second POST
I think the connection.connect() and connection.end() on every POST request is causing problems. Drop those two lines and you should be good to go. This way the connection is only established once and all requests can re-use the same connection without constantly trying to tear it down and bring it back up again.
You can also create a pool of mysql connections if you find yourself needing greater concurrency with your database queries.
Related
I'm just learning how to make a simple web-application for my dorm that would assign each participant a random number once they enter their name. There is a form field with one text box and a button. The text box (form) needs to send the full name (a single string) to the MySQL database so that later on I could retrieve the full list with the assigned numbers to actually use the application in the real world. Just for redundancy, I've put in code that creates a new database and a table every time, but then SQL ignores it if the DB and table already exist.
My fundamental problem is that I can not get data from my form in HTML. I'm using express.js and am trying to retrieve it, then post it into my database via the SQL module. Now as I'm a complete newbie, I have no idea how it should work. For the past 4 days, I've searched all over the internet to try to solve this issue. I don't know if the js document is the problem or the HTML document.
This is my HTML form (do tell me if you would need the whole thing):
<form action="/createPerson" method="POST">
<input type="text" name="name" value="Ime in priimek">
<input type="submit" name="name" value="Potrdi" class="gumbek">
</form>
And here is my complete node.js document:
var mysql = require('mysql');
var express = require("express");
var bodyParser = require("body-parser");
var urlencodedParser = bodyParser.urlencoded({
extended: false
});
const http = require('http');
var fs = require('fs');
const app = express();
const path = require('path');
const router = express.Router();
// Unique random number generator module
const uniqueRandom = require('unique-random');
app.use(express.static(__dirname + '/public'));
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(bodyParser.json());
server = http.createServer(app);
server.listen();
// Start connecting to MySQL database
var con = mysql.createConnection({
host: "localhost",
user: "root",
password: "root",
database: "mydb"
});
//if database mydb exists, ignore database creation
let createMydb = "CREATE DATABASE if not exists mydb"
con.connect(function(err) {
if (err) throw err;
console.log("Connected!");
con.query(createMydb, function(err, result) {
if (err) throw err, console.log("Database already exists!");
console.log("Database OK (Already exists, will not create new one)");
});
});
//if table person exists, ignore table creation
let createTable = "CREATE TABLE if not exists person (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), number VARCHAR(255))";
var sql = createTable;
con.query(sql, function(err, result) {
if (err) throw err, console.log("Table exists, will not create new table");
console.log("Table OK (Already exists, will not create new one)");
console.log('Running at Port 3000');
console.log("Connected. Commencing value input into database.");
//var post = { name: req.body.name, number: random }
//app.get('/createPerson', urlencodedParser, function(err, req, res) {
if (err) throw err;
//res(req.body.name)
});
router.get('/', function(req, res) {
res.sendFile(path.join(__dirname + '/index.html'));
//__dirname : It will resolve to your project folder.
});
/*const random = uniqueRandom(1, 100);
const values = ['/createPerson', String(random())];
var insert = "INSERT INTO person (name, number) VALUES (?)"
con.query(insert, [values], function(err, result) {
if (err) throw err;
console.log("Value was inserted into database.");
});*/
app.get('/createPerson', function(req, res) {
res.render('form'); // if jade
// You should use one of line depending on type of frontend you are with
res.sendFile(__dirname + '/index.html'); //if html file is root directory
});
app.post('/createPerson', urlencodedParser, function(req, res) {
const random = uniqueRandom(1, 100);
const values = [String(req.body.name), String(random())];
var insert = "INSERT INTO person (name, number) VALUES (?)"
console.log(req.body.name);
con.query(insert, [values], function(err, result) {
if (err) throw err;
console.log("Value was inserted into database.");
res.sendFile(__dirname + '/numberAssigned.html');
res.end();
});
});
Now every time I press the button in the form, I get Cannot POST /createPerson inside the browser and no data was sent to my database. Browser (network tab) also gives me 404. Maybe it can't find the form?
I am a complete newbie at all of this, I can manage HTML and CSS, Javascript is something really new to me. If you find the time to help me, THANK YOU FROM THE BOTTOM OF MY HEART!
The problem is that you are using node.js http module and express at the same time.
You are setting up /createPerson within the express.js app, but starting the node.js http server instead. So, no end-points are present in the server you've started - hence 404 Page Not Found.
Usually, you use just one of them. Node.js http module provides an ability to start a low-level HTTP server. Express, on the other hand, is a more high-level solution for building http services. So in your case, I would stick with express and throw out http (express is using http module under the hood anyways).
But the fundamental problem of your solution is that it is too big and complex to bootstrap from scratch.
It could be really confusing to figure out what is going on in a complex app, since you are trying to do many things at once - express http server + sql database + html forms... Many things can go wrong, so better try a "Hello World" approach instead.
To debug a problem like that, I would downscale the app and try to check every little interaction level by level:
Level 1
Comment out http module usage and every mapping in express except POST for /createPerson
Make sure you run express app.listen() after the end-point setup.
Comment out all database access in /createPerson handler and leave just a log statement like that:
app.post('/createPerson', urlencodedParser, function(req, res) {
console.log(req.body.name);
}
Now run your script with node.js and try to check the POST on /createPerson with curl:
curl --data-urlencode "name=John Doe (Junior)" http://localhost:3000
(make sure you are using the right port)
Check node.js logs - you have to see a name you're sending with curl in there.
When you see the name in logs, Level 1 is complete!
Level 2
Now try to do the same POST, but form an HTML form.
Add a static mapping on /public to node.js.
Run the node.js server.
Open a page with the HTML form and POST it.
Make sure your form is sending data to correct URL and you see the data in node.js logs
Level 3
Only now, when you have data flowing from html to node.js, you can try to extend the system with a database. Reintegrate db access code back into /createPerson and debug the solution.
Good luck with the next levels!
Can someone explain or point to some tutorial where is explained how to render rows of data from mySql database into react.js component?
I've made small database using mysql workbench and this baza.js file inside my project folder:
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : 'root',
password : '',
database : 'db'
});
connection.connect(function(err) {
if (err) throw err;
connection.query("SELECT * FROM promjer", function (err, result, fields) {
if (err) throw err;
console.log(result);
});
});
When I run node baza.js in my CMD, everything seems fine, I get everything from that specific table inside CMD terminal so I guess my database is ok and it's connected with app.
What troubles me is how to render that data inside my app?
I know that React by itself can't handle data so i should use Express.js. But I don't get what to do with it. Express should be running on other port so how should I even get data to component in app which is running on port 3000 if express is running on port 9000?
Thanks in advance!
I'm working on a MERN webapp (using MySQL instead of MongoDB) and we are having an issue where at some point after querying to add an entry, the backend is somehow re-querying the last query. In the meantime, between the original entry and the duplicate one, the backend runs continuously to keep the frontend displaying up-to-date data.
I've read on old threads that MySQL for Node may have some issues with memory leaking and thus running sleep queries. I don't believe this is a frontend issue, and the backend isn't running the queries as if they were called from the function that handles the frontend button click (to submit).
I'm a noob to full-stack JS, so I don't really know where to look for an answer to this issue. I'm not sure if we should band-aid the solution and just make sure a query isn't sent without the submit button being clicked within a 1 second time span.
EDIT: Here's code for the query to add the entry (data for a music album).
db.query(insertAlbumQuery, insertAlbumValues, function(err, result) {
if (err) throw err;
console.log("1 Album added.");
});
We don't close the connection to the db after querying, one connection runs for the duration of the app's execution.
Here's the code for the db connection:
let mysql = require("mysql");
var db;
function connectDB() {
if (!db) {
db = connection = mysql.createConnection({
host: "******",
user: "******",
password: "******",
database: "******"
});
connection.connect(function(err) {
if (err) {
return console.error("error: " + err.message);
} else {
console.log("Connected to the MySQL server.");
}
});
}
return db;
}
module.exports = connectDB();
From the main, backend app.js file we have the router post
router.post("/addAlbum", (req, res) => {
const {
Album_title,
Artist,
Release_date,
Category,
Description,
Rotation
} = req.body;
album.add(Album_title, Artist, Release_date, Category, Description, Rotation, null);
});
From the front end we post with
addAlbum = currentState => {
this.setState({ Rotation: +this.state.Rotation });
axios.post("http://localhost:3001/api/addAlbum", this.state);
};
Not sure if this is enough background on the app, but I can add more snippets if needed.
I started working on a MERN App today and am trying to write a restful api. First I am using mlab to store my mongodb database. I have succesfully connected to this database after creating a user. I can manually create a collection and inject some data into this collection. From my server.js file I can then get the data stored in here.
MongoClient.connect(db_url, (err, database) => {
if (err) return console.log(err);
var collection = database.collection('memories'); // Collection called memories
app.listen(3000, () => {
console.log("Listening on 3000");
});
});
Thats all fine and dandy but I want to take it to the next level. I want to write a CRUD api for the collection Memory. Coming from django, I would like to create my model first. Therefore, in my models/memory.js:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var MemorySchema = new Schema({
name: String,
description: String
});
module.exports = mongoose.model('Memory', MemorySchema);
Then I went ahead and started working on my routes/api/api.js:
let router = require('express').Router();
let Memory = require('../../../models/memories');
router.use(function (req, res, next) {
console.log("Something is happening");
next(); // Request stops at middleware without next()
});
router.route('/memory')
.post(function (req, res) {
let memory = new Memory();
memory.name = req.body.name;
memory.description = req.body.description;
memory.save(function (err) {
if (err) {
res.send(err);
}
res.json({message: 'Memory Created'});
});
})
.get(function (req, res) {
res.json({message: 'First memory'});
});
module.exports = router;
And in my server.js I call this module:
const apiRoutes = require('./routes/api/api');
app.use('/api/', apiRoutes);
However, after testing the post api with postman, it the POST request just takes forever before showing up as Could not get any response. However, the GET request works. What am I missing?
EDIT: So the post function is having trouble saving the model instance...
Try adding results as the first parameter in the callback of the save function, then res.json(results, { message: "Memory Created" }) to see if you are returned anything.
The main difference between the post and the get method is that the post method uses Mongoose, while the get doesn't. If you fail to connect to the database then the response can time out due to memory.save(...) not working as it should. And there are no responses sent outside the callback to save, so if your program never enter it, you will never send a response. The request will time out eventually.
In your model file you register a model on the following line:
module.exports = mongoose.model('Memory', MemorySchema);
Mongoose will then look for data in the memorys collection. If you change it to
module.exports = mongoose.model('Memory', MemorySchema, 'memories');
it will use the memories collection instead. This will make it consistent with the connection-to-db snippet you posted. I don't know if that will fix your issue though. I would suggest changing the connection code to
mongoose.connect(dburl, {
useMongoClient: true
});
instead of the native mongo client. You can add these lines too
mongoose.connection.on('connected', function () {
console.log('Mongoose connected');
});
mongoose.connection.on('error', function (err) {
console.log('Mongoose connection error: ' + err);
});
mongoose.connection.on('disconnected', function () {
console.log('Mongoose disconnected');
});
right after the connection code to help with debugging. Make sure you get connected when starting the app.
If you see an error similar to this Error: Can't set headers after they are sent. in the node terminal window, it might be because you are sending two responses in the post function. If an error occurs while saving it will enter the if(err) block, send a response async then go to the res.json(...) response and send that too.
So you have to return after sending the response to exit the function. Either like this
res.send(err);
return;
or like this
return res.send(err);
Same for the json response.
If that doesn't fix the problem you should either fire up the debugger (node --inspect or nodemon --inspect), or insert a console.log('inside post'); inside the post function to see that you're actually entering it.
This question already has answers here:
Caching database queries with Node.js
(3 answers)
Closed 9 years ago.
I'm new to Node.js and Express. I understand that the functions are executed asynchronously, but I don't get how to use global variables. Here I connect to mysql database, retrieve the query results and render them on my test.html page. Then in the mysql.js file, I want to save those results in an array called entry, so that the other get() can use those same results. The only alternative I can think of with my limited understanding of Node.js is to just query the database again in the other get(). How can I use this global to save my query results from the anonymous function? Also what event and function do I call so that I can execute my connection.end() correctly?
//mysql.js
var express = require('./express');
var mysql = require('mysql');
var hbs = require('./hbs');
var app = express();
app.set('view engine', 'html');
app.engine('html', hbs.__express);
var connection = mysql.createConnection({
host: '127.0.0.1',
user: 'root',
password: 'password',
database: 'db',
port: 3306
});
connection.connect();
entry=[];
app.get('/', function(req, res){
connection.query(
'SELECT * FROM table where ID < 10;',
function(err, result, fields)
{
if(err) throw err;
res.render('test',{title:"title", entries:result});
entry = result;
});
});
app.get('/article/:id', function(req, res) {
res.render('article',{title:entry.title, blog:entry});
});
app.listen(3000);
//connection.end();
<h1>HTML Test</h1>
{{#each entries}}
<p>
{{Name}}<br/>
Name: {{Name}}
</p>
{{/each}}
The easy way is to run a query to retrieve each article when it’s requested. Your first route (for '/') looks fine. Just add a similar query for your second route:
connection.query('SELECT * FROM table WHERE ID=?', [req.params.id],
function(err, rows, fields)
{
if (err) { throw err; }
if (!rows.length) { return res.send(404); }
res.render('article', { title: rows[0].title, blog: rows[0] });
})
But if you really want to cache entries:
Use redis or memcached if you want real caching. E.g. if you’re concerned about being slashdotted or whatever it’s called now. This needs a Redis or Memcache daemon and is a bit more involved.
In your code, the SQL query doesn’t impose an ORDER. The only way to get an article with a particular ID is to loop over the global entry array looking at each one until you find the right one.
Adding an ORDER BY clause doesn’t help because you could still skip an ID (or later delete an entry with a particular ID). You still have to loop over the entire array to find the one you want.
If you are done using the database, you can call connection.end. But if your app runs “forever” and you plan to access the DB from time to time, there’s no need to call it. The connection will be killed if/when your app is killed. A cleaner way is to let the mysql module manage connections for you. See the documentation section “Pooling connections”.