Three ways to set headers with Netlify and Astro
I recently had to build an Astro website on Netlify in which we needed custom headers. Turns out there’s several different ways to do that, some of them are weird, and some of them will work better for your use cases than others.
I’m writing this down here because I know for a fact that I will need to refer back to this again someday, because CORS errors are the worst and omnipresent.
Anyway!
There are also other ways, but I am only going to list three, because these are the three that seem to work the most for me. I’m also just doing it for the Access=Control-Allow-Origin
header because you can probably figure out how to add others once you see one.
Also, here’s the Astro documentation for the Netlify integration if you need it! I’m also assuming you have the @astrojs/netlify
package installed if you’re using Astro for server-side rendering or for on-demand builders.
Setting headers in your Astro config
The first way to set headers in Astro is directly in the astro.config.mjs
file.
// astro.config.mjs
import { defineConfig } from "astro/config";
import netlify from "@astrojs/netlify/functions";
export default defineConfig({
output: "server",
server: {
headers: {
"Access-Control-Allow-Origin": "*"
}
},
adapter: netlify()
});
This works great if you’re running your Astro site in server-side rendering mode, but it’s kind of weird on Netlify sometimes (and I admit I don’t know all the cases, like when edge functions are involved or something, etc), so if it doesn’t work, don’t fret, there’s other options!
Setting headers in the Netlify config file
You can set headers in your netlify.toml
like so (docs here):
# netlify.toml
[[headers]]
for = "/*"
[headers.values]
Access-Control-Allow-Origin = "*"
There’s also a _headers
file that Netlify supports that’s very similar:
# _headers
/*
Access-Control-Allow-Origin: *
And also similar still is setting a Netlify proxy redirect (again in the netlify.toml
) where you take a relative route, point it to an absolute route, and add the header.
# netlify.toml
[[redirects]]
from = "/search"
to = "https://somewebsitethatimadeup.biz/search/*"
status = 200
force = true
headers = { Access-Control-Allow-Origin = "*" }
This Netlify config method works best with static sites, not anything served with serverless functions or edge functions.
Setting headers with an edge function as middleware
This is probably the most “advanced” way to set headers, but it works really well, and you can add a lot more custom logic to it (plus I think it has the least restrictions as well).
First of all, you have to make an edge function file in netlify/edge-functions/
(I’ll call mine headers.js
), and then point to it in your netlify.toml
:
# netlify.toml
[[edge_functions]]
path = "/*"
function = "headers" # or whatever your file name is
Then, in that headers.js
file, you add your headers:
// headers.js
export default async (request, context) => {
const response = await context.next();
// You need this if you are calling this from the browser
// to handle CORS preflight stuff
if (request.method === "OPTIONS") {
return new Response("ok", {
headers: {
"Access-Control-Allow-Origin": "*",
}
});
}
response.headers.set("Access-Control-Allow-Origin", "*");
return response;
};
If you don’t add that OPTIONS
conditional, you might see an error like this whenever you call that edge function:
Access to fetch at '...' from origin '...' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
Anyway, in here you can do whatever logic you’d like around adding headers conditionally, adding multiple headers, whatever your heart wants!
The end
These were all things that I ended up working with for some projects at my work, Contenda, and you can probably find some of these sprinkled in some of our open source repos if you’d like to see some examples.
All this being said…
For future Cassidy: welcome back. I see you’re running into the same CORS issues again. When will you ever learn?
For everyone else: I hope this was helpful for you, ‘til next time!