2

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.
  • Is your question directed toward express.js (and therefore javascript), or your own framework? If it is your own framework, it may fall short of the design of the original library, and therefore tasks that are doable in the original library may be impossible in your own framework. Since we know nothing about your own framework, we can't give any useful advice. – rwong May 28 '15 at 11:03
  • I was just looking for some language-agnostic advice on dependency management for a middleware-like architecture. I can't share everything I've built for this specific project, so I used Express as an example because it's very similar in design. If answers are specific to Express, that's fine -- I'm just looking for some ideas, not a definitive answer (otherwise I'd ask on SO). – mpen May 28 '15 at 17:02
  • What makes it difficult for all of the devs to know and follow the exact order that the app.uses must happen in? – rwong May 28 '15 at 18:37
  • @rwong Hidden dependencies. From the example in my question, it's not immediately obvious that a menu depends on authentication. Maybe that's okay though; what I've done for now is to throw an exception if the dependencies aren't met, so it will be immediately obvious rather than having UI elements disappear. – mpen May 28 '15 at 21:39
2

(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?
0

Among other things (a template engine, an OO language, an application container etc. ) php functions quite well as middleware.

A simple php class/script that maps your functionality to php classes or scripts or resources would work fine. ( After all this is the paradigm used by the most successful and admired Python frameworks!)

Java, J2EE etc. need template engines, complex middleware , application containers etc. because it is not supported natively. PHP on the other hand supports everything you need to present web pages in a controlled manner.

Any middleware you use will be more complex and harder to maintain than simply coding a plain old PHP script which does the same thing.

  • The word "middleware" is merely a choice-of-word by express.js to mean "handler". It has no relationship to middleware architecture. – rwong May 28 '15 at 11:04
  • We've presently got a ~1600 line linear script that handles requests, includes other scripts sporadically, and is littered with globals. This "plain old PHP script" is by no means simple which is why I'm trying to clean it up by organizing it into "middleware" functions a la Express. – mpen May 28 '15 at 16:55
  • I should also point out that that this is not a new project. Sure, you can render a page with vanilla PHP and no dependencies, but that's not what I have to work with. We've already got a rendering engine (two, actually), a database layer, auth layer, oodles of XML, and all kinds of dependencies that need to remain in tact. Whether or not this is all needed (it isn't), I'm looking for a way to structure it in a sane manner that isn't so prone to breaking. – mpen May 28 '15 at 17:14
  • @Mark -- the perils of over engineering, it looks like the original designer was suffering "J2EE Envy"! PHP is designed from the ground up to handle web sites. All you need is to impose a bit of structure on your scripts/classes. The JAVA world needs all the extras because it is only a programming language designed to run a domestic satellite receiver, plus, no Java programmer will code one simple class when you it could be implemented in 20 classes with 10 obscure XML config files. Years of experience has taught - Simpler is Better. – James Anderson May 29 '15 at 5:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.