Middleware dependencies

design-patternsmiddlewarenode.js

I'm trying to convert a legacy PHP app to use the middleware paradigm, similar to connect/express.js.

I've started porting the code into separate middlewares so that every feature is neatly self contained and can be easily add/removed/re-arranged as needed going forward.

However, I'm finding that many of these middlewares depend on other middlewares. For example, I have a DebugBar middleware which adds a bar at the bottom of every page if you're either on dev (which is determined via an environment middleware), or if you're a super user (determined by auth middleware).

Our site also has a link menu which changes based on your user permissions. Your user permissions can't be determined until you're authenticated, and I don't want to authentic at all unless you're on a page that requires it (basically anything except the login/logout page and 1 or 2 other pages) — so there's also conditional middleware based on what page you're viewing.

Up until now I've been more or less copying how express does things, but as far as I can tell, they don't really have any examples of middleware depending on each other, and if they do, you would just monkey-patch the response object and subsequent middlewares would either depend on it or crash, which doesn't seem like a great way of doing things.

Questions:

  1. What's the best way to share data between middlewares? Monkey-patching a response object seems very fragile.
  2. How can I make it clear which middleware depends on what? There are a number of devs here, they can't all know the exact order that the app.uses must happen in.

Best Answer

(Disclaimer: I don't know any of the technologies mentioned in the question; I'm just inferring from the descriptions on the question itself and the linked articles.)


Dependency and the order of execution. Based on the linked documentation,

  • It seems you can control the order of execution of middlewares simply by calling app.use(...) in a particular order.
  • It can be documented clearly inside your project.
  • There is a way to make it work correctly; whether it can be done in a maintainable (non-fragile) way is a matter of
    • Your design, and
    • Your (or programmer's) discipline in following the guidelines

There are some relevant design patterns and techniques that will help you maintain the correct dependency and order of execution.

  • Command pattern
  • Chain of responsibility pattern
  • Decorator pattern
  • Topological sorting, which can be used to calculate the order of execution based on their dependencies. You will likely do this with pen and paper, since you have control over what middlewares will be executed and there are no new middlewares to be added.

Regarding "monkey-patch(ing) the response object",

  1. A middleware that is executed early can insert some placeholders in the response, which will be replaced by real content by another middleware that is executed later.
  2. There can also be a final middleware that strips out any placeholders that were unprocessed (i.e. as a catch-all in case of a programming mistake), and replace that with error message.
  3. To prevent injection attacks (the user somehow manipulating user-submitted content to look indistinguishable from a placeholder), you can sanitize (remove) such placeholders from the response in the beginning, before any genuine placeholders are added.
  4. Anything else that do not belong to the response might be better written to the request object, or the session middleware instead.

To resolve circular dependencies between middleware, one can implement a middleware that would be executed at the very beginning. This middleware can do a "requirements gathering" on the request, to decide what other middleware will be potentially activated, and then set various flags on the request object.

This "requirements gathering" middleware should avoid doing the actual work that causes the circular dependency.


The authentication issue is not unique to any paradigm. It is a general user interface design issue that affects every application where the user doesn't need to authenticate up-front.

The core issue is this. After the user navigated to a page, and that page contains elements that will potentially require authentication, the questions are:

  1. How to let the user easily find out whether the app is in an authenticated state or not (i.e. let the user see whether it's "logged in" or not)
  2. How to convey to the user that there are such elements (that would require authentication)?
    • Completely hiding it?
    • Show a pane that blurs over it (but still hints at the existence of what's below), and put a login button on top? (There would be no user-specific information in the blurred content.)
    • Show the element with placeholder strings
  3. Should the user be forced to authenticate? If so,
    • Should this happen when the page is being loaded?
    • Or only when the user clicks on the element (or a "Login" button?)
  4. Are there less intrusive ways to authenticate the user?
    • Will this compromise security? Does the benefit outweigh the risks?
Related Topic