Open marko-hologram opened 2 months ago
I'm quite sure after a redirect, no additional middleware should run.
This is what I was expecting as well.
For example, you might want to run a middleware very early in order to redirect users who are heading to old routes (routes which no longer exist), to a different route. Once that middleware runs and attempts to redirect, you no longer want to run any other middleware for that request.
First of all I gotta say I absolutely love this library. It has helped me clean up middleware in projects a lot. I'm definitely going to be using it all the time.
Describe the bug
Returning a
NextResponse.redirect()
orNextResponse.rewrite()
from middleware doesn't stop subsequent middleware from executing when in a middleware chainTo Reproduce
Clone this reproduction repo: https://github.com/marko-hologram/nemo-middleware-chain-bug
npm install
npm run dev
Steps to reproduce the behavior:
Expected behavior
If
NextResponse.redirect()
orNextResponse.rewrite()
is returned from a middleware in a middleware chain, all other middleware after it should not be executed.There might be a case that I'm missing where it makes sense to have additional middleware run after a rewrite, but I'm quite sure after a redirect, no additional middleware should run. I did find this older issue (https://github.com/z4nr34l/nemo/issues/17) where apparently the redirect issue was fixed, but the bug might have been re-introduced after that.
Ideally, it would be great if maybe we could return some special type of response that would break the middleware chain because middleware chain doesn't need to always just break on redirect or rewrite, but maybe based on some custom condition. For example, in the app I'm working on, there is some special case on a route where only admins get some special treatment that needs to happen in middleware. So there I just need to check if user is admin and if it is, I want to execute additional middleware.
I know I could do each middleware on its own and do all checks there, but maybe I want to have smaller middleware that can be composed like this:
Unfortunately, with the current implementation there is no baked in solution to skip
anotherAdminSpecialMiddleware
oradditionalAdminOnlyMiddleware
ifisUserAdminMiddleware
doesn't satisfy some check. But this is a bit offtopic here.Screenshots
Here is a screenshot of few console logs from my minimal reproduction code. "This is an additional middleware for admin routes" gets logged even though it shouldn't.
Desktop (please complete the following information):
Additional context
EDIT: Ok I noticed my
createSkippableMiddleware
function isn't actually working because middleware doesn't properly execute one after another, but rather executes async and depends on race conditions. Will fix it at some point, but the idea still stands I guess.I did find a workaround by using
context
and setting a value on it that I use to check if middleware should run and then in middleware that I want to specify "hey, after this middleware don't run anything else" I do call a function to set that flag incontext
. Then those middleware that can be skippable I just create using mycreateSkippableMiddleware
function that just returns the response if thatcontext
key is set and doesn't actually run that middleware's code.I did leave this custom code in my reproduction repo just to showcase how this works. You can clearly see that "This is an additional middleware that won't be logged after the first middleware" message isn't logged when you click on "Skippable Middleware" link on homepage.