# How to use Netlify Edge Functions

> Learn how to use Netlify Edge Functions to run code on the CDN edge for geolocation, A/B testing, and redirects, configured through a netlify.toml file.

Author: [Flavio Copes](https://flaviocopes.com/about/) | Published: 2022-04-22 | Topics: [Services](https://flaviocopes.com/tags/services/) | Canonical: https://flaviocopes.com/netlify-edge-functions/

[Netlify](https://flaviocopes.com/netlify/) Edge Functions are a very interesting feature offered by [Netlify](https://flaviocopes.com/netlify/), the popular hosting platform.

It's interesting because while Netlify is famous as a static hosting, Edge Functions allow you do do things that are ...not so static.

Allowing us to do things like:

- geolocation
- localization
- A/B testing
- redirects
- ...and much more

They are similar to [Netlify Serverless Functions](https://flaviocopes.com/netlify-functions/), except they run on the Netlify Edge which means they are closer to the user and run on multiple CDN locations, and they are counted differently (3m calls/month instead of 125k calls per site/month).

To enable Edge Functions you create a `netlify.toml` file in your website repository (if you don't have one already) with this content:

```
[[edge_functions]]
  function = "hello" 
  path = "/hello" 
```

`function` is the file name in `netlify/edge-functions/` without the `.js` extension.

`path` is the URL path this function will be available on

Then you can write a function in a file `netlify/edge-functions/hello.js`:

```js
export default () => new Response("Hello world")
```

`Response` is an object we have available to send the response back to the client.

and once you deploy the repository, you can access its result using the URL

```
https://<YOURSITEDOMAIN>/hello
```

Try it!

During the deploy you will see this in the logs:

![Netlify deploy logs showing Edge Functions bundling process with packaging from netlify/edge-functions directory](https://flaviocopes.com/images/netlify-edge-functions/Screen_Shot_2022-04-20_at_12.24.02.png)

And once the deploy is done, you'll see a page dynamically generated with the content `Hello, World!`. 

But I recommend first to test them locally using the Netlify CLI `netlify dev`. Make sure it's up to date with `npm i -g netlify-cli` otherwise it might not have the feature enabled.

You can set the response headers, like the content type for example, passing a second parameter to `new Response()`:

```js
export default () =>
  new Response('Hello world', {
    headers: { 'content-type': 'text/html' },
  })
```

The edge function receives two arguments: `request` and `context`:

```js
export default (request, context) => {
  //...
}
```

Those two objects provide interesting features.

`request` allows you to access all the [request data](https://developer.mozilla.org/en-US/docs/Web/API/Request), and it's the same request object you get when using the Fetch API.

`context` allows you to access cookies, geolocation data, json, log, and more.

You can write to the logs using context.log():

```js
export default (request, context) => {
  context.log('test')
}
```

You can see the logs in the Edge Functions menu of your website:

![Netlify dashboard showing Edge Functions page with log entries displaying function execution output](https://flaviocopes.com/images/netlify-edge-functions/Screen_Shot_2022-04-20_at_12.39.06.png)

You can return [JSON](https://flaviocopes.com/json/) using the `context.json` function:

```js
export default (request, context) => {
  return context.json({ hello: 'world' })
}
```

If you want to write more than one function, you add other entries in `netlify.toml`:

```
[[edge_functions]]
  function = "hello"
  path = "/hello"

[[edge_functions]]
  function = "second"
  path = "/second"
```

The function can be async if you plan to use promise-based APIs like the [Fetch API](https://flaviocopes.com/fetch-api/) to get some JSON from a remote server:

```js
export default async () => await fetch('https://dog.ceo/api/breeds/image/random')
```

or even an image directly:

```js
export default async () => await fetch('https://placekitten.com/g/300/300')
```

You can get the user's location:

```js
export default async (request, context) =>
  new Response(`
    Country code: ${context.geo?.country?.code}
    Country name: ${context.geo?.country?.name}
    City: ${context.geo?.city}
    Subdivision: ${context.geo?.subdivision?.code} - ${context.geo?.subdivision?.name}
  `)
```

> Tip: does only work on the edge, not locally

There's an example on the Netlify docs on how to use this to block access to your website from a country, for example.

Working with cookies you can set a [cookie](https://flaviocopes.com/cookies/) in this way:

```js
export default (request, context) => {
  context.cookies.set({
    name: "alreadyvisited",
    value: "yes"
  })
}
```

You can use `context.cookies.get()` to read the value of a cookie, or `context.cookies.delete()` to delete a cookie.

You can access environment variables using `Deno.env.get()`, like this:

```js
Deno.env.get('YOUR_VARIABLE')
```

Example:

```js
export default () => new Response(Deno.env.get('YOUR_VARIABLE'))
```

I take this last example to say that Netlify Edge Functions run on Deno. 

Learn more about Deno in my [Deno tutorial](https://flaviocopes.com/deno/)!

That's it for this overview, hopefully it gave you some ideas on how to use them for your use case.

I think they are pretty cool and maybe you will use them without even realizing when you deploy a [Next.js](https://flaviocopes.com/nextjs/) or Remix or SvelteKit app on Netlify, and they use this feature under the hood.

I recommend you check out the full examples library on https://edge-functions-examples.netlify.app and read more about the Web APIs you can use on https://docs.netlify.com/netlify-labs/experimental-features/edge-functions/api/
