-
-
Notifications
You must be signed in to change notification settings - Fork 10.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add route middleware functionality #9975
Conversation
🦋 Changeset detectedLatest commit: 1e8a428 The changes in this PR will be included in the next version bump. This PR includes changesets to release 5 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
96fe57e
to
a13ebb2
Compare
defaultValue: T | ||
): MiddlewareContextInstance<T> { | ||
return new MiddlewareContextInstance<T>(defaultValue); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pcattori Definitely want to get your eyes on this before merging - this all "works" but no clue if it's "right" ;)
b8c0eeb
to
d84bd08
Compare
*/ | ||
export interface FutureConfig { | ||
unstable_middleware: boolean; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New future config accepted in createRouter
export interface StaticHandlerInit { | ||
basename?: string; | ||
future?: FutureConfig; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
future
also accepted in createStaticHandler
context: requestContext || disabledMiddlewareContext, | ||
}); | ||
|
||
result = await Promise.race([dataPromise, abortPromise]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If enabled, call the middleware pipeline, otherwise just call the handler
packages/router/router.ts
Outdated
// Avoid memory leaks since we don't control the key | ||
let store = new WeakMap(); | ||
let middlewareContext: MiddlewareContext = { | ||
get<T>(k: MiddlewareContextInstance<T>) { | ||
if (store.has(k)) { | ||
return store.get(k) as T; | ||
} | ||
return k.getDefaultValue(); | ||
}, | ||
set<T>(k: MiddlewareContextInstance<T>, v: T) { | ||
if (typeof v === "undefined") { | ||
throw new Error( | ||
"You cannot set an undefined value in the middleware context" | ||
); | ||
} | ||
store.set(k, v); | ||
}, | ||
next: () => {}, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Create the context
for this pipeline (scoped to a given loader/action execution)
packages/router/router.ts
Outdated
let next: MiddlewareContext["next"] = () => { | ||
nextCalled = true; | ||
return callRouteSubPipeline( | ||
request, | ||
matches.slice(1), | ||
params, | ||
requestContext, | ||
middlewareContext, | ||
handler | ||
); | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Provide a next()
function to this middleware which will launch all child middlewares and the eventual handler
if (nextCalled) { | ||
return res; | ||
} else { | ||
return next(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the middleware resolves without calling next()
- just keep going down the chain
ebf9f48
to
19d7488
Compare
658580a
to
3f9c740
Compare
It looks like middleware will get run for document requests, so I think it would be nice to include |
|
||
[pickingarouter]: ../routers/picking-a-router | ||
[react-context]: https://reactjs.org/docs/context.html | ||
[fresh-middleware]: https://fresh.deno.dev/docs/concepts/middleware |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What you would middleware composition look like with this new API?
For example, what If I needed to apply 3-4 middleware to my request, which is not an uncommon thing if you're coming from Express or Fastify or in general a production nodejs server 😄
Recently stumbled upon this lib which takes a fetch
API first approach & feels very vanilla, thought i'd share 👀
https://github.com/data-eden/data-eden/tree/main/packages/network
Closing temporarily - we'll be revisiting shortly after v2 releases |
Now that v2 has been released, perhaps this should be taken out of the fridge..? |
It has - see the roadmap |
Wasn't aware! Thank u! |
Middleware implementation to run before/after loaders/actions. API is inspired by the Fresh middleware with the
.next()
call in the middle thus allowing us to alter responses on the way back up the chain.Data is passed down through strongly typed
get
/set
methods that operate in a React Context-like manner where you define the typed "context" up front with an optional default value and use that as the key.Proposal: #9564
future.unstable_middleware
flagmiddleware
param tocontext
behind the flag