I want to create html content that looks something like this using node.js.
<div class="outputs">
...
</div>
I have the following code:
var mongoose = require("mongoose");
var express = require("express");
var bodyParser = require("body-parser");
var Url = require("./models/Url");
var shortId = require("shortid");
var http = require("http");
var app = express();
var { JSDOM } = jsdom;
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
mongoose.connect(process.env.MLAB_URI);
app.get("/urls", (req, res, next) => {
Url.find({}, function(err, data) {
res.json(data);
console.log(data.length);
});
});
app.get("/deletebase", (req, res, next) => {
Url.deleteMany({}, function(err, data) {
res.json(data);
});
});
app.use(express.static(__dirname + "/"));
app.get("/:shortUrl", function(req, res, next) {
Url.findOne({ shortUrl: req.params.shortUrl }, function(err, findUrl) {
if (err) console.log(err);
if (!findUrl) {
return next({ status: 400, message: "unknown shorturl" });
}
res.redirect(findUrl.longUrl);
});
});
app.post("/", function(req, res) {
var url = new Url(req.body);
var hostname = req.headers.host;
var expression = /[-a-zA-Z0-9#:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()#:%_\+.~#?&//=]*)?/gi;
var regex = expression;
if (regex.test(url) === true) {
url.shortUrl = shortId.generate();
url.fullUrl = "https://" + hostname + "/" + url.shortUrl;
url.save(function(err, savedUrl) {
if (err) console.log(err);
res.redirect("https://" + hostname);
});
} else {
res.redirect("https://" + hostname);
}
});
var options = {
runScripts: "dangerously",
resources: "usable"
};
app.listen(3000, function() {
console.log("RUNNING");
});
I want to get length of the data and create that many div objects with longUrl and shortUrl objects in it. Also when database will be updated new div object should be created, and when I delete database information all the div elements should be deleted too, is this possible to do?
You should be using a templating engine for this the two most popular ones for Node.js are pug(formerly Jade) and hbs(Handlebars.js).
There are a lot of other template engines here you could consider.
Related
I am trying to do my first API Rest and I am following some tutorials. I am requesting all the articles in a MongoDB database.
This is the code of the main:
var express = require("express"),
app = express(),
http = require("http"),
bodyParser = require("body-parser"),
methodOverride = require("method-override"),
server = http.createServer(app),
mongoose = require('mongoose');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(methodOverride());
// Import Models and controllers
var models = require('./models/article')(app, mongoose);
var articleCtrl = require('./controllers/articleController');
// Example Route
var router = express.Router();
router.get('/', function(req, res) {
res.send("Hello world!");
});
articles.route('/articles/:id')
.get(articleCtrl.findById);
articles.route('/articles')
.get(articleCtrl.findAllarticles)
.post(articleCtrl.addarticle);
app.use('/api', articles);
app.use(router);
mongoose.connect('mongodb://localhost/ustcg', { useNewUrlParser: true ,useUnifiedTopology: true}, function(err, res) {
if(err) {
console.log('ERROR: connecting to Database. ' + err);
}
app.listen(3000, function() {
console.log("Node server running on http://localhost:3000");
});
});
The code of the controller is here:
// Import article and mongoose
var mongoose = require('mongoose');
var Article = mongoose.model('Article');
//GET - Return a article with specified ID
exports.findById = function(req, res) {
Article.findById(req.params.id, function(err, Article) {
if(err) return res.send(500, err.message);
console.log('GET /article/' + req.params.id);
res.status(200).jsonp(Article);
});
};
//GET - Return all articles in the DB
exports.findAllarticles = function(req, res) {
Article.find(function(err, Article) {
if(err) res.send(500, err.message);
console.log('GET /article')
res.status(200).jsonp(Article);
});
};
//POST - Insert a new article in the DB
exports.addarticle = function(req, res) {
console.log('POST');
console.log(req.body);
var Article = new Article({
title: req.body.title,
paragraphs: req.body.paragraphs
});
Article.save(function(err, Article) {
if(err) return res.send(500, err.message);
res.status(200).jsonp(Article);
});
};
The model:
//We create the model
exports = module.exports = function(app, mongoose) {
var ArticleSchema = new mongoose.Schema({
title: { type: String },
paragraphs: { type: Array },
});
mongoose.model('Article', ArticleSchema);
};
When I tried to request the following http request it send me 404 error. I can not see any logs on the console so it is not entering the methods in order to see the exception is happening so I am stucked with this...
If someone could help me it would be nice.
what is articles variable in your main file.
I tried your code in my machine and struggled with articles variable and you have extra imports which are not required.
Try following code it works fine
var express = require("express");
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
var articleCtrl = require('./sample.controller');
var router = express.Router();
router.get('/', function(req, res) {
res.send("Hello world!");
});
router.get('/articles/:id', articleCtrl.findById);
router.post('/articles', articleCtrl.addarticle);
router.get('/articles', articleCtrl.findAllarticles)
// app.use('/api', router);
app.use(router);
app.listen(3000, function() {
console.log("Node server running on http://localhost:3000");
});
if you uncomment app.use('/api', router); then you can also use routes as localhost:3000/api/articles
I am creating a node and express REST application with a PostgreSQL database.
My question is how to define the connection variable globally in a minimalist express application (for a Hello World example)?
I have the following file structure with the following key files included.
{PROJECT_ROOT}\bin\www
{PROJECT_ROOT}\app.js
{PROJECT_ROOT}\routes\index.js
{PROJECT_ROOT}\db\db.js
{PROJECT_ROOT}\db\location.js
{PROJECT_ROOT}\OTHER FILES
The db.js should contain definition of a variable for a connection to the PostgreSQL database globally. This variable should be shared by other modules whenever necessay so that duplicated connections should be avoided.
db.js
var promise = require('bluebird');
/**
*Use dotenv to read .env vars into Node
*/
require('dotenv').config();
const options = {
// Initialization Options
promiseLib: promise,
connect(client, dc, useCount) {
const cp = client.connectionParameters;
console.log('Connected to database:', cp.database);
}
};
const pgp = require('pg-promise')(options);
const connectionString = process.env.PG_CONN_STR;
const db = pgp(connectionString);
module.exports = {
pgp, db
};
location.js defines the business logic to manipulate the gcur_point_location table.
var db_global = require('./db');
var db = db_global.db;
// add query functions
module.exports = {
getAllLocations: getAllLocations,
getLocation: getLocation,
createLocation: createLocation,
updateLocation: updateLocation,
removeLocation: removeLocation
};
function getAllLocations(req, res, next) {
db.any('select * from gcur_point_location')
.then(function (data) {
res.status(200)
.json({
status: 'success',
data: data,
message: 'Retrieved ALL GCUR Point Locations'
});
})
.catch(function (err) {
return next(err);
});
}
function getLocation(req, res, next) {
var locationId = parseInt(req.params.id);
db.one('select * from gcur_point_location where locationid = $1', locationId)
.then(function (data) {
res.status(200)
.json({
status: 'success',
data: data,
message: 'Retrieved ONE Location by Id'
});
})
.catch(function (err) {
return next(err);
});
}
function createLocation(req, res, next) {
req.body.age = parseInt(req.body.age);
db.none('insert into gcur_point_location(locationname, locationstatus, lng, lat)' +
'values(${locationname}, ${locationstatus}, ${lng}, ${lat})',
req.body)
.then(function () {
res.status(200)
.json({
status: 'success',
message: 'Inserted one Location'
});
})
.catch(function (err) {
return next(err);
});
}
function updateLocation(req, res, next) {
db.none('update gcur_point_location set locationname=$1, locationstatus=$2, lng=$3, lat=$4 where locationid=$5',
[req.body.locationname, req.body.locationstatus, parseFloat(req.body.lng),
parseFloat(req.body.lat), parseInt(req.params.id)])
.then(function () {
res.status(200)
.json({
status: 'success',
message: 'Updated Location'
});
})
.catch(function (err) {
return next(err);
});
}
function removeLocation(req, res, next) {
var locationId = parseInt(req.params.id);
db.result('delete from gcur_point_location where locationid=$1', locationId)
.then(function (result) {
/* jshint ignore:start */
res.status(200)
.json({
status: 'success',
message: `Removed ${result.rowCount} Location`
});
/* jshint ignore:end */
})
.catch(function (err) {
return next(err);
});
}
Likewise, munipulation of different tables will be defined in individual js files. All of them will require the db.js.
routes/index.js
var express = require('express');
var router = express.Router();
var db = require('../db/location');
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
router.get('/api/locations', db.getAllLocations);
router.get('/api/location/:id', db.getLocation);
router.post('/api/location', db.createLocation);
router.put('/api/location/:id', db.updateLocation);
router.delete('/api/location/:id', db.removeLocation);
module.exports = router;
app.js
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser');
var logger = require('morgan');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter);
app.use('/users', usersRouter);
// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});
// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};
// render the error page
res.status(err.status || 500);
res.render('error');
});
module.exports = app;
I would like to have some ideas about whether the above code is a good or a bad practise or any potential failure?
Most of the code makes sense to me, though I would implement your own ORM and model layers, so you can remove some of the code for PSQL queries and follow MVC design pattern. If all you are building is an express api server, then you do not need the View portion.
I usually have a file called ORM, which has something similar to the following:
var orm = {
all: function(tableInput, cb) {
var queryString = "SELECT * FROM " + tableInput + ";";
connection.query(queryString, function(err, result) {
if (err) {
throw err;
}
cb(result);
});
},
create: function(table, cols, vals, cb) {
var queryString = "INSERT INTO " + table;
queryString += " (";
queryString += cols.toString();
queryString += ") ";
queryString += "VALUES (";
queryString += printQuestionMarks(vals.length);
queryString += ") ";
console.log(queryString);
connection.query(queryString, vals, function(err, result) {
if (err) {
throw err;
}
cb(result);
});
},
// An example of objColVals would be {name: panther, sleepy: true}
update: function(table, objColVals, condition, cb) {
var queryString = "UPDATE " + table;
queryString += " SET ";
queryString += objToSql(objColVals);
queryString += " WHERE ";
queryString += condition;
console.log(queryString);
connection.query(queryString, function(err, result) {
if (err) {
throw err;
}
cb(result);
});
}
};
// Export the orm object for the model (cat.js).
module.exports = orm;
Then I define a model file for each table you have in psql as following:
// Import the ORM to create functions that will interact with the database.
var orm = require("../config/orm.js");
var cat = {
all: function(cb) {
orm.all("cats", function(res) {
cb(res);
});
},
// The variables cols and vals are arrays.
create: function(cols, vals, cb) {
orm.create("cats", cols, vals, function(res) {
cb(res);
});
},
update: function(objColVals, condition, cb) {
orm.update("cats", objColVals, condition, function(res) {
cb(res);
});
}
};
// Export the database functions for the controller (catsController.js).
module.exports = cat;
A controller:
var express = require("express");
var router = express.Router();
// Import the model (cat.js) to use its database functions.
var cat = require("../models/cat.js");
// Create all our routes and set up logic within those routes where required.
router.get("/", function(req, res) {
cat.all(function(data) {
var hbsObject = {
cats: data
};
console.log(hbsObject);
res.render("index", hbsObject);
});
});
router.post("/api/cats", function(req, res) {
cat.create(["name", "sleepy"], [req.body.name, req.body.sleepy], function(result) {
// Send back the ID of the new quote
res.json({ id: result.insertId });
});
});
router.put("/api/cats/:id", function(req, res) {
var condition = "id = " + req.params.id;
console.log("condition", condition);
cat.update(
{
sleepy: req.body.sleepy
},
condition,
function(result) {
if (result.changedRows === 0) {
// If no rows were changed, then the ID must not exist, so 404
return res.status(404).end();
}
res.status(200).end();
}
);
});
// Export routes for server.js to use.
module.exports = router;
This follows MVC design pattern which is very easy to read and understand. So my whole folder structure would look something like this:
Best practices for structuring a database layer with pg-promise are shown in pg-promise-demo.
For a complete, real-world example of using that approach, see LISK database layer.
I created some code (a simple file uploader) that works well all on one file. I would like to start breaking up the code into several files. I would like to have a routes.js (to control the routes), imports.js (that contains my function) and my server. I am having problems calling my imports from the route. I am getting error imports is not a function. Thank you!!
Server.js -----------------------------------------------------------
var express = require('express');
var app = express();
var passport = require('passport');
var ejs = require('ejs');
var bodyParser = require('body-parser');
var imports = require('./src/import.js');
var port = process.env.PORT || 8080;
app.use(express.static('public'));
require('./src/import')(imports);
require('./app/routes.js')(app, imports);
app.listen(port);
console.log('The app is running on port ' + port)
routes.js-----------------------------------------------------------
module.exports = function (app, imports) {
//home Page
app.get('/', function (req, res) {
res.render('index.ejs');
});
app.post('/import', imports(){});
};
import.js---------------------------------------------
var multer = require('multer');
var fs = require('fs');
module.exports = function (imports) {
var imports = multer({ dest: 'C:/Users/ron/temp/' });
var type = imports.single('file');
imports( type, function (req, res) {//removed type
var fileType = req.file.type;
console.log('output' + req.file);
console.log(fileType);
var file = __dirname + "/" + req.file.name;
fs.readFile(req.file.path, function (err, data) {
fs.writeFile(file, data, function (err) {
if (err) {
console.log(err);
} else {
var fileName = req.file.originalname;
response = {
message: 'File uploaded successfully',
fileinfo: req.file,
filename: fileName
};
}
console.log(response);
res.end(JSON.stringify(response));
var filePath = req.file.destination + req.file.originalname;
fs.rename(req.file.destination + req.file.filename, req.file.destination + req.file.originalname, function (err) {
if (err) console.log('ERROR:' + err);
console.log('the path is...' + filePath);
console.log('the name is...' + fileName);
});
});
});
});
};
Single file solution..................................................
var express = require('express');
var app = express();
var passport = require('passport');
var ejs = require('ejs');
var bodyParser = require('body-parser');
var multer = require('multer');
var fs = require('fs');
var port = process.env.PORT || 8080;
var imports = multer({ dest: 'C:/Users/ron/temp/' });
var type = imports.single('file');
var urlencodedParser = bodyParser.urlencoded({extended: false});
app.use(bodyParser.urlencoded({ extended: false }));
app.use(express.static('public'));
app.get('/', function (req, res) {
res.render('index.ejs');
});
app.post('/import', type, function (req, res) {//removed type
var fileType = req.file.type;
console.log('output' + req.file);
console.log(fileType);
var file = __dirname + "/" + req.file.name;
fs.readFile(req.file.path, function (err, data) {
fs.writeFile(file, data, function (err) {
if (err) {
console.log(err);
} else {
var fileName = req.file.originalname;
response = {
message: 'File uploaded successfully',
fileinfo: req.file,
filename: fileName
};
}
console.log(response);
res.end(JSON.stringify(response));
var filePath = req.file.destination + req.file.originalname;
fs.rename(req.file.destination + req.file.filename, req.file.destination + req.file.originalname, function (err) {
if (err) console.log('ERROR:' + err);
console.log('the path is...' + filePath);
console.log('the name is...' + fileName);
});
});
});
});
app.listen(port);
console.log('The app is running on port ' + port)
Note that every function you include in your router must have reqest and response object as a parameter.
Change your function as :
function imports (req,res){
//your code
}
module.exports ={
imports:imports
}
And now import this function in router file.
I have the following Node.js code:
var app, fs, express
fs = require("fs")
app = require("http").createServer(function (req, res) {
var file
file = req.url === "/" ? "/index.html" : req.url
console.log(req.method + " " + file)
return fs.readFile("./views" + file, function (err, data) {
if (err != null) {
res.write(404)
return res.end("<h1>HTTP 404 - Not Found</h1>")
}
res.writeHead(200)
return res.end(data)
})
})
app.listen(3000, function () {
return console.log("running...")
})
I need to include Express.js in my application, for example:
app = express()
express = require("express")
app.use(express.bodyParser())
app.use(app.router)
app.get("/form", function (req, res) {
res.sendfile("./form.html")
})
http.createServer(app).listen(3000)
How to combine those two snippets?
By joining 2 code in one , i guess you want to use the middleware you described in 1st file
var app = express();
var express = require("express");
app.use(express.bodyParser());
app.use(app.router);
app.get("/form", function (req,res){
res.sendfile("./form.html");
});
app.use(function(req, res) {
var file;
file = req.url === '/' ? '/index.html' : req.url;
console.log(req.method + " " + file);
return fs.readFile("./views" + file, function(err, data) {
if (err != null) {
res.write(404);
return res.end("<h1>HTTP 404 - Not Found</h1>");
}
res.writeHead(200);
return res.end(data);
})
http.createServer(app).listen(3000);
// Create app with Express
let app = express();
// Create a Node server for Express app
let server = http.createServer(app);
// Parse application/json
app.use(bodyParser.json());
// Parse application/vnd.api+json as json
app.use(bodyParser.json({ type: 'application/vnd.api+json' }));
// Parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));
app.get("/form", function (req,res){
res.sendfile("./form.html");
});
app.use(function(req, res) {
var file;
file = req.url === '/' ? '/index.html' : req.url;
console.log(req.method + " " + file);
return fs.readFile("./views" + file, function(err, data) {
if (err != null) {
res.send(404);
}
res.json(data);
})
server.listen(3000);
I have a route.js which looks like this:
module.exports = function(app) {
app.get('/tip', function(req, res) {
res.render("tip");
});
app.get('/article', function(req, res) {
res.render("article");
});
app.get('/article1', function(req, res) {
res.render("article1");
});
app.get('/article2', function(req, res) {
res.render("article2");
});
app.get('/article3', function(req, res) {
res.render("article3");
});
app.get('/modules/:name', function(req, res) {
var name = req.params.name;
res.render('modules/' + name);
});
app.get('/modules/esaver/:name', function(req, res) {
var name = req.params.name;
res.render('modules/esaver/' + name);
});
};
Considering i have over 200 different routes to create, i would end up with stuff like 'article1', 'article2' etc
and my app.js is like:
var express = require('express')
,http = require('http')
,fs = require('fs')
,path = require('path');
var app = express();
html_templates = __dirname + '/html_templates';
app.set('views', html_templates + '/views');
app.set('view engine', 'jade');
app.use('/Core', express.static(__dirname + '/Core'));
app.listen(3000, function () {
console.log("express has started on port 3000");
});
require('./html_templates/controller/routes.js')(app);
Is there any dynamic way to create this?
I would do the same thing you did for /modules/:name
app.get('/article/:id', function(req , res){
res.render('article' + req.params.id);
});
It would be more meaningful from a rest point of view.
If you cannot do it for any particular reason you might want to do something like:
var articlesEndpoints = ['/article2', '/article3'];
articlesEndpoints.forEach(function(name) {
app.get(name, function(req, res) {
res.render(name);
});
});
Is this what you meant?
Finally got it working..
In cases where I got, article1, article2 etc:
app.get('/:name(article|article2|article3)?', function(req, res) {
var name = req.params.name;
res.render(name);
});
In cases where I got multi level url, I created a custom function:
function geturl(url) {
app.get('/' + url + '/' + ':name', function(req, res){
var name = req.params.name;
res.render(url + '/' + name);
});
};
There are many ways to implement dynamic express routes. It depends to a great extent on the structure you have implemented in your project, here I leave an example of dynamic routes and I hope it will be useful.
RouterService.js
module.exports = (function(myCustomRoutes) {
let express = require('express');
let router = express.Router();
let methods = Object.keys(myCustomRoutes); // getting methods ('get', 'post'... etc)
let routesMethod = null;
let url = null;
for(i in methods) {
routesMethod = Object.keys(myCustomRoutes[methods[i]]);
for(j in routesMethod) {
url = '/' + routesMethod[j];
url += '/:' + myCustomRoutes[methods[i]][routesMethod[j]].params.join('/:');console.log(url);
router[methods[i]](url, myCustomRoutes[methods[i]][routesMethod[j]].controller);
}
}
return router;
})();
CustomRoutes.js
module.exports = (function() {
let routes = {get: {}, post: {}};
let routerService = require('./RouterService');
// GET: /dynamic1
routes.get.dynamic1 = {
params: [],
controller: function(req, res, next) {
res.send('route 1');
}
};
// GET: /dynamic2/:param1
routes.get.dynamic2 = {
params: [':param1'],
controller: function(req, res, next) {
res.send('route 2');
}
};
// POST: /dynamic3/:param1/:param1
routes.post.dynamic3 = {
params: ['param1', 'param2'],
controller: function(req, res, next) {
res.send('route 3');
}
};
/*
* Export a router with paths
* GET: /dynamic1
* GET: /dynamic2/:param1
* POST: /dynamic3/:param1/:param1
**/
return routerService(routes);
})();
app.js
let express = require('express');
let app = express();
/*
* Option 1
* GET: /dynamic1
* GET: /dynamic2/:param1
* POST: /dynamic3/:param1/:param1
**/
app.use(require('CustomRoutes')());
/*
* Option 2
* GET: /api/v1/dynamic1
* GET: /api/v1/dynamic2/:param1
* POST: /api/v1/dynamic3/:param1/:param1
**/
app.use('/api/v1', require('CustomRoutes')());
Here is what I did to create dynamic APIs while I am in control over which API allows access to which methods. To maintain the APIs from now on, you can just edit the APIs array.
const APIs = [
{
route: 'order',
methods: ['get', 'post']
},
{
route: 'item',
methods: ['get']
},
]
APIs.forEach(api => {
api.methods.forEach(method => {
app[method]('/' + api.route, (req, res) => require('./routes/' + api.route)[method](req, res))
})
})
Here are a couple of other solutions:
app.get(^\/article(\d{1,3})?\/?$, function(req, res, next) {
var n;
if (req.params[0])
n = parseInt(req.params[0], 10);
if (!n || (n > 0 && n < 900))
res.render('article' + (n ? n : ''));
else
next();
});
or use app.all for the first solution or use a generic middleware:
app.use(function(req, res, next) {
var m = ^\/article(\d{1,3})?\/?$.exec(req.url);
if (m) {
var n;
if (m[0])
n = parseInt(m[0], 10);
if (!n || (n > 0 && n < 900))
return res.render('article' + (n ? n : ''));
}
next();
});
I create a new module called: jadewalker. It will create router code automatically.
We can simply add a jadewalker comment to your jade Or pug file.
//- jadewalker=/b,/b/:id
doctype html
html
title b.jade
body
p b.jade
p params: #{params.id}
And add this module to our app. That's all.
var app = require('koa')()
var router = require('koa-router')();
router = require('jadewalker')(router, path.join(__dirname, 'views'));
app.use(router.routes());
We can visit our jade file by the URL http://localhost:3000/b/abc. (^∀^)
It's work on my project
routesPath = path.join(__dirname, 'routes');
fs.readdirSync(routesPath).forEach(function(file) {
require(routesPath + '/' + file)(app);
});