Updating the prototype of ServerRequest in an express/node configuration - node.js

I'd like to augment the prototype of the request object in expressjs, but it isn't clear where this request is defined? I think it is http.ServerRequest, but I can't find that definition either.
What's the right way to do the following...
http.ServerRequest.prototype.redirect = function(path) { }

Express itself adds it's utility methods to http.IncomingMessage.prototype, using this pattern in 2.*:
var http = require('http'),
req = http.IncomingMessage.prototype;
req.foo = function(bar) {
// Do cool stuff
};
And this pattern in 3.*:
var http = require('http');
var req = exports = module.exports = {
__proto__: http.IncomingMessage.prototype
};
It's wise to be careful with monkey patching though, as Vadim Baryshev warns in his answer.

Look at Connect framework and his middleware libs. Every middleware extends request and response objects after their creation. Changing prototype of core objects not the best way because this can lead to unpredictable behavior in other modules.

Related

Two way communication between routers within express app

I have an express app that has a router for different sections of my application, each contained within individual files. At the end of each file I export the router object like so.
var express = require("express");
var router = express.Router();
//routing handlers
module.exports = router;
However my problem is that I am trying to implement a feature were a user is allowed to edit a post that could be displayed on the front page, therefore in order to have the most current version of the user's post I need to be able to know when the user edits the post to make the necessary changes.
I have two modules one that handles dispatching the user's posts call this module B and another that handles editing call this module A. I need to be able to have module A include handler function and an array from module B, but I also need module B to be able to be notified when to make changes to the its array that module A requires.
I have tried
module A
var express = require('express');
var EventEmitter = require('events').EventEmitter;
var evt = new EventEmitter();
var router = express.Router();
var modB = require('moduleB');
router.evt = evt;
module.exports = router;
Module B
var express = require('express');
var router = express.Router();
var modA = require('moduleA').evt;
modA.on('myEvent',handler);
var myArray = [....];
router.myArray = myArray;
module.exports = router;
This gives me an undefined for modA and throws an error. I suspect it might be the order the modules are included but anyhow I would like to obtain some feedback since I sense that this might not even be good practice.
I think you are running into a common scenario for someone just starting out with express. A lot of people stick everything into routes/controllers when really the route should be very simple and just extract the data needed to figure out what the request is doing and then pass it to a service for most of the processing.
The solution is to create a Service and put the bulk of your logic and common code there, then you can wire up ModA and ModB to use the Service as needed.
EDIT with an example(not working but should give you a good starting point):
Shared Service
var EventEmitter = require('events').EventEmitter;
var evt = new EventEmitter();
module.exports = {
saveData: function(data) {
// do some saving stuff then trigger the event
evt.emit('myEvent', data);
},
onDataChange: function(handler) {
evt.on('myEvent', handler);
}
};
Module A
var service = require('SharedService.js');
// listen for events
service.onDataChange(function(e, data) {
// do something with the data
});
Module B
var service = require('SharedService.js');
// save some data which will cause Module A's listener to fire
service.saveData(data);
This example above hides the implementation of EventEmitter which may or may not be desirable. Another way you could do it would be to have SharedService extend EventEmitter, then your Modules could listen/emit directly on the service.

How do I overload the functionality of app.listen in expressjs

I've been trying to create (basically) a factory function that configures and builds an expressjs server for a dozen smaller specialized servers I have. For part of this I want to augment the listen function.
I would like to know the best way to go about this. I'm also looking for a reusable design choice here.
Server is created normally:
var httpServer = express();
...
Because of the way express is designed (Not sure if I am correct) I cannot access a {whatever}.prototype.listen. So I have come up with two approaches.
Using an additional variable in the current scope:
var oldListen = httpServer.listen;
httpServer.listen = function(callback){
...
oldListen.call(httpServer, options.port, options.host, function(){
...
if ( typeof callback == 'function' ) callback();
});
};
Which works and is fairly straight forward but then I have a variable hoisting wart. I also have a closure solution, but I think it may be too obtuse to be practical:
httpServer.listen = (function(superListen){
return function(callback){
...
superListen.call(httpServer, options.port, options.host, function(){
...
if ( typeof callback == 'function' ) callback();
});
};
})(httpServer.listen);
Both examples are part of the factory context and I am intentionally reducing the arguments passed to the function.
Any help would be appreciated.
If you insist on "overloading", make sure you implement the original footprint (such is the nature of overloading). Express listen is just an alias to node's internal http listen method:
server.listen(port, [host], [backlog], [callback]);
UPDATE: Express even suggests using node's server API for custom implementations: http://expressjs.com/4x/api.html#app.listen
Otherwise, you should create your own custom listen method which would be defined like:
httpServer.myCustomListen = function (callback) {
httpServer.listen.call(httpServer, options.port, options.host, callback);
}
The second option is your best bet, but in order for it to work, you must extend the express library. Express is open source and hosted on Github. Fork it and modify it as you please. Periodically pull in new updates so you stay up-to-date with the core library. I do this all the time with node modules.
There are two benefits from doing it this way:
You have complete control to customize the code however you see fit while staying up to date with the code written by the original authors.
If you find a bug or build a cool feature, you can submit a pull request to benefit the community at large.
You would first fork the repository, then grab the URL for your fork, clone it, and then add a reference to the original "upstream" repo:
git clone [url_to your_fork]
cd express
git remote add upstream git#github.com:strongloop/express.git
Then you can push changes to your own repo (git push). If you want to get updates from the original repo, you can pull from the upstream repo: git pull upstream master.
If you want to add your custom fork of express as an npm module for a project, you would use the following:
npm install git://github.com/[your_user_name]/express.git --save
As Victor's answer pointed out, express's prototype is in express/lib/application.js. That file is used to build express and is exported via the application namespace in express/lib/express.js. Therefore, the .listen function can be referenced using express.appliction.listen.
One can use this method then: (similar to Victor's method)
var express = require('express');
express.application._listen = express.application.listen;
express.application.listen = function(callback) {
return this._listen(options.port, options.host, callback);
};
One can also use Lo-dash's _.wrap function if you don't want to store the base function in a variable yourself. It would look something like this:
var express = require('express');
var _ = require('lodash');
express.application.listen = _.wrap(express.application.listen, function(listenFn) {
return listenFn(options.port, options.host, callback); // Called with the same this
};
However, using these methods would run into the problems that you mentioned in your question (variable hoisting, creating an extra variable). To solve this, I would usually create my own subclass of express.application and replace the .listen function in that subclass and tell express to use that subclass instead. Due to express's current structure, however, you cannot replace express.application with your own subclass without overriding the express() function itself.
Hence, what I would do is to take over express.application.listen completely since it is only 2 lines. It is rather simple!
var express = require('express');
var http = require('http');
express.application.listen = function(callback) {
return http.createServer(this).listen(options.port, options.host, callback);
};
You can even make an https option!
var express = require('express');
var http = require('http');
var https = require('https');
express.application.listen = function(callback) {
return (options.https ? http.createServer(this) : https.createServer({ ... }, this))
.listen(options.port, options.host, callback);
};
Note: One of the other answers mentions forking express and modifying it. I would have a tough time justifying that for such a small function.
You should be able to easily overload the express listen function. You can access it in the following Object path: express.application.listen
So, you can implement something like this:
var express = require('express');
express.application.baseListen = express.application.listen;
express.application.listen = function(port) {
console.log('Port is: ' + port);
this.baseListen(port);
};
The implementation of the listen function is in the following path under the express module folder: node_modules\express\lib\application.js
Bind and listen for connections on the given host and port. This method is identical to node's http.Server#listen().
var express = require('express');
var app = express();
app.listen(3000);
The app returned by express() is in fact a JavaScript Function, designed to be passed to node's HTTP servers as a callback to handle requests. This allows you to provide both HTTP and HTTPS versions of your app with the same codebase easily, as the app does not inherit from these (it is simply a callback):
var express = require('express');
var https = require('https');
var http = require('http');
var app = express();
http.createServer(app).listen(80);
https.createServer(options, app).listen(443);
The app.listen() method is a convenience method for the following (if you wish to use HTTPS or provide both, use the technique above):
app.listen = function(){
var server = http.createServer(this);
return server.listen.apply(server, arguments);
};
Reference:http://expressjs.com/api.html
Hope This helps.

How to use send in Locomotive Js

How can I use send() in action of controller in locomotive Js. I think LCM only provides render().
Can some one guide me in this regards.
Locomotivejs is just an extension of Express, meaning a Loco app is an Express app. From the docs:
Request and Response
If an application needs access to the raw request and response, each is available as an instance variable within the controller.
PhotosController.show = function() {
var req = this.req; // also aliased as this.request
var res = this.res; // also aliased as this.response
this.render();
}
So from within your controller, simply:
MyController.myAction = function () {
this.res.send(200);
}

Extend View class in Express on Node.js

I'd like to override the View class in the Express framework, used in Node.js. I want to augment the lookup method, but I can't see a way to do this without altering the Express and App modules. I'd favour deriving from the Express framework, but I can't figure out a neat way to do this.
Any ideas?
Thanks
It seems to me you should be able to:
var View = require('express/lib/view');
// Keep reference to original lookup method
var _lookup = View.prototype.lookup;
// Override lookup method
View.prototype.lookup = function (path) {
// Your implementation here
};
Update:
Run this as a demonstration:
var View = require('express/lib/view');
var _lookup = View.prototype.lookup;
var express = require('express');
View.prototype.lookup = function (path) {
console.log('LOOKUP!!! ' + path);
return _lookup.call(this, path);
};
var app = express();
app.get('/', function (req, res) {
res.render('foo.jade');
});
app.listen(3000);
Run
node app & sleep 1 && curl localhost:3000
I hope this will demonstrate the viability of this way of overriding a method.
It depends on which version of Express you are using.
You can easily augment the view lookup code only if your app is using Express prior to version 3
Since Express 3.0 that's not doable anymore.
You can check one of my old related answers for sample code:
Multiple View paths on Node.js + Express

How to Make a Call to Koa.js App Instance for Unit Tests

I don't know how I'd term this maybe 'static call to a koa router'? Does that seem like the right wordage here for what I'm really trying to accomplish if you were to talk about it technically?
Anyway, I'm using koa-router and I'm coding unit tests (not integration tests). So I do not want to invoke .listen() on my koa app because of that reason...it would create an http server which now makes my test an integration tests.
Instead in my test I simply want to make a straight call to the app object instance and call a route and be able to return no results and check that I returned no results in the response.
How can you do that? I can't find an example and I've tried all sorts of pseudo code attemps agains the koa app object.
If you want to test the function that koa-router routes to then just perform a unit test on that function and leave the routing out of it.
To me it sounds like you've got a file such as app.js and it contains all your code. What you can do is create a router.js file to put you route bindings and a services.js file where you can put your application logic.
So for example app.js might look like:
var koa = require("koa");
var app = module.exports = koa();
var router = require('./router.js');
app.use(router.unsecured.middleware());
app.listen(3000);
And router.js might look like:
var router = require("koa-router");
var service = require("./services.js");
var unsecured = module.exports.unsecured = new router();
unsecured.post('/account/signin', service.signinUser);
unsecured.post('/account/register', service.registerUser);
And services.js might look like:
module.exports.signinUser = function*(signinDetails) {
// contains your application signin logic
};
module.exports.registerUser = function*(registerDetails) {
// contains your application register logic
};
So in this manner you can individually test services.js. I don't see any value in individually testing router.js since it is so trivial. As #Dan Pantry shows you can test routing as part of an integration test using supertest.
Edit:
So this is a little experimental test I was playing around with to test that the routing is correct. I'm using mocha as the test runner and the code example I posted in my original code.
// standard library
var assert = require("assert");
// in app objects
var router = require('./router.js');
var service = require('./service.js');
describe("routing tests", function() {
it("test register routing, POST", function*(done) {
// arrange
var unsecured = router.unsecured;
var path = '/account/register';
var httpMethod = 'POST';
var expected = service.register.toString();
var actual;
// act
for (var i = 0; i < unsecured.stack.length; i++)
{
var pathMatch = unsecured.stack[i].path === path;
var methodMatch = unsecured.stack[i].methods.indexOf(httpMethod) >= 0;
if (pathMatch && methodMatch)
{
actual = unsecured.stack[i].middleware.toString();
break;
}
}
// assert
try {
assert.equal(expected, actual);
done();
} catch(err) {
done(err);
}
});
});
There is probably a neater way of doing this (and a more modular way for testing multiple paths) but as I said this is just a basic example to verify the routing is calling the correct service. What I'm doing is delving into the koa-router object to verify what path is bound to what service code depending on the HTTP method (e.g. POST, GET, etc).
If you have your routing and your services in modules this test completely avoids dealing with the main koa app. Although technically this test spans multiple units (the routing and the service code) so it would technically be an integration test but it does mean you don't go near app.listen() which is what you didn't want to call in your tests.

Resources