I have a node.js (with express) module that connects to twitter and streams data based on search terms the user inputs in the front end (see: twitter.tweetStream(api, params, values, track, bridgeArray, usernameArray, scoreData);). The module executes when the user submits a form and is directed to /test, but it continues to run even after they leave /test. It also runs in parallel with any new instance of it that starts.
Is there a way to tell the module to stop running if the user leaves the /test route? Th
// Renders form on default Route
app.get('/', function(req, res){
res.render('form');
});
// On form submission take data and passes it into twitter stream call as "track" object then renders the 'tweets' feed
app.post('/test',function(req,res){
var track = req.body;
twitter.tweetStream(api, params, values, track, bridgeArray, usernameArray, scoreData);
res.render('tweets');
});
// Renders Tweets stored in "values object" onto a page to be called from tweets template
app.get('/tweets', function(req, res){
res.render('home', {
profileImg: values.profileImg,
userName: values.userName,
screenName: values.screenName,
text: values.text,
timeStamp: values.timeStamp,
tweetScore: values.tweetScore,
// totals: values.totals
});
});
Complete code added for clarity:
var express = require('express');
var app = express();
//var http = require('http').Server(app); // Not using
var exphbs = require('express-handlebars');
var bodyParser = require('body-parser');
var twitter = require('./twitter.js');
var hue = require("./hue_control.js");
// Variable that control Twitter Calls
var api = 'statuses/filter';
var params = {slug:'REDACTED', owner_screen_name: 'REDACTED', skip_status: true};
var values = {};
app.engine('handlebars', exphbs({defaultLayout: 'main'}));
app.set('view engine', 'handlebars');
app.use(bodyParser());
app.use(express.static('public'));
// Checks for Hue bridge on local network gets IP and sets usename
var bridgeArray = [];
var usernameArray = [];
var scoreData = [];
var track = {};
hue.activate(bridgeArray, usernameArray);
// Renders form on default Route
app.get('/', function(req, res){
res.render('form');
});
// On form submission take data and passes it into twitter stream call as "track" object then renders the 'tweets' feed
app.post('/tweets',function(req,res){
track = req.body;
res.render('tweets');
twitter.tweetStream(api, params, values, track, bridgeArray, usernameArray, scoreData);
});
// Renders Tweets stored in "values object" onto a page to be called from tweets template
app.get('/tweetstatic', function(req, res){
res.render('home', {
profileImg: values.profileImg,
userName: values.userName,
screenName: values.screenName,
text: values.text,
timeStamp: values.timeStamp,
tweetScore: values.tweetScore,
});
});
app.get('/totals', function(req, res){
res.render('totals', {
tweetTotal: values.tweetTotal,
score: values.score,
color: values.color
});
});
// App Settings
var server = app.listen(3000, function () {
var host = server.address().address;
var port = server.address().port;
console.log('Example app listening at http://%s:%s', host, port);
});
Related
A little info
I got my client (localhost:8080) and my server.js (localhost:3000). I made some routes for my server.js (see the file below).
Question
Now, if I try to access the route on my server e.g. localhost:3000/users/4, I get the expected result - 4 fake users are created. However if I try to append the postfix users/4 to the client: (localhost:8080/users/4), I get an error! Cannot GET /users/4. Likewise I get an cannot GET *SOMETHING* error if I try one of the other routes.
Have I misinterpreted something? Shouldn't I be able to append the route to the client url and then get the res (respons) back again? (as long as the server is running of course, or is that not how it works?)
routes.js (I got all my routes in this one file)
var faker = require("faker");
var appRouter = function (app) {
app.get("/", function (req, res) {
res.status(200).send({ message: 'Welcome to our restful API' });
});
app.get("/user", function (req, res) {
var data = ({
firstName: faker.name.firstName(),
lastName: faker.name.lastName(),
username: faker.internet.userName(),
email: faker.internet.email()
});
res.status(200).send(data);
});
app.get("/users/:num", function (req, res) {
var users = [];
var num = req.params.num;
if (isFinite(num) && num > 0 ) {
for (i = 0; i <= num-1; i++) {
users.push({
firstName: faker.name.firstName(),
lastName: faker.name.lastName(),
username: faker.internet.userName(),
email: faker.internet.email()
});
}
res.status(200).send(users);
} else {
res.status(400).send({ message: 'invalid number supplied' });
}
});
};
module.exports = appRouter;
Server.js
var express = require("express");
var bodyParser = require("body-parser");
var routes = require("./routes/routes.js");
var app = express();
const server_port = process.env.PORT || 3000;
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
routes(app);
var server = app.listen(server_port, function () {
console.log("app running on port.", server.address().port);
});
You must be mixing up something there. When you open http://localhost:8080/users/4, then what you are doing is a SERVER request to localhost:8080 with the route users/4. The client in your scenario is a browser which is making a request to the server.
Now if your server is actually running on localhost:3000, then you must be running another server on localhost:8080. So if you want to be able to make a request to http://localhost:8080/users/4, then you need to configure your server on localhost:8080 to accept that route, not the one on localhost:3000.
Trying to set up a basic Express server with a basic pug template.
Can you please tell me what I'm doing wrong here?
'use strict';
//Require Express
var express = require('express');
var app = express();
//Require Pug
var pug = require('pug');
//Require Twitter
var Twitter = require('twitter');
//Set view engine to serve middleware
app.set('view engine', 'pug');
//Set where to look for templates
app.set('views', __dirname + '/templates');
//Set up style sheets
app.use('/static', express.static(__dirname + '/public'));
//Access keys to access twitter account
var config = {
"consumerKey": "",
"consumerSecret": "",
"accessToken": "",
"accessTokenSecret": ""
};
//instantiate twitter client
var client = new Twitter(config);
//Log whether
var error = function (err, response, body) {
console.log('ERROR [%s]', err);
};
var success = function (data) {
console.log('Data [%s]', data);
};
//Set up server on Port 3000
app.listen(3000, function() {
console.log("The frontend server is running on port 3000!");
});
//Render when appropriate
//Tell app to render template
app.get('/'), function(req, res){
res.render('index', {title: 'Hey', message: 'Hello there!'});
}
I'm getting back The frontend server is running on port 3000! in the console.
What am I missing?
I'd really appreciate any help please
You're calling app.get() wrong. You're doing
app.get('/'), function(req, res){
...
Which is two statements separated by the comma operator. The correct syntax is to pass the function as the second argument:
app.get('/', function(req, res){
...
});
I am a newbie to Node.JS and began looking for best practice articles, etc. to make sure my node.js code was unit test friendly and followed the node.js best practices. While researching I came across the following code examples:
app.js:
module.exports = function (flights) {
var express = require('express');
var routes = require('./routes')(flights);
var path = require('path');
var app = express();
// all environments
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(function (req, res, next) {
res.set('X-Powered-By', 'Flight Tracker');
next();
});
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
}
app.get('/flight/:number', routes.flight);
app.put('/flight/:number/arrived', routes.arrived);
app.get('/list', routes.list);
return app;
}
server.js:
var http = require('http'),
flights = require('./data'),
app = require('./app')(flights);
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
module(index.js):
var Flight = function () {
this.data = {
number: null,
origin: null,
destination: null,
departs: null,
arrives: null,
actualDepart: null,
actualArrive: null
};
this.fill = function (info) {
for(var prop in this.data) {
if(this.data[prop] !== 'undefined') {
this.data[prop] = info[prop];
}
}
};
this.triggerDepart = function () {
this.data.actualDepart = Date.now();
};
this.triggerArrive = function () {
this.data.actualArrive = Date.now();
};
this.getInformation = function () {
return this.data;
};
};
module.exports = function (info) {
var instance = new Flight();
instance.fill(info);
return instance;
};
routes(index.js):
module.exports = function (flights) {
var flight = require('../flight');
for(var number in flights) {
flights[number] = flight(flights[number]);
}
var functions = {};
functions.flight = function(req, res){
var number = req.param('number');
if (typeof flights[number] === 'undefined') {
res.status(404).json({status: 'error'});
} else {
res.json(flights[number].getInformation());
}
};
functions.arrived = function (req, res) {
var number = req.param('number');
if (typeof flights[number] === 'undefined') {
res.status(404).json({status: 'error'});
} else {
flights[number].triggerArrive();
res.json({status: 'done'});
}
};
functions.list = function (req, res) {
res.render('list', {
title: 'All Flights',
flights: flights});
};
return functions;
};
While I like how this is organized alot, I do not see an efficient way to handle multiple modules in this scenario. Let's say I have additional modules for User, Initerary, etc. This seems like it could become chaotic quickly as I began to add routes to the app.js file, not to mention how many potential parameters would need to be passed into app.js. What if I have a large rest layer that required 20 or more modules? I am looking for any doc or links or examples demonstrating a clean way I should do this in node.js.
Granularize and encapsulate using sub routers with express.Router(). Each router then becomes it's own module that you pull in making it so that you don't have to add every single route explicitly in app.js.
User.js
"use strict";
// Create a router
var express = require("express"),
router = express.Router();
router.get("/", function (req, res, next) {
// All your User logic
res.send([
{
name: "Bob"
},
{
name: "John"
}
]);
});
router.get("/:number", function (req, res, next) {
res.send({
name: "Bob"
});
});
router.post("/", function (req, res, next) {
res.send({
name: "New Guy"
});
});
module.exports = router;
App.js
var app = express();
app.use("/user", require("./User"));
Now you can GET /user, GET /user/SOME_ID, and POST to /user. It's also simple if you want to move the sub route around to somewhere else because the methods defined for the user route are relative.
I too have a large enterprise app called campaign_service, consisting of many many modules.
This is how, I organize the routes in a file campaign_router.js.
var express = require('express');
var router = express.Router();
var cm = require('./campaign_manager.js');
var qsc = require('./converters/qs_converter.js');
var jsc = require('./converters/json_converter.js');
var xmlc = require('./converters/xml_converter.js');
var fc = require('./converters/f_converter');
var fc2 = require('./converters/fjt2_converter');
var cv = require('./campaign_validator.js');
var templates = require('./template_list.js');
var AuthDecoder = require('authdecoder');
var adc = AuthDecoder.middleware;
router.get ('/campaigns/qs', qsc, adc, cv, cm.createCampaign); // Creates a new campaign using query string params
router.post ('/campaigns/b/xml', xmlc, adc, cv, cm.createCampaign); // Creates a new campaign using xml payload
router.post ('/campaigns/file', fc, adc, cv, cm.createCampaign); // Creates a new campaign using uploaded file
router.post ('/campaigns/file/type2', fc2, adc, cv, cm.createCampaign); // Creates a new campaign using uploaded file
router.post ('/campaigns/js', jsc, adc,cv, cm.createCampaign); // Creates a new bulk campaign using json payload
router.get ('/campaigns/', adc, cm.getCampaigns); // Returns a list of bulk campaigns accessible for the invoking user.
router.get ('/campaigns/date', adc, cm.getCampaignsByRange); // Returns a list of bulk campaigns accessible for the invoking user.
router.get ('/campaigns/b/:id', adc, cm.getCampaign); // returns the details of a specific campoaign
router.put ('/campaigns/b/id', cm.updateCampaign); // Updates a specified campaign
router.delete ('/campaigns/b/:id', cm.deleteCampaign); // deletes a campaign
router.post ('/pause', adc, cm.pauseJob); // Pauses an ongoing campaign
router.post ('/resume', adc, cm.resumeJob); // Resumes a paused campaign
router.post ('/cancel', adc,cm.cancelJob); // Resumes a paused campaign
//router.post ('/reschedule', adc,cm.rescheduleCampaign); // Resumes a paused campaign
//router.get ('/', cm.pingCampaignServer);
router.get ('/templates', adc, templates.listTemplates); // gives the campaign server templates
Salient points:
All campaign functions, go into another js file (which is a middleware), called campaign_manager.js
All payload converters go into a sub-folder called "converters", and this folder has many files called 'qs_converter.js', 'json_converter.js', ..., blah blah.
My app performs authentication, before any campaign request is accepted, so there is a middleware loaded into the route.
If I have other mount points apart from "/campaigns", I would create another router module and define additional .js files.
_ I would use index.js (or app.js), to load these routers.
Essentially, it is very easy for me to scale my code into multiple modules and import them via the router file.
EDIT
Added usage scenario
Index.js
var routes = require('./campaign_router.js');
...
app.use('/campaignservice', routes);
I'm working through a basic node tutorial and am having difficulty getting my routes.js file to work.
It was working earlier today. The server Node is reading the file. For some reason, though it is not utilizing it. My code looks exactly like the tutorial -- though the teacher is on a PC and I am on a Mac (though I can't see why that would matter).
Before this issue started to occur, I hooked up my database (file below) -- but again, I can't see why that would screw with my routes. When I put this code in server.js, I can get the proper routing.
Help me stackoverflow, you're my only hope! All I see is "Cannot GET /"
My routes.js file
var User = require('../models/user');
module.exports = function(app){
app.get('/', function(req, res){
res.send("Hello World");
});
// app.get('/:username/:password', function(req, res){
// var newUser = new User();
// newUser.local.username = req.params.username;
// newUser.local.password = req.params.password;
// console.log(newUser.local.username + " " + newUser.local.password);
// newUser.save(function(err){
// if(err)
// throw err;
// });
// res.send('Success!')
// });
};
server.js
var express = require('express');
var app = express();
var port = process.env.PORT || 8080;
var cookieParser = require('cookie-parser');
var session = require('express-session');
var morgan = require('morgan');
var mongoose = require('mongoose');
//Config Database
var configDB = require('./config/database.js');
mongoose.connect(configDB.url);
//MIDDLEWARE is run during every interaction;
app.use(morgan('dev'));
//sets req.cookies
app.use(cookieParser());
app.use(session({
//secret for user session
secret: "ist0",
//if the server goes down, the user can remain logged on -- still save to database
saveUninitialized: true,
//even if nothing has changed, resave
resave: true
}));
//ROUTES
require('./app/routes/routes');
// app.use('/', function(req, res){
// //send is express function
// res.send("Our first express program");
// console.log(req.cookies);
// console.log("============");
// console.log(req.session);
// });
app.listen(port);
console.log('The magic happens on ' + port)
My database.js file:
module.exports = {
'url': 'mongodb://localhost/meanboil'
}
You are exporting a function (one that expects app as an argument):
module.exports = function(app) { ... }
But you're just importing that function and don't actually call it:
require('./app/routes/routes');
Instead, you need to call it and pass app as argument:
require('./app/routes/routes')(app);
I am running into an issue where I am trying to run a POST request via Postman and I get a loading request for a long time and then a Could not get any response message. There are no errors that are appearing in terminal. Is it the way I am saving the POST? Specifically looking at my /blog route.
server.js
//Load express
var express = require('express');
var app = express();
var router = express.Router(); // get an instance of the router
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
// configure app to use bodyParser()
// get data from a POST method
app.use(bodyParser.urlencoded({ extended: true}));
app.use(bodyParser.json());
var port = process.env.PORT || 8080; // set the port
var blogDB = require('./config/blogDB.js');
var Blogpost = require('./app/models/blogModel');
app.set('view engine', 'ejs'); // set ejs as the view engine
app.use(express.static(__dirname + '/public')); // set the public directory
var routes = require('./app/routes');
// use routes.js
app.use(routes);
app.listen(port);
console.log('magic is happening on port' + port);
blogModel.js:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var BlogPostSchema = new Schema({
title : String,
body : String,
date_created : Date
});
module.exports = mongoose.model('Blogpost', BlogPostSchema);
routes.js:
var express = require('express');
var router = express.Router();
var blogDB = require('../config/blogDB.js');
var Blogpost = require('./models/blogModel.js');
//index
router.route('/')
.get(function(req, res) {
var drinks = [
{ name: 'Bloody Mary', drunkness: 3 },
{ name: 'Martini', drunkness: 5 },
{ name: 'Scotch', drunkness: 10}
];
var tagline = "Lets do this.";
res.render('pages/index', {
drinks: drinks,
tagline: tagline
});
});
//blog
router.route('/blog')
.get(function(req, res) {
res.send('This is the blog page');
})
.post(function(req, res) {
var blogpost = new Blogpost(); // create a new instance of a Blogpost model
blogpost.title = req.body.name; // set the blog title
blogpost.body = req.body.body; // set the blog content
blogpost.date_created = Date.now();
blogpost.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'Blog created.' });
});
});
//about
router.get('/about', function(req, res) {
res.render('pages/about');
});
module.exports = router;
The issue was that I did not setup a user for my Mongo database. Basically it couldn't gain access to the user/pw to the database that I was using. Once I created a user matching the user/pw I included in my url, then I was able to get a successful post.