Node.js/Express - Where to put MySQL connection? - mysql

I'm learning how to connect to a mysql database using node.js for my first express web application:
http://expressjs.com/guide/database-integration.html#mysql
Where do I put this code in the Express application that I've just generated? Do I just put it in the app.js file?
It seems to me, that if I put it in app.js, the query-data will remain stagnant for all future web-requests. Where should I put this code if each web-request must have current data from the database?
Sorry, I've written other node.js applications, but I'm new with using it as a web server, and I'm totally new to express. I'd appreciate any guidance about where to put things.

You can use this simplified block of code that I copied over:
'use strict';
var mysql = require('mysql');
var database = {
initDB: function() {
this.pool = mysql.createPool({
//fill in
}});
},
query: function(query, callback) {
this.pool.query(query, function(err, res) {
if (err) {
this.initDB();
//you can call the query again here if you want
} else {
callback(res);
}
});
},
disconnect: function() {
if (this.pool) {
this.pool.end();
}
}
};
module.exports = database;
You can call the initDB() method inside of your server init code, then call query() method whenever you need to make a real query.

Related

How to Host HTML on a different server than Heroku

I have my index.html and the necessary .js files on heroku. Everything works fine. Now, I don't want to send my users to "myappname.herokuapp.com", so I plan to use my own website to store the .html file, but when the user taps "submit" on my HTML form, I want to execute the Herok NodeJS code.
Here is what the html looks like
<script>
const form = document.querySelector("form");
form.addEventListener("submit", async (e) => {
e.preventDefault();
try {
displayStatus("processing...");
const request = new Request("/file-upload", {
method: "POST",
body: new FormData(form),
});
const res = await fetch(request);
const resJson = await res.json();
displayResult(resJson.result);
} catch (err) {
displayStatus("an unexpected error");
console.error(err);
}
});
function displayResult(result) {
const content = `Your ID: ${result.id}`;
displayStatus(content);
}
function displayStatus(msg) {
result.textContent = msg;
}
</script>
How can I call this "/file-upload" from my HTML that is located on "mywebsite.com/index.html" while the actual NodeJS logic runs on "myappname.herokuapp.com"
I've tried to replace the "/file-upload" with "myappname.herokuapp.com/file-upload" but it doesn't work.
Again, the goal is to use what I have on Heroku, but not have the users go to "myappname.herokuapp.com" instead they should go to "mywebsite.com/index.html"
Thank you
Actually, replacing "/file-upload" with "myappname.herokuapp.com/file-upload" did the trick. The only issue is my "const request = new Request" request returning an error all the time, but Heroku logs shows a successful execution of "file-upload"

Loopback autoupdate not creating custom models

I'm trying to create an app using Loopback (V3) and i've encountered a weird error.
I'm trying to create my Mysql tables using autoupdate(), but for my custom models it is not working.
This is what i've tried so far ->
var server = require('../server');
var ds = server.dataSources.db;
var models = ['test','Post','User', 'AccessToken', 'ACL', 'RoleMapping', 'Role'];
ds.isActual(models, function(err, actual) {
if (!actual) {
ds.autoupdate(null, function(err,result){
console.log("DONE!");
console.log(result);
});
};
});
The script works. If the database is empty it will create tables for all EXCEPT test and Post. Those are my custom models, the others are built into loopback.
Is it because of model type? (tried Model and PersistedModel) or is it something else? I even tried without the isActual check and still nothing.
I would recommend that you keep two separate arrays for built-in models and custom models and write code like following, that way you could know where the issue is. also, I think there is an error in your code near ds.autoupdate(null, fun.....
please follow according to the below code
var builtInModels = ['AccessToken', 'ACL', 'RoleMapping','Role'];
var userDefinedModels = ['Post','test'];
// migrate built-in models
dataSource.isActual(builtInModels, function (err, actual) {
if (!actual) {
dataSource.autoupdate(builtInModels, function (err, result) {
if(err) console.log(err);
console.log('Datasource Synced: Built in models');
});
}
});
// migrate userdefined models
dataSource.isActual(userDefinedModels, function (err, actual) {
if (!actual) {
dataSource.autoupdate(userDefinedModels, function (err, result) {
if (err) console.log(err);
console.log('Datasource Synced: User defined models');
});
}
});

Proxy webpack-dev-server based on request payload to return json file

So I've searched and I think a saw the entire internet but no solution regarding the issue I encounter.
I have multiple http request which I want to mock. All request have the same url but deviate based on the requestPayload which contain a graphQl query. Based on this query I want to return a specific json file. All proxy settings I have found can handle parameters but do not handle responses based on requestPayload.
Have you taken a look over this functionality?
https://webpack.js.org/configuration/dev-server/#devserver-before
as far as webpack-dev-server is an instance of express app you are able to setup it in the before/after hooks. Hooks get app (server) instance as a first argument.
so for your case your webpack development config would look like:
module.exports = {
//...
devServer: {
before: function(app) {
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.get('/some/path/graphql', function(req, res) {
var query = req.body;
// ...your custom logic of
// specific query handling goes here
if (condition(query)) {
res.json({ mockedResponse: 'foo' });
} else {
res.json({ mockedResponse: 'bar' });
}
});
}
}
};
UPD: keep in mind if you're using proxy config for devServer you might want to use after hook instead of before to let your requests be proxified if needed.

How can I access my couchdb from my node server using REST/JSON/GET/POST?

I'm trying to access my couchdb from a node.js server.
I've followed the nodejs tutorial, and have set up this simple nodejs server:
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('Hello World\n');
}).listen(80, "127.0.0.1");
console.log('Server running at http://127.0.0.1:80/');
I would like to make RESTful http and POST requests to the nodejs server. The nodejs server should then be able to make GET/POST request to the Couchdb, which responds with JSON objects.
How might I do this?
First of all I am the author of nano and will use it in this response.
Here go some simple instructions to get started with node.js and CouchDb.
mkdir test && cd test
npm install nano
npm install express
If you have couchdb installed, great. If you don't you will either need to install it setup a instance online at iriscouch.com
Now create a new file called index.js. Inside place the following code:
var express = require('express')
, nano = require('nano')('http://localhost:5984')
, app = module.exports = express.createServer()
, db_name = "my_couch"
, db = nano.use(db_name);
app.get("/", function(request,response) {
nano.db.create(db_name, function (error, body, headers) {
if(error) { return response.send(error.message, error['status-code']); }
db.insert({foo: true}, "foo", function (error2, body2, headers2) {
if(error2) { return response.send(error2.message, error2['status-code']); }
response.send("Insert ok!", 200);
});
});
});
app.listen(3333);
console.log("server is running. check expressjs.org for more cool tricks");
If you setup a username and password for your CouchDB you need to include it in the url. In the following line I added admin:admin# to the url to exemplify
, nano = require('nano')('http://admin:admin#localhost:5984')
The problem with this script is that it tries to create a database every time you do a request. This will fail as soon as you create it for the first time. Ideally you want to remove the create database from the script so it runs forever:
var express = require('express')
, db = require('nano')('http://localhost:5984/my_couch')
, app = module.exports = express.createServer()
;
app.get("/", function(request,response) {
db.get("foo", function (error, body, headers) {
if(error) { return response.send(error.message, error['status-code']); }
response.send(body, 200);
});
});
});
app.listen(3333);
console.log("server is running. check expressjs.org for more cool tricks");
You can now either manually create, or even do it programmatically. If you are curious on how you would achieve this you can read this article I wrote a while back Nano - Minimalistic CouchDB for node.js.
For more info refer to expressjs and nano. Hope this helps!
I have a module (node-couchdb-api) I've written for this exact purpose. It has no ORM or other features like that, it's just a simple wrapper for the HTTP API that CouchDB offers. It even follows the conventions established by Node.JS for async callbacks, making your code that much more consistent all-around. :)
You can use node.js module such as Cradle to work with CouchDB.
Here is a list of available Node.JS modules: https://github.com/joyent/node/wiki/modules
Just make HTTP requests. I would recommend request
Here's an example from my code
request({
"uri": this._base_url + "/" + user._id,
"json": user,
"method": "PUT"
}, this._error(cb));
Here's another example from my code
// save document
"save": function _save(post, cb) {
// doc changed so empty it from cache
delete this._cache[post.id];
// PUT document in couch
request({
"uri": this._base_url + "/" + post._id,
"json": post,
"method": "PUT"
}, this._error(function _savePost(err, res, body) {
if (body) {
body.id = post.id;
body.title = post.title;
}
cb(err, res, body);
}));
}

node.js / node_mysql - stale connections get "NO database selected" error

We have a node.js app that uses node_msyql, a great little library for accessing MySQL databases.
Unfortunately, if our connection is not used for maybe 8-10 hours, the next time we try to run a query, we get a "No database selected" error back from the server. We need to add a "USE db" somewhere, but I can't figure out where.
Now, it makes sense to me that connections would go stale, and it seems as though node_mysql is refreshing those stale connections, but there doesn't seem to be a way to make sure that the right db is connected. I was looking for a .connected() callback or event or something that would let me make sure the correct DB was alway USE'd, but no luck so far.
Any suggestions how to do this?
Ys, client tries to reconnect. You can try to query 'use db' on reconnect using code like this:
client._connection.on('connect', function() { client.query('use db'); })
This is where reconnection happen in the node-mysql ('end' handler):
https://github.com/felixge/node-mysql/blob/master/lib/mysql/client.js
var connection = self._connection = new Stream(),
parser = self._parser = new Parser();
connection
.on('error', function(err) {
var connectionError = err.code && err.code.match(/ECONNREFUSED|ENOTFOUND/);
if (connectionError) {
if (cb) {
cb(err);
return;
}
}
self.emit('error', err);
})
.on('data', function(b) {
parser.write(b);
})
.on('end', function() {
if (self.ending) {
self.connected = false;
self.ending = false;
return;
}
if (!self.connected) {
return;
}
self.connected = false;
self._prequeue(connect);
});
connection.connect(self.port, self.host);
because of node-mysql update following code maybe work:
client._socket.on('connect', function() {
console.log("use ",DB_NAME);
client.query('use '+DB_NAME);
});
When using the node-mysql-promise package, you may want to use this code to do the same:
dbConn.pool.on('connection', function() {
dbConn.pool.query("USE myDBname");
} );