-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
fix(vercel): edge middleware #9585
Conversation
🦋 Changeset detectedLatest commit: 930f851 The changes in this PR will be included in the next version bump. 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 |
This comment has been minimized.
This comment has been minimized.
@gislerro Will be ready for review soon after astro 4.2 (wednesday). The work is done, it is just based on a future branch. Late this week/early next week. |
06906cd
to
32b2288
Compare
remove getVercelOutput
32b2288
to
5c7d8ca
Compare
f3ead9c
to
8081fad
Compare
interface CreateMiddlewareFolderArgs { | ||
config: AstroConfig | ||
entry: URL | ||
functionName: string | ||
} | ||
|
||
async function createMiddlewareFolder({ | ||
functionName, | ||
entry, | ||
config, | ||
}: CreateMiddlewareFolderArgs) { | ||
const functionFolder = new URL(`./functions/${functionName}.func/`, config.outDir); | ||
|
||
await generateEdgeMiddleware( | ||
entry, | ||
new URL(VERCEL_EDGE_MIDDLEWARE_FILE, config.srcDir), | ||
new URL('./middleware.mjs', functionFolder), | ||
) | ||
|
||
await writeJson(new URL(`./.vc-config.json`, functionFolder), { | ||
runtime: 'edge', | ||
entrypoint: 'middleware.mjs', | ||
}); | ||
} | ||
|
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.
We create an edge function, complete with its own folder and vc-config.
const { origin } = new URL(request.url); | ||
const next = () => | ||
fetch(new URL('/_render', request.url), { | ||
headers: { | ||
${JSON.stringify(ASTRO_LOCALS_HEADER)}: trySerializeLocals(ctx.locals) | ||
...Object.fromEntries(request.headers.entries()), | ||
'x-astro-path': request.url.replace(origin, ''), | ||
'x-astro-locals': trySerializeLocals(ctx.locals) | ||
} | ||
}); | ||
return response; | ||
}; | ||
}) |
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.
The edge function calls the node server at /_render
, with the original path as a header.
: _middlewareEntryPoint ? '_middleware' | ||
: 'render', |
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.
Should this use dest
instead? Or the render
should be _render
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.
I think we should move this strings (_render
, _middleware
) to some constants, so we don't do any typo
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.
You're right, it is supposed to be _render
. Moved to constants.
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.
Sorry to bother you, but this PR has many changes that aren't related to the edge middleware and aren't explained in the PR description.
Could you:
- Describe the entity to the changes in the PR description. For example, we don't know why you changed
render
to_render
. - Move them in a separate PR
} | ||
} | ||
if (_middlewareEntryPoint) { | ||
await createMiddlewareFolder({ | ||
functionName: '_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.
Why _middleware
and not 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.
Vercel routes the folder names to a path on the deployed website so we avoid interfering this way.
: _middlewareEntryPoint ? '_middleware' | ||
: 'render', |
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.
I think we should move this strings (_render
, _middleware
) to some constants, so we don't do any typo
const realPath = req.headers['x-astro-path']; | ||
if (typeof realPath === 'string') { | ||
req.url = realPath; | ||
} |
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's this change about?
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.
This is so that the edge function can call the serverless function in 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.
I still think it's worth adding a comment because the read and write of the header happens in two different places, so it could be helpful to give some context.
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.
Changes
Testing
Added cases to edge-middleware.test.js
Docs
Does not affect usage.