Three ways to set headers with Netlify and Astro
Tags: astro, netlify, javascript, cors
Published: 2023-04-15 01:57:10

---
title: Three ways to set headers with Netlify and Astro
published: true
description: If you need to set headers in your Astro site to deal with CORS or custom requests, here's a few ways how!
tags: astro, netlify, javascript, cors
cover_image: https://images.unsplash.com/photo-1495020689067-958852a7765e?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1738&q=80
canonical_url: https://cassidoo.co/post/netlify-astro-headers
---

I recently had to build an [Astro](https://astro.build/) website on [Netlify](https://www.netlify.com/) 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](https://docs.astro.build/en/guides/integrations-guide/netlify/) if you need it! I'm also assuming you have the [`@astrojs/netlify`](https://docs.astro.build/en/guides/integrations-guide/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.

```js
// 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](https://docs.netlify.com/routing/headers/)):

```toml
# 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](https://docs.netlify.com/routing/redirects/rewrites-proxies/) (again in the `netlify.toml`) where you take a relative route, point it to an absolute route, and add the header.

```toml
# 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`:

```toml
# netlify.toml
[[edge_functions]]
	path = "/*"
	function = "headers" # or whatever your file name is
```

Then, in that `headers.js` file, you add your headers:
```js
// 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](https://contenda.co/), and you can probably find some of these sprinkled in some of our [open source repos](https://github.com/contenda-team/share-pear) 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!