Show Attached Middleware Functions in Console - javascript

I have to admit I'm rather surprised I didn't find any info on this through Google. Perhaps I wasn't looking hard enough.
Basically, I want to find information on the various middleware functions my Express.js app is using, preferably via a bash-like console. Logging the express() function itself does not log the sub-functions, such as trace() or mkcol(). These are shown as attributes of the express function object, as, for example, trace: [Function], or emit: [Function: emit]; their bodies and current contents are not shown. I am able to log the function bodies through e.g. express().once.toString(), as said in several answers, including this one.
This only shows the function body as it was before I called it (when I added all the middleware), not what said body is now. It does not show the middleware I had Express use().
How do I show these middleware functions in the console as they are now? For example, if I define:
express = require('express');
server = express();
flash = require('connect-flash');
bodyParser = require('body-parser');
server.use(flash());
server.use(bodyParser.json());
server.use(bodyParser.urlencoded());
how do I see that Express now uses the flash middleware, and, separately, how do I see that Express now uses the middleware that consists of whatever function is exported by the connect-flash module? If one or both of these would not work for "whatever the bodyParser.json()/bodyParser.urlencoded() function is", is there another way to log that? As I said, it is not enough to simply console.log Express's use() function, or, if it is, I was not able to find the trick. There are a million ways in which a middleware function can be defined & use()d, so I don't expect any answer to work for all of them, but "as many as possible" would be nice.
Any answer should work for nested middleware, as well, as, for example, the Router and vhost middlewares can and usually do use() other middleware, and are in fact Express apps themselves.

Closest thing I know of is to run your app with the DEBUG environment variable set to express:router like this: DEBUG=express:router node server.js and watch the output as you use the app. Many of the functions you use as middleware are going to be anonymous since it is common to define them like this: app.get('/foo', function(req, res) {...}); thus express doesn't even have access to something as basic as a human-readable name for that route handler function.

Related

setting up a lot of routes in node.js

I've created a webpage to use it locally as a way to save information about random topics and college stuff. I have a ton of routes like the ones shown below:
//app.js - using node and express
app.get('/page1', function(req, res){
res.render('page1');
});
app.get('/page2', function(req, res){
res.sendFile('views/page2.html', { root: __dirname });
});
Each one of these routes has a .ejs file or a .html file, and they are all quite small.
I don't think I've made any major mistakes, but I gotta a feeling I'm not using "best practices", or at least could be doing some differently.
Is there anything wrong with using a lot a routes like this? Should change something to optimize the rendering of my pages?
As I said before, I'm using .ejs on most of the pages, and most of them have the same header.ejs and footer.ejs. Every time I change pages that have the same header/footer, do they get loaded again, or since they are using the same header/footer files the server only requests the content in between?
what's the difference between using res.render and res.send?
Should I be using a different syntax: const express = require('express'); & const app = express(); instead of var express = require('express'); & var app = express();
``` or this
app.get('/page1', (req, res) => {
res.render('page1');
});
```
Instead of the first block of code above.
Thanks! :D
Is there anything wrong with using a lot a routes like this? Should change something to optimize the rendering of my pages?
Nothing technically wrong with it. Many plain res.sendFile() routes can probably be replaced with a single express.static() middleware statement to simplify your code.
Lots of res.render() routes that don't pass any customized data to EJS can also probably be replaced by a single middleware that handles either a whole directory of template files (and their corresponding routes) or a list of files. That would be a lot more DRY than spelling out each route separately.
As I said before, I'm using .ejs on most of the pages, and most of them have the same header.ejs and footer.ejs. Every time I change pages that have the same header/footer, do they get loaded again, or since they are using the same header/footer files the server only requests the content in between?
EJS caches templates in memory (unless you disable caching) so the header and footer templates won't get loaded over and over again from disk.
what's the difference between using res.render and res.send?
These are fully covered in the documentation. In a nutshell, res.render() supports your template engine and local data to feed to the template engine to allow it to add data to the template. res.send() just sends the raw content you give it.
Should I be using a different syntax: const express = require('express'); & const app = express(); instead of var express = require('express'); & var app = express();
It is considered a good practice to use const whenever the variable you are declaring should get its initial value and not be assigned to again. In addition to some coding safety, this also can sometimes allow the interpreter to do more optimizations when using the variable (since its value can't be changed).

How to bypass an express middleware?

I'm working with an express application. There are some express routes, as
server.get('*' , ... )
etc. which perform some common operations: authentication, validation... etc.
they also decorates the response with meaningful information: i.e. in every request to the server it gives not only the expected json/html, but also information regarding the user, some app metadata that the front-end consumes etc. etc.
Let's say all this extra metadata cames in a field called extradata in every request to the server.
Now, there is a bug that is causing a problem: instead of returning its expected response (a json with a bunch of system logs), is sending only this extradata field.
I'm pretty confident the problem is in one of the middlewares, because that code that sends the response in this case is really simple, it's just a res.send() of a json. So I believe this part of the app is requiring some module that sets a middleware which causes the error. There are a lot of global vars and implicit parameters in the app so is really difficult to debug it manualluy.
I attempted to bypass such middlewares programmatically, like:
delete server._router.stack[2];
but is causing an TypeError: Cannot read property 'route' of undefined and thus preventing my app to build: sure this is not the way to go.
so, is there a way to programmatically ignore or bypass express routes that are yet set?
Even better, is there a way to programmatically tap into express middlewares and log every request and response?
(afaik, there are libreries like morgan that logs every request, but I don't think they apply to this case since I need to discriminate between middlewares).
What I generally do is simply use the next method. You can access it by simply passing it to the callback function. Something like:
app.use(function(req, res, next) {
if(...) {
next();
} else {
...
}
}
What this is going to do is go to the next middleware.
So if I understand correctly, you can check what you exactly need in the if-statement and do things accordingly.
What I would suggest is you read the Express API documentation, especially the section about middleware, which you can find here. Moreover, try to isolate the suspects and solve the issue by removing the problem, rather than deleting handlers and trying to solve the problem the easy way.

Require statements needed when something is already attached to a request in Node/Express?

Let's say I have an app in Node with the main elements of the application in a file at the root directory called app.js. Now let's say I have a route in ./routes/index.js.
If some of my middleware in app.js attaches handlers to the request, do I need to require the library that added that handler when handling the route in index.js?
I.e. in app.js:
var flash = require('connect-flash');
...
app.use(flash());
And in index.js:
var flash = require('connect-flash'); // ???
router.get('/', function(req, res, next) {
res.render('index', { message: req.flash('loginMessage') });
});
It appears to work without the require statement in index.js, but I want to make sure I'm understanding this conceptually. Once something is attached to the request, it stays with the request wherever it goes, right?
When you create an express application you create a "tree" so to speak, meaning that wherever you apply middleware any descending route will go through that function. So if we put the middleware at the top of our application all requests will go through that function. You only need to require the middleware wherever you are applying it to the application.
No, you don't. You only need require to get access to exported items from the module. If you don't need to access them (for instance, because something is already accessible as a property on req), you don't need the require.

Pass req res objects into socket.io?

I am a little confused how I can interact with the socket when I need to pass in data from my routes file. I have the standard setup using node.js, express, mongodb etc.
I'll run my socket.io logic inside server.js, and I include the routes.js inside that file.
var routes = require('./app/routes');
In this case I need to run some io.sockets inside my routes.js file.
My question is what is a good way to do this? I could run that specific route inside server.js but that gets messy. If I were to use sockets in my routes.js do I need to re-require
var io = require('socket.io').listen(server);
That means I need to create a new http server object, and I don't like that since I am requiring this file in server.js, this seems like a counter-intuitive move to me.
So how do I make a request to the server and pass for example a user name?
Example:
app.get('/profile', isLoggedIn, function(req, res) {
res.render('profile', { user : req.user });
io.sockets.on('connection', function (socket) {
console.log(socket);
console.log(req.user); // Here I have access to the user and can pass that around in my sockets
});
});
I am also using route middleware, so I'd like to keep that in my routes.js, IDK I am just confused what I should do, hopefully someone understands my angle here?
Edit:
What about passing something into the routes?
routes.initialize(app, passport);
You can get the req and res objects directly in the socket by invoking socket.request (a Getter function which is available via __proto__). See docs.
I was then able to find req.user in socket.request.client.user.

Node.js Programming Pattern for getting Execution Context

I am writing a web app in node.js. Now every processing on the server is always in the context of a session which is either retrieved or created at the very first stage when the request hits the server. After this the execution flows through multiple modules and callbacks within them. What I am struggling with is in creating a programming pattern so that at any point in the code the session object is available without the programmer requiring it to pass it as an argument in each function call.
If all of the code was in one single file I could have had a closure but if there are function calls to other modules in other files how do I program so that the session object is available in the called function without passing it as an argument. I feel there should be some link between the two functions in the two files but how to arrange that is where I am getting stuck.
In general I would like to say there is always a execution context which could be a session or a network request whose processing is spread across multiple files and the execution context object is to be made available at all points. There can actually be multiple use cases like having one Log object for each network request or one Log object per session. And the plumbing required to make this work should be fitted sideways without the application programmer bothering about it. He just knows that that execution context is available at all places.
I think it should fairly common problem faced by everyone so please give me some ideas.
Following is the problem
MainServer.js
app = require('express').createServer();
app_module1 = require('AppModule1');
var session = get_session();
app.get('/my/page', app_module1.func1);
AppModule1.js
app_module2 = require('AppModule2');
exports.func1 = function(req,res){
// I want to know which the session context this code is running for
app_module2.func2(req,res);
}
AppModule2.js
exports.func2 = function(req,res){
// I want to know where the session context in which this code is running
}
You can achieve this using Domains -- a new node 0.8 feature. The idea is to run each request in it's own domain, providing a space for per-request data. You can get to the current request's domain without having to pass it all over via process.domain.
Here is an example of getting it setup to work with express:
How to use Node.js 0.8.x domains with express?
Note that domains in general are somewhat experimental and process.domain in particular is undocumented (though apparently not going away in 0.8 and there is some discussion on making it permanent). I suggest following their recommendation and adding an app-specific property to process.domain.data.
https://github.com/joyent/node/issues/3733
https://groups.google.com/d/msg/nodejs-dev/gBpJeQr0fWM/-y7fzzRMYBcJ
Since you are using Express, you can get session attached to every request. The implementation is following:
var express = require('express');
var app = express.createServer();
app.configure('development', function() {
app.use(express.cookieParser());
app.use(express.session({secret: 'foo', key: 'express.sid'}));
});
Then upon every request, you can access session like this:
app.get('/your/path', function(req, res) {
console.log(req.session);
});
I assume you want to have some kind of unique identifier for every session so that you can trace its context. SessionID can be found in the 'express.sid' cookie that we are setting for each session.
app.get('/your/path', function(req, res) {
console.log(req.cookies['express.sid']);
});
So basically, you don't have to do anything else but add cookie parser and enable sessions for your express app and then when you pass the request to these functions, you can recognize the session ID. You MUST pass the request though, you cannot build a system where it just knows the session because you are writing a server and session is available upon request.
What express does, and the common practice for building an http stack on node.js is use http middleware to "enhance" or add functionality to the request and response objects coming into the callback from your server. It's very simple and straight-forward.
module.exports = function(req, res, next) {
req.session = require('my-session-lib');
next();
};
req and res are automatically passed into your handler, and from their you'll need to keep them available to the appropriate layers of your architecture. In your example, it's available like so:
AppModule2.js
exports.func2 = function(req,res){
// I want to know where the session context in which this code is running
req.session; // <== right here
}
Nodetime is a profiling tool that does internally what you're trying to do. It provides a function that instruments your code in such a way that calls resulting from a particular HTTP request are associated with that request. For example, it understands how much time a request spent in Mongo, Redis or MySQL. Take a look at the video on the site to see what I mean http://vimeo.com/39524802.
The library adds probes to various modules. However, I have not been able to see how exactly the context (url) is passed between them. Hopefully someone can figure this out and post an explanation.
EDIT: Sorry, I think this was a red-herring. Nodetime is using the stack trace to associate calls with one another. The results it presents are aggregates across potentially many calls to the same URL, so this is not a solution for OP's problem.

Categories