Skip to content

Commit 0852d7e

Browse files
fix: bypass deployment protection for read when fetching files in an edge function (#14147)
* add bypass header * add changeset * add docs, link to them from error message --------- Co-authored-by: Rich Harris <[email protected]>
1 parent 107f767 commit 0852d7e

File tree

3 files changed

+35
-2
lines changed

3 files changed

+35
-2
lines changed

.changeset/early-lions-occur.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/adapter-vercel': patch
3+
---
4+
5+
fix: ensure `read` works in an edge function that has deployment protection. Protection bypass automation must be enabled

documentation/docs/25-build-and-deploy/90-adapter-vercel.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,3 +194,7 @@ You can't use `fs` in edge functions.
194194
You _can_ use it in serverless functions, but it won't work as expected, since files are not copied from your project into your deployment. Instead, use the [`read`]($app-server#read) function from `$app/server` to access your files. It also works inside routes deployed as edge functions by fetching the file from the deployed public assets location.
195195

196196
Alternatively, you can [prerender](page-options#prerender) the routes in question.
197+
198+
### Deployment protection
199+
200+
If using [`read`]($app-server#read) in an edge function, SvelteKit will `fetch` the file in question from your deployment. If you are using [Deployment Protection](https://vercel.com/docs/deployment-protection), you must also enable [Protection Bypass for Automation](https://vercel.com/docs/deployment-protection/methods-to-bypass-deployment-protection/protection-bypass-automation) so that the request does not result in a [401 Unauthorized](https://http.dog/401) response.

packages/adapter-vercel/files/edge.js

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@ import { manifest } from 'MANIFEST';
55

66
const server = new Server(manifest);
77

8+
/** @type {HeadersInit | undefined} */
9+
let read_headers;
10+
if (process.env.VERCEL_AUTOMATION_BYPASS_SECRET) {
11+
read_headers = {
12+
'x-vercel-protection-bypass': process.env.VERCEL_AUTOMATION_BYPASS_SECRET
13+
};
14+
}
15+
816
/**
917
* We don't know the origin until we receive a request, but
1018
* that's guaranteed to happen before we call `read`
@@ -15,10 +23,26 @@ let origin;
1523
const initialized = server.init({
1624
env: /** @type {Record<string, string>} */ (process.env),
1725
read: async (file) => {
18-
const response = await fetch(`${origin}/${file}`);
26+
const url = `${origin}/${file}`;
27+
const response = await fetch(url, {
28+
// we need to add a bypass header if the user has deployment protection enabled
29+
// see https://vercel.com/docs/deployment-protection/methods-to-bypass-deployment-protection/protection-bypass-automation
30+
headers: read_headers
31+
});
32+
1933
if (!response.ok) {
20-
throw new Error(`Failed to fetch ${file}: ${response.status} ${response.statusText}`);
34+
if (response.status === 401) {
35+
throw new Error(
36+
`Please enable Protection Bypass for Automation: https://svelte.dev/docs/kit/adapter-vercel#Troubleshooting-Deployment-protection`
37+
);
38+
}
39+
40+
// belt and braces — not sure how we could end up here
41+
throw new Error(
42+
`read(...) failed: could not fetch ${url} (${response.status} ${response.statusText})`
43+
);
2144
}
45+
2246
return response.body;
2347
}
2448
});

0 commit comments

Comments
 (0)