Reputation: 7687
I need to serve some files from my SvelteKit project with permissive CORS headers.
Some options I've explored:
/static
If I place those files in /static
I get restrictive CORS headers.
Is there a way to customize headers for static files? I would guess not, based on this conversation: https://github.com/sveltejs/kit/issues/2060.
/lib
I can place the files elsewhere in the directory structure, then access them using readFile
from within a +server.ts
endpoint.
However, if I place the files in /lib
and build, they do not get copied into the build output at an easily accessible path.
I can figure out the correct path manually, but it's brittle and only works when I'm running the pre-built project (i.e. only if I do npm build; npm preview
, and not if I do npm dev
).
Using the same custom endpoint approach as above, in theory I could:
vite.config.ts
:{
...,
resolve: {
alias: {
$public: '/public'
}
}
}
readFile(`$public/{params.filename}`)
However, when building, Vite does not rewrite $public
to the correct path in the build output. It would appear that this path rewriting only works in certain situations.
Again using the custom endpoint approach, I could add a new step to my Docker build to copy the files to a path outside of the SvelteKit build output and then read them from disk at that path.
Unfortunately I then don't get the benefit of any of the packaging that SvelteKit/Vite does when building my assets (e.g. compression).
Upvotes: 3
Views: 1378
Reputation: 7687
For now I have a quick fix in place, which is to:
/static/__public/
, where they will be served by SvelteKit at /__public/<filename>.js
without the correct CORS headers.../public/[filename]/+server.ts
make a fetch to /__public/<filename>.js
, manipulate the headers in the response and send it on its way, i.e.:// In /src/routes/public/[filename]/+server.ts
export const GET = (async ({ fetch, url, params }) => {
const response = await fetch(new URL(`/__public/${params.filename}`, url.origin));
const mimeType = "replace-me"; // I'm using the mime-types library here, i.e. `mime.lookup(params.filename);`
const headers = {
...response.headers,
'Access-Control-Allow-Origin': `*`,
'Content-Type': `${mimeType};charset=UTF-8`
};
return new Response(response.body, {
headers
});
}) satisfies RequestHandler;
export const OPTIONS = (async ({ fetch, url, params }) => {
const response = await fetch(new URL(`/__public/${params.filename}`, url.origin), {
method: 'OPTIONS'
});
const headers = {
...response.headers,
'Access-Control-Allow-Methods': 'GET, OPTIONS',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': '*'
};
return new Response(null, {
headers
});
}) satisfies RequestHandler;
While it does work, this is suboptimal:
/__public/<filename>.js
without permissive CORS headers, and /public/<filename>.js
with the correct headers.Upvotes: 1