Three ways to set headers with Netlify and Astro

April 15, 2023

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.


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()
Enter fullscreen mode

Exit fullscreen mode

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
  for = "/*"
    Access-Control-Allow-Origin = "*"
Enter fullscreen mode

Exit fullscreen mode

There’s also a _headers file that Netlify supports that’s very similar:

# _headers
  Access-Control-Allow-Origin: *

Enter fullscreen mode

Exit fullscreen mode

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
  from = ""
  to = "*"
  status = 200
  force = true
  headers = { Access-Control-Allow-Origin = "*" }
Enter fullscreen mode

Exit fullscreen mode

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
    path = "/*"
    function = "headers" # or whatever your file name is
Enter fullscreen mode

Exit fullscreen mode

Then, in that headers.js file, you add your headers:

// headers.js
export default async (request, context) => {
    const response = await;

    // 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;
Enter fullscreen mode

Exit fullscreen mode

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.
Enter fullscreen mode

Exit fullscreen mode

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!

Source link

Comments 0

Leave a Reply

Your email address will not be published. Required fields are marked *