(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",
- 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.
- 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.
- 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.
- 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:
- 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)
- 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
- 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?)
- Are there less intrusive ways to authenticate the user?
- Will this compromise security? Does the benefit outweigh the risks?