diff --git a/README.md b/README.md
index f446fc2..1a20aa7 100644
--- a/README.md
+++ b/README.md
@@ -1,59 +1,14 @@
-
+
-# [Netlify Edge Functions](https://www.netlify.com/products/?utm_campaign=devex&utm_source=edge-functions-examples&utm_medium=github&utm_content=Edge%20Functions%20Product%20Page#netlify-edge-functions) Examples
-
-Explore these examples here: https://edge-functions-examples.netlify.app/
-
-## Responses
-
-- [Hello, world](/pages/hello)
-- [Return JSON](/pages/json)
-- [Return an image](/pages/image)
-
-## Rewrites and proxies
-
-- [Rewrite responses from another URL](/pages/rewrite)
-- [Proxy requests to another source](/pages/proxy-requests)
-
-## HTTP Headers
-
-- [Set custom HTTP request headers](/pages/set-request-header)
-- [Set custom HTTP response headers](/pages/set-response-header)
-
-## Transforming responses
-- [Text transformation](/pages/transform)
-- [Content includes](/pages/include)
-
-## Geolocation
-
-- [Determine a user's location](/pages/geolocation)
-- [Block content according to country](/pages/country-block)
-- [Serve localized content](/pages/localized-content)
-
-## Cookies
-
-- [Set cookies](/pages/cookies-set)
-- [Read cookies](/pages/cookies-read)
-- [Delete cookies](/pages/cookies-delete)
-- [Set up an A/B test using cookies](/pages/abtest)
-
-## Streams
-- [Long-running edge functions](/pages/long-running)
-- [Server-sent events](/pages/server-sent-events)
-
-## WebAssembly
-- [Edge WebAssembly](/pages/wasm)
-
-## Environment and debugging
+# [Netlify Edge Functions](https://www.netlify.com/products/?utm_campaign=devex&utm_source=edge-functions-examples&utm_medium=github&utm_content=Edge%20Functions%20Product%20Page#netlify-edge-functions) Examples
-- [Write to the logs](/pages/log)
-- [Use environment variables](/pages/environment)
+Try these examples here: https://edge-functions-examples.netlify.app/
---
-## Deploy this site to Netlify
+## This code has a new home
-Click this button to deploy this site automatically to your Netlify account.
+This repo has been migrated into the [Netlify Examples monorepo](https://github.com/netlify/examples/tree/main/examples/edge-functions ).
-[](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/edge-functions-examples&utm_campaign=devex&utm_source=edge-functions-examples&utm_medium=web&utm_content=Deploy%20Edge%20Functions%20Examples%20to%20Netlify)
+Explore the code for these examples, along with many others here: https://github.com/netlify/examples/
diff --git a/components/layout.js b/components/layout.js
index 6ba5d3a..152d7b1 100644
--- a/components/layout.js
+++ b/components/layout.js
@@ -7,7 +7,7 @@ const explainer = `
Using JavaScript and TypeScript, Netlify Edge Functions give you the power to modify network requests to localize content, serve relevant ads, authenticate visitors, A/B test content, and much more! And this all happens at the Edge — directly from the worldwide location closest to each user. To use Edge Functions on Netlify, add JavaScript or TypeScript files to an edge-functions directory in your project, and add To use Edge Functions on Netlify, add JavaScript or TypeScript files to an edge-functions directory in your project.What are Edge Functions?
[[edge_functions]] entries to your netlify.toml file.
- ${data.url.pathname !== "/" ? `Explore more examples` : ""} + ${ + data.url.pathname !== "/" ? `Explore more examples` : "" + }
${data.url.pathname !== "/" ? explainer : ""} diff --git a/netlify.toml b/netlify.toml index c5b9639..ae0c4a5 100644 --- a/netlify.toml +++ b/netlify.toml @@ -1,119 +1,19 @@ [dev] - framework = "#static" +framework = "#static" [build] - command = "echo No build for this site, we are living on the edge" - publish = "public" +command = "echo No build for this site, we are living on the edge" +publish = "public" [context.production] - environment = { MY_IMPORTANT_VARIABLE = "this is a very important secret" } +environment = { MY_IMPORTANT_VARIABLE = "this is a very important secret" } -# The URL for each edge function -[[edge_functions]] - function = "transform" - path = "/*" - -[[edge_functions]] - function = "set-response-header" - path = "/*" -[[edge_functions]] - function = "set-request-header" - path = "/*" +[[redirects]] +from = "/img/og/:text" +to = "https://res.cloudinary.com/netlify/image/upload/c_fit,g_west,h_400,co_rgb:FFFFFFFF,l_text:netlify.com:Pacaembu-Bold.ttf_57::text,w_1053,x_46/v1619123320/netlify.com/default-og-background-learn-more.png" +status = 200 [[edge_functions]] - function = "include" + function = "transform" path = "/*" - -[[edge_functions]] - path = "/hello" - function = "hello" - -[[edge_functions]] - path = "/geolocation" - function = "geolocation" - -[[edge_functions]] - path = "/json" - function = "json" - -[[edge_functions]] - path = "/cookies" - function = "cookies" - -[[edge_functions]] - path = "/rewrite" - function = "rewrite" - -[[edge_functions]] - path = "/abtest" - function = "abtest" - -[[edge_functions]] - path = "/image-internal" - function = "image-internal" - -[[edge_functions]] - path = "/image-external" - function = "image-external" - -[[edge_functions]] - path = "/log" - function = "log" - -[[edge_functions]] - path = "/country-block" - function = "country-block" - -[[edge_functions]] - path = "/localized-content" - function = "localized-content" - -[[edge_functions]] - path = "/fetch-joke" - function = "proxy-requests" - -[[edge_functions]] - path = "/environment" - function = "environment" - -[[edge_functions]] - path = "/error" - function = "error" - -[[edge_functions]] - path = "/long-running" - function = "long-running" - -[[edge_functions]] - path = "/sse" - function = "sse" - -[[edge_functions]] - path = "/context-site" - function = "context-site" - -[[edge_functions]] - path = "/wasm" - function = "wasm" - -# Serve pages explaining each example -[[edge_functions]] - path = "/example/*" - function = "[page]" - -# Serve our index page -[[edge_functions]] - path = "/" - function = "[page]" - -[[redirects]] - from = "/img/og/:text" - to = "https://res.cloudinary.com/netlify/image/upload/c_fit,g_west,h_400,co_rgb:FFFFFFFF,l_text:netlify.com:Pacaembu-Bold.ttf_57::text,w_1053,x_46/v1619123320/netlify.com/default-og-background-learn-more.png" - status = 200 - - - - - - diff --git a/netlify/edge-functions/[page].js b/netlify/edge-functions/[page].js index c9a1f7d..7327927 100644 --- a/netlify/edge-functions/[page].js +++ b/netlify/edge-functions/[page].js @@ -8,12 +8,14 @@ import layout from "../../components/layout.js"; import pageHome from "../../pages/home/index.js"; import pageHello from "../../pages/hello/index.js"; import pageTransform from "../../pages/transform/index.js"; +import pageHtmlrewriter from "../../pages/htmlrewriter/index.js"; import pageInclude from "../../pages/include/index.js"; import pageRewrite from "../../pages/rewrite/index.js"; import pageGeolocation from "../../pages/geolocation/index.js"; import pageJson from "../../pages/json/index.js"; import pageSetRequestHeader from "../../pages/set-request-header/index.js"; import pageSetResponseHeader from "../../pages/set-response-header/index.js"; +import pageMethod from "../../pages/method/index.js"; import pageCookiesSet from "../../pages/cookies-set/index.js"; import pageCookiesRead from "../../pages/cookies-read/index.js"; import pageCookiesDelete from "../../pages/cookies-delete/index.js"; @@ -39,6 +41,7 @@ const pages = { json: pageJson, "set-response-header": pageSetResponseHeader, "set-request-header": pageSetRequestHeader, + method: pageMethod, "cookies-set": pageCookiesSet, "cookies-read": pageCookiesRead, "cookies-delete": pageCookiesDelete, @@ -53,14 +56,15 @@ const pages = { environment: pageEnvironment, "uncaught-exceptions": pageUncaughtExceptions, "context-site": pageContextSite, - "wasm": pageWasm, + wasm: pageWasm, "server-sent-events": pageSse, "long-running": pageLongRunning, + htmlrewriter: pageHtmlrewriter, }; export default (request, context) => { const url = new URL(request.url); - const path = url.pathname.split("/example/")[1] || "home"; + const path = context.params?.page || "home"; console.log(`serve page for ${url} `); @@ -77,3 +81,7 @@ export default (request, context) => { headers: { "content-type": "text/html" }, }); }; + +export const config = { + path: ["/", "/example/:page"], +}; diff --git a/netlify/edge-functions/abtest.ts b/netlify/edge-functions/abtest.ts index 6840777..bbcfa4d 100644 --- a/netlify/edge-functions/abtest.ts +++ b/netlify/edge-functions/abtest.ts @@ -1,4 +1,4 @@ -import type { Context } from "https://edge.netlify.com/"; +import type { Context, Config } from "@netlify/edge-functions"; export default async (request: Request, context: Context) => { // look for existing "test_bucket" cookie @@ -29,3 +29,7 @@ export default async (request: Request, context: Context) => { `Congratulations! You have been assigned ${bucketName} **${newBucketValue}**. View your browser cookies to check it out!`, ); }; + +export const config: Config = { + path: "/abtest", +}; \ No newline at end of file diff --git a/netlify/edge-functions/context-site.ts b/netlify/edge-functions/context-site.ts index 122432f..163d0ee 100644 --- a/netlify/edge-functions/context-site.ts +++ b/netlify/edge-functions/context-site.ts @@ -1,5 +1,9 @@ -import type { Context } from "https://edge.netlify.com/"; +import type { Context, Config } from "@netlify/edge-functions"; export default async (request: Request, context: Context) => { return new Response(`Hello from ${context.site.name}!`); }; + +export const config: Config = { + path: "/context-site", +}; \ No newline at end of file diff --git a/netlify/edge-functions/cookies.ts b/netlify/edge-functions/cookies.ts index 494d999..92bc8fb 100644 --- a/netlify/edge-functions/cookies.ts +++ b/netlify/edge-functions/cookies.ts @@ -1,4 +1,4 @@ -import type { Context } from "https://edge.netlify.com/"; +import type { Context, Config } from "@netlify/edge-functions"; export default async (request: Request, context: Context) => { const url = new URL(request.url); @@ -27,3 +27,7 @@ export default async (request: Request, context: Context) => { return new Response(message); }; + +export const config: Config = { + path: "/cookies", +}; \ No newline at end of file diff --git a/netlify/edge-functions/country-block.ts b/netlify/edge-functions/country-block.ts index 9cee3cd..661d5ca 100644 --- a/netlify/edge-functions/country-block.ts +++ b/netlify/edge-functions/country-block.ts @@ -1,4 +1,4 @@ -import { Context } from "https://edge.netlify.com/"; +import type { Context, Config } from "@netlify/edge-functions"; export default async (request: Request, context: Context) => { // Here's what's available on context.geo @@ -32,3 +32,7 @@ export default async (request: Request, context: Context) => { headers: { "content-type": "text/html" }, }); }; + +export const config: Config = { + path: "/country-block", +}; \ No newline at end of file diff --git a/netlify/edge-functions/environment.ts b/netlify/edge-functions/environment.ts index 7f93604..9fb6d75 100644 --- a/netlify/edge-functions/environment.ts +++ b/netlify/edge-functions/environment.ts @@ -1,4 +1,4 @@ -import type { Context } from "https://edge.netlify.com/"; +import type { Context, Config } from "@netlify/edge-functions"; export default async (request: Request, context: Context) => { const value = Netlify.env.get("MY_IMPORTANT_VARIABLE"); @@ -7,3 +7,7 @@ export default async (request: Request, context: Context) => { headers: { "content-type": "text/html" }, }); }; + +export const config: Config = { + path: "/environment", +}; \ No newline at end of file diff --git a/netlify/edge-functions/error.ts b/netlify/edge-functions/error.ts index 94c50aa..a60cd44 100644 --- a/netlify/edge-functions/error.ts +++ b/netlify/edge-functions/error.ts @@ -1,3 +1,7 @@ export default async () => { throw new Error("💥"); }; + +export const config = { + path: "/error", +}; \ No newline at end of file diff --git a/netlify/edge-functions/geolocation.ts b/netlify/edge-functions/geolocation.ts index 3a582ef..cc7f694 100644 --- a/netlify/edge-functions/geolocation.ts +++ b/netlify/edge-functions/geolocation.ts @@ -1,4 +1,5 @@ -import { Context } from "https://edge.netlify.com/"; +import type { Config, Context } from "@netlify/edge-functions"; + export default async (request: Request, context: Context) => { // Here's what's available on context.geo @@ -24,3 +25,7 @@ export default async (request: Request, context: Context) => { geo: context.geo, }); }; + +export const config: Config = { + path: "/geolocation", +}; \ No newline at end of file diff --git a/netlify/edge-functions/hello.js b/netlify/edge-functions/hello.js index 4de5bcc..0d6ce29 100644 --- a/netlify/edge-functions/hello.js +++ b/netlify/edge-functions/hello.js @@ -3,3 +3,7 @@ export default async (request) => { headers: { "content-type": "text/html" }, }); }; + +export const config = { + path: "/hello", +}; \ No newline at end of file diff --git a/netlify/edge-functions/htmlrewriter.ts b/netlify/edge-functions/htmlrewriter.ts new file mode 100644 index 0000000..aa70a8a --- /dev/null +++ b/netlify/edge-functions/htmlrewriter.ts @@ -0,0 +1,35 @@ +import { Config, Context } from "@netlify/edge-functions"; +import { HTMLRewriter } from "https://ghuc.cc/worker-tools/html-rewriter/index.ts"; + +export default async function handler(request: Request, context: Context) { + const url = new URL(request.url); + if (!url.searchParams.has("catify")) { + return; + } + + const location = context?.geo?.city; + + const response = await context.next(); + const rewriter = new HTMLRewriter() + .on("#location", { + element: (element) => { + element.setInnerContent(`Catified for a visitor in ${location}`); + }, + }) + .on("img[catify]", { + element: (element) => { + const width = element.getAttribute("width") ?? 800; + const height = element.getAttribute("height") ?? 600; + element.setAttribute( + "src", + `https://placekitten.com/${width}/${height}` + ); + element.setAttribute("alt", "A random cat"); + }, + }); + return rewriter.transform(response); +} + +export const config: Config = { + path: "/a-static-page", +}; diff --git a/netlify/edge-functions/image-external.ts b/netlify/edge-functions/image-external.ts index 85fdcc6..627359e 100644 --- a/netlify/edge-functions/image-external.ts +++ b/netlify/edge-functions/image-external.ts @@ -1,4 +1,4 @@ -import type { Context } from "https://edge.netlify.com/"; +import type { Context, Config } from "@netlify/edge-functions"; // Let's serve an image of a kitten from the internet @@ -9,3 +9,7 @@ export default async (request: Request, context: Context) => { const kitten = await fetch("https://github.com/service/https://placekitten.com/g/300/300"); return kitten; }; + +export const config: Config = { + path: "/image-external", +}; \ No newline at end of file diff --git a/netlify/edge-functions/image-internal.ts b/netlify/edge-functions/image-internal.ts index a6b820b..25400c4 100644 --- a/netlify/edge-functions/image-internal.ts +++ b/netlify/edge-functions/image-internal.ts @@ -1,4 +1,4 @@ -import type { Context } from "https://edge.netlify.com/"; +import type { Context, Config } from "@netlify/edge-functions"; // Let's serve an image that's stored in the repo // by rewriting the URL. @@ -6,3 +6,7 @@ import type { Context } from "https://edge.netlify.com/"; export default async (request: Request, context: Context) => { return new URL("/apple-touch-icon.png", request.url); }; + +export const config: Config = { + path: "/image-internal", +}; \ No newline at end of file diff --git a/netlify/edge-functions/include.ts b/netlify/edge-functions/include.ts index 74ae860..9e2440b 100644 --- a/netlify/edge-functions/include.ts +++ b/netlify/edge-functions/include.ts @@ -1,4 +1,4 @@ -import { Context } from "https://edge.netlify.com/"; +import { Context, Config } from "@netlify/edge-functions"; export default async (request: Request, context: Context) => { @@ -23,3 +23,7 @@ export default async (request: Request, context: Context) => { const updatedPage = page.replace(regex, pricingContent); return new Response(updatedPage, response); }; + +export const config: Config = { + path: "/*", +}; \ No newline at end of file diff --git a/netlify/edge-functions/json.ts b/netlify/edge-functions/json.ts index 95624ab..6a9a3ef 100644 --- a/netlify/edge-functions/json.ts +++ b/netlify/edge-functions/json.ts @@ -1,5 +1,9 @@ -import type { Context } from "https://edge.netlify.com/"; +import type { Context, Config } from "@netlify/edge-functions"; export default async (request: Request, context: Context) => { return Response.json({ hello: "world" }); }; + +export const config: Config = { + path: "/json", +}; \ No newline at end of file diff --git a/netlify/edge-functions/localized-content.js b/netlify/edge-functions/localized-content.js index 7a81319..575cefd 100644 --- a/netlify/edge-functions/localized-content.js +++ b/netlify/edge-functions/localized-content.js @@ -14,3 +14,7 @@ export default async (request, context) => { headers: { "content-type": "text/html" }, }); }; + +export const config = { + path: "/localized-content", +}; \ No newline at end of file diff --git a/netlify/edge-functions/log.ts b/netlify/edge-functions/log.ts index 289a8fd..0fe4962 100644 --- a/netlify/edge-functions/log.ts +++ b/netlify/edge-functions/log.ts @@ -1,4 +1,4 @@ -import type { Context } from "https://edge.netlify.com/"; +import type { Context, Config } from "@netlify/edge-functions"; export default async (request: Request, context: Context) => { console.log("Hello from the logging service"); @@ -7,3 +7,7 @@ export default async (request: Request, context: Context) => { headers: { "content-type": "text/html" }, }); }; + +export const config: Config = { + path: "/log", +}; \ No newline at end of file diff --git a/netlify/edge-functions/long-running.ts b/netlify/edge-functions/long-running.ts index 2a2560e..06d5508 100644 --- a/netlify/edge-functions/long-running.ts +++ b/netlify/edge-functions/long-running.ts @@ -1,4 +1,4 @@ -import type { Context } from "https://edge.netlify.com/"; +import type { Context, Config } from "@netlify/edge-functions"; function doSomethingSlow(): PromiseVisitors can then be redirected to different pages, depending on the bucket and cookie they were assigned.
You could even use A/B testing in combination with Geolocation at The Edge!
-import type { Context } from "https://edge.netlify.com/";
+ import type { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
// look for existing "test_bucket" cookie
diff --git a/pages/context-site/README.md b/pages/context-site/README.md
index cf7b89a..fa3546d 100644
--- a/pages/context-site/README.md
+++ b/pages/context-site/README.md
@@ -9,7 +9,7 @@ Netlify Edge Functions give access to site information via `context.site`.
Edge Functions are files held in the `netlify/edge-functions` directory.
```ts
-import type { Context } from "https://edge.netlify.com/";
+import type { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
return new Response(`Hello from ${context.site.name}!`);
diff --git a/pages/context-site/index.js b/pages/context-site/index.js
index e68d3be..e297982 100644
--- a/pages/context-site/index.js
+++ b/pages/context-site/index.js
@@ -8,7 +8,7 @@ export default {
Access Site Information from Edge Functions
Netlify Edge Functions give access to site information via context.site.
- import type { Context } from "https://edge.netlify.com/";
+ import type { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
return new Response(\`Hello from \${context.site.name}!\`);
diff --git a/pages/cookies-delete/README.md b/pages/cookies-delete/README.md
index 04a72a0..cabb018 100644
--- a/pages/cookies-delete/README.md
+++ b/pages/cookies-delete/README.md
@@ -9,7 +9,7 @@ Manipulate HTTP cookies
Edge Functions are files held in the `netlify/edge-functions` directory.
```ts
-import type { Context } from "https://edge.netlify.com/";
+import type { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
// Set a cookie
diff --git a/pages/cookies-delete/index.js b/pages/cookies-delete/index.js
index 4e75bcb..af83ef5 100644
--- a/pages/cookies-delete/index.js
+++ b/pages/cookies-delete/index.js
@@ -8,7 +8,7 @@ export default {
Delete HTTP cookies
Use an Edge Function to delete cookies.
- import type { Context } from "https://edge.netlify.com/";
+ import type { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
// Delete a cookie
diff --git a/pages/cookies-read/README.md b/pages/cookies-read/README.md
index 2f8ef06..cd2cdc3 100644
--- a/pages/cookies-read/README.md
+++ b/pages/cookies-read/README.md
@@ -9,7 +9,7 @@ Manipulate HTTP cookies
Edge Functions are files held in the `netlify/edge-functions` directory.
```ts
-import type { Context } from "https://edge.netlify.com/";
+import type { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
// Set a cookie
diff --git a/pages/cookies-read/index.js b/pages/cookies-read/index.js
index d566930..0bcacee 100644
--- a/pages/cookies-read/index.js
+++ b/pages/cookies-read/index.js
@@ -8,7 +8,7 @@ export default {
Reading cookies
Use an Edge Function to read and manage HTTP cookies.
- import type { Context } from "https://edge.netlify.com/";
+ import type { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
// Read the value of a cookie
diff --git a/pages/cookies-set/README.md b/pages/cookies-set/README.md
index 506e18a..128e438 100644
--- a/pages/cookies-set/README.md
+++ b/pages/cookies-set/README.md
@@ -9,7 +9,7 @@ Manipulate HTTP cookies
Edge Functions are files held in the `netlify/edge-functions` directory.
```ts
-import type { Context } from "https://edge.netlify.com/";
+import type { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
// Set a cookie
diff --git a/pages/cookies-set/index.js b/pages/cookies-set/index.js
index 8a69ddd..6ea18cc 100644
--- a/pages/cookies-set/index.js
+++ b/pages/cookies-set/index.js
@@ -8,7 +8,7 @@ export default {
Setting cookies
Use an Edge Function to create and manage HTTP cookies.
- import type { Context } from "https://edge.netlify.com/";
+ import type { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
// Set a cookie
diff --git a/pages/country-block/index.js b/pages/country-block/index.js
index 7ac904a..56840eb 100644
--- a/pages/country-block/index.js
+++ b/pages/country-block/index.js
@@ -10,7 +10,7 @@ export default {
You can use geolocation data to identify a user's country and block content if required.
Geolocation information is available on the Context.geo object.
- import { Context } from "https://edge.netlify.com/";
+ import { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
const BLOCKED_COUNTRY_CODE = "GB";
diff --git a/pages/environment/README.md b/pages/environment/README.md
index ca75d43..a9d42cf 100644
--- a/pages/environment/README.md
+++ b/pages/environment/README.md
@@ -10,7 +10,7 @@ use the `Netlify.env` API.
Edge Functions are files held in the `netlify/edge-functions` directory.
```ts
-import type { Context } from "https://edge.netlify.com/";
+import type { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
const value = Netlify.env.get("MY_IMPORTANT_VARIABLE");
diff --git a/pages/environment/index.js b/pages/environment/index.js
index 6cc0655..483594d 100644
--- a/pages/environment/index.js
+++ b/pages/environment/index.js
@@ -9,7 +9,7 @@ export default {
Use environment variables
To access your Netlify environment variables in Edge Functions, use the Netlify.env API.
- import type { Context } from "https://edge.netlify.com/";
+ import type { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
const value = Netlify.env.get("MY_IMPORTANT_VARIABLE");
diff --git a/pages/geolocation/index.js b/pages/geolocation/index.js
index 58d5603..2768c46 100644
--- a/pages/geolocation/index.js
+++ b/pages/geolocation/index.js
@@ -22,7 +22,7 @@ export default {
Geolocation information is available on the Context.geo object.
- import { Context } from "https://edge.netlify.com/";
+ import { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
// Here's what's available on context.geo
diff --git a/pages/home/index.js b/pages/home/index.js
index 76a5165..0d4cd10 100644
--- a/pages/home/index.js
+++ b/pages/home/index.js
@@ -1,8 +1,9 @@
export default {
title: "Home",
- metaDescription: "Explore our library of Edge Function examples and deploy your own to Netlify.",
+ metaDescription:
+ "Explore our library of Edge Function examples and deploy your own to Netlify.",
page: function () {
- return /* html */`
+ return /* html */ `
Examples
@@ -26,19 +27,21 @@ export default {
Proxy requests to another source
-
+
- HTTP Headers
+ HTTP Headers and Methods
-
+
Transforming responses
diff --git a/pages/htmlrewriter/README.md b/pages/htmlrewriter/README.md
new file mode 100644
index 0000000..d5672e9
--- /dev/null
+++ b/pages/htmlrewriter/README.md
@@ -0,0 +1,66 @@
+
+
+# Transform HTML responses with Netlify Edge Functions and HTMLRewriter
+
+You can use Edge Functions with the HTMLRewriter library to transform HTML
+responses. HTMLRewriter uses WebAssembly to parse a response stream, so is very
+efficient. It can parse large HTML pages with minimal overhead, and is a better
+choice than using a string transform in most cases. It has an API that uses
+familiar CSS selectors to target elements, and can be used to add, remove, or
+modify elements.
+
+In this example, we transform an HTML page, replacing the `src` of `
` tags
+with a placeholder image. We also add content with the user's location. This
+shows how to do user personalization when the pages may be static.
+
+## Code example
+
+Edge Functions are files held in the `netlify/edge-functions` directory.
+
+```ts
+import { Config, Context } from "@netlify/edge-functions";
+import { HTMLRewriter } from "https://ghuc.cc/worker-tools/html-rewriter/index.ts";
+
+export default async function handler(request: Request, context: Context) {
+ const url = new URL(request.url);
+ // Only run if the `catify` query parameter is set
+ if (!url.searchParams.has("catify")) {
+ return;
+ }
+
+ const location = context?.geo?.city;
+
+ const response = await context.next();
+ const rewriter = new HTMLRewriter()
+ .on("#location", {
+ element: (element) => {
+ element.setInnerContent(`Catified for a visitor in ${location}`);
+ },
+ })
+ .on("img[catify]", {
+ element: (element) => {
+ const width = element.getAttribute("width") ?? 800;
+ const height = element.getAttribute("height") ?? 600;
+ element.setAttribute(
+ "src",
+ `https://placekitten.com/${width}/${height}`
+ );
+ element.setAttribute("alt", "A random cat");
+ },
+ });
+ return rewriter.transform(response);
+}
+```
+
+- [Explore the code for this Edge Function](../../netlify/edge-functions/htmlrewriter.ts)
+
+## View this example on the web
+
+- https://edge-functions-examples.netlify.app/example/htmlrewriter/
+
+## Deploy to Netlify
+
+You can deploy this and all the other examples in this repo as a site of your
+own to explore and experiment with, by clicking this button.
+
+[](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/edge-functions-examples&utm_campaign=devex&utm_source=edge-functions-examples&utm_medium=web&utm_content=Deploy%20Edge%20Functions%20Examples%20to%20Netlify)
diff --git a/pages/htmlrewriter/index.js b/pages/htmlrewriter/index.js
new file mode 100644
index 0000000..5295fcf
--- /dev/null
+++ b/pages/htmlrewriter/index.js
@@ -0,0 +1,67 @@
+import repoLink from "../../components/repo-link.js";
+
+export default {
+ title: "Transform HTML Response stream",
+ metaDescription: "Dynamically transform any HTML response at the edge.",
+ page: function () {
+ return /* html */ `
+
+ Transform HTML responses with Netlify Edge Functions and HTMLRewriter
+
+ You can use Edge Functions with the HTMLRewriter library to transform HTML
+ responses. HTMLRewriter uses WebAssembly to parse a response stream, so is very
+ efficient. It can parse large HTML pages with minimal overhead, and is a better
+ choice than using a string transform in most cases. It has an API that uses
+ familiar CSS selectors to target elements, and can be used to add, remove, or
+ modify elements.
+
+
+ In this example, we transform an HTML page, replacing the src of ![]()
tags
+ with a placeholder image. We also add content with the user's location. This
+ shows how to do user personalization when the pages may be static.
+
+
+ import { Config, Context } from "@netlify/edge-functions";
+import { HTMLRewriter } from "https://ghuc.cc/worker-tools/html-rewriter/index.ts";
+
+export default async function handler(request: Request, context: Context) {
+ const url = new URL(request.url);
+ // Only run if the catify query parameter is set
+ if (!url.searchParams.has("catify")) {
+ return;
+ }
+
+ const location = context?.geo?.city;
+
+ const response = await context.next();
+ const rewriter = new HTMLRewriter()
+ .on("#location", {
+ element: (element) => {
+ element.setInnerContent(\`Catified for a visitor in \${location}\`);
+ },
+ })
+ .on("img[catify]", {
+ element: (element) => {
+ const width = element.getAttribute("width") ?? 800;
+ const height = element.getAttribute("height") ?? 600;
+ element.setAttribute(
+ "src",
+ \`https://placekitten.com/\${width}/\${height}\`
+ );
+ element.setAttribute("alt", "A random cat");
+ },
+ });
+ return rewriter.transform(response);
+}
+
+
+ See this in action
+
+ - View the original response from /a-static-page without a transform
+ - View the response from /a-static-page dynamically transformed with a HTMLRewriter
+ - ${repoLink("htmlrewriter.ts")}
+
+
+ `;
+ },
+};
diff --git a/pages/image/index.js b/pages/image/index.js
index 9cc5321..a9c45f3 100644
--- a/pages/image/index.js
+++ b/pages/image/index.js
@@ -9,7 +9,7 @@ export default {
Image Response
You can use Edge Functions to return an image.
- import type { Context } from "https://edge.netlify.com/";
+ import type { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
diff --git a/pages/include/README.md b/pages/include/README.md
index 712c0e5..b26bd62 100644
--- a/pages/include/README.md
+++ b/pages/include/README.md
@@ -13,7 +13,7 @@ some other content.
Edge Functions are files held in the `netlify/edge-functions` directory.
```ts
-import { Context } from "https://edge.netlify.com/";
+import { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
// Get the page content
diff --git a/pages/include/index.js b/pages/include/index.js
index 651638d..da6d628 100644
--- a/pages/include/index.js
+++ b/pages/include/index.js
@@ -14,7 +14,7 @@ export default {
In this example, we look for an {{INCLUDE_PRICE_INFO}} placeholder in our response, and replace it with some other content.
- import { Context } from "https://edge.netlify.com/";
+ import { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
diff --git a/pages/json/README.md b/pages/json/README.md
index e33eaa4..16ec252 100644
--- a/pages/json/README.md
+++ b/pages/json/README.md
@@ -10,7 +10,7 @@ You can use Edge Functions to return a JSON response by returning `Response.json
Edge Functions are files held in the `netlify/edge-functions` directory.
```ts
-import type { Context } from "https://edge.netlify.com/";
+import type { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
return Response.json({ hello: "world" });
diff --git a/pages/json/index.js b/pages/json/index.js
index 35711bd..373e304 100644
--- a/pages/json/index.js
+++ b/pages/json/index.js
@@ -10,7 +10,7 @@ export default {
You can use Edge Functions to return a JSON response by returning Response.json() with a JavaScript object — no need to JSON.stringify!
In this example, we return a JSON object containing hello: "world".
- import type { Context } from "https://edge.netlify.com/";
+ import type { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
return Response.json({ hello: "world" });
diff --git a/pages/log/README.md b/pages/log/README.md
index 892bcd6..e888cd9 100644
--- a/pages/log/README.md
+++ b/pages/log/README.md
@@ -9,7 +9,7 @@ Output content to the logs from an Edge Function using `console.log()`.
Edge Functions are files held in the `netlify/edge-functions` directory.
```ts
-import type { Context } from "https://edge.netlify.com/";
+import type { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
console.log("Hello from the logging service");
diff --git a/pages/log/index.js b/pages/log/index.js
index b9878c1..9195afd 100644
--- a/pages/log/index.js
+++ b/pages/log/index.js
@@ -8,7 +8,7 @@ export default {
Logging with Edge Functions
You can output content to the logs during the execution of your Edge Function.
- import type { Context } from "https://edge.netlify.com/";
+ import type { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
console.log("Hello from the logging service");
diff --git a/pages/long-running/README.md b/pages/long-running/README.md
index 5807f96..8855c75 100644
--- a/pages/long-running/README.md
+++ b/pages/long-running/README.md
@@ -9,7 +9,7 @@ Edge Functions are limited to 50ms of CPU time, but this does not include time s
Edge Functions are files held in the `netlify/edge-functions` directory.
```ts
-import type { Context } from "https://edge.netlify.com/";
+import type { Context } from "@netlify/edge-functions";
export default (request: Request, context: Context) => {
const body = new ReadableStream({
diff --git a/pages/long-running/index.js b/pages/long-running/index.js
index 364ac7b..5632f14 100644
--- a/pages/long-running/index.js
+++ b/pages/long-running/index.js
@@ -13,7 +13,7 @@ export default {
from the function and write to it when you have the data.
- import type { Context } from "https://edge.netlify.com/";
+ import type { Context } from "@netlify/edge-functions";
export default (request: Request, context: Context) => {
const body = new ReadableStream({
diff --git a/pages/method/README.md b/pages/method/README.md
new file mode 100644
index 0000000..9e673de
--- /dev/null
+++ b/pages/method/README.md
@@ -0,0 +1,48 @@
+
+
+# Configure for specific HTTP methods
+
+With in-source configuration, you can restrict Edge Functions to respond to certain HTTP methods.
+
+## Code example
+
+Edge Functions are files held in the `netlify/edge-functions` directory.
+
+```ts
+import type { Config, Context } from "@netlify/edge-functions";
+
+export default async (request: Request, context: Context) => {
+
+ return new Response(`This is a response to a ${request.method} request`)
+};
+
+export const config: Config = {
+ method: ["POST", "PUT"]
+}
+```
+
+- [Explore the code for this Edge Function](../../netlify/edge-functions/method.ts)
+
+## View this example on the web
+
+- https://edge-functions-examples.netlify.app/example/method
+
+When viewed through a browser, the URL should 404. To validate that it works, you can use a CURL by running the following command in a terminal:
+
+```
+curl -X POST https://edge-functions-examples.netlify.app/example/method
+```
+
+or
+
+```
+curl -X PUT https://edge-functions-examples.netlify.app/example/method
+```
+
+
+## Deploy to Netlify
+
+You can deploy this and all the other examples in this repo as a site of your own to explore and experiment with, by
+clicking this button.
+
+[](https://app.netlify.com/start/deploy?repository=https://github.com/netlify/edge-functions-examples&utm_campaign=devex&utm_source=edge-functions-examples&utm_medium=web&utm_content=Deploy%20Edge%20Functions%20Examples%20to%20Netlify)
diff --git a/pages/method/index.js b/pages/method/index.js
new file mode 100644
index 0000000..544afd4
--- /dev/null
+++ b/pages/method/index.js
@@ -0,0 +1,39 @@
+import repoLink from "../../components/repo-link.js";
+
+export default {
+ title: "Configure for HTTP Methods",
+ metaDescription: "Configure Edge Functions to execute for certain HTTP methods.",
+ page: function() {
+ return `
+
+ Configure for specific HTTP methods
+
+ With in-source configuration, you can restrict Edge Functions to respond to certain HTTP methods.
+
+
+ In this example, we set up an Edge Function to execute for a PUT or POST request.
+
+
+ import type { Config, Context } from "@netlify/edge-functions";
+
+export default async (request: Request, context: Context) => {
+ return new Response(\`This is a response to a \${request.method}\`)
+};
+
+export const config: Config = {
+ method: ["POST", "PUT"]
+}
+ See this in action
+ Since the Edge Function is configured to respond to PUT and POST, accessing the Edge Function through a browser will result in a 404.
+
To validate that the Edge Function works, you can use cURL in your terminal:
+
+
curl -X POST https://edge-functions-examples.netlify.app/example/method
+
curl -X PUT https://edge-functions-examples.netlify.app/example/method
+
+
+ - ${repoLink("method.ts")}
+
+
+ `;
+ },
+};
diff --git a/pages/proxy-requests/README.md b/pages/proxy-requests/README.md
index 59cd0fc..5cc4851 100644
--- a/pages/proxy-requests/README.md
+++ b/pages/proxy-requests/README.md
@@ -10,7 +10,7 @@ Edge Function.
Edge Functions are files held in the `netlify/edge-functions` directory.
```ts
-import { Context } from "https://edge.netlify.com/";
+import { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
const joke = await fetch("https://github.com/service/https://icanhazdadjoke.com/", {
diff --git a/pages/proxy-requests/index.js b/pages/proxy-requests/index.js
index bd7ffff..95334e8 100644
--- a/pages/proxy-requests/index.js
+++ b/pages/proxy-requests/index.js
@@ -8,7 +8,7 @@ export default {
Proxy requests to another source
You can use fetch() to make requests to other sources via an Edge Function.
- import { Context } from "https://edge.netlify.com/";
+ import { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
diff --git a/pages/rewrite/README.md b/pages/rewrite/README.md
index 94406de..7c31cbc 100644
--- a/pages/rewrite/README.md
+++ b/pages/rewrite/README.md
@@ -9,7 +9,7 @@ You can rewrite requests on one URL to resources available on another URL using
Edge Functions are files held in the `netlify/edge-functions` directory.
```ts
-import type { Context } from "https://edge.netlify.com/";
+import type { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
return new URL("/something-to-serve-with-a-rewrite", request.url);
diff --git a/pages/rewrite/index.js b/pages/rewrite/index.js
index 2c7e227..f9fc7b7 100644
--- a/pages/rewrite/index.js
+++ b/pages/rewrite/index.js
@@ -8,7 +8,7 @@ export default {
Rewrite with Edge Functions
You can rewrite requests on one URL to resources available on another URL using an Edge Function.
- import type { Context } from "https://edge.netlify.com/";
+ import type { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
return new URL("/something-to-serve-with-a-rewrite", request.url);
diff --git a/pages/server-sent-events/README.md b/pages/server-sent-events/README.md
index 654e14d..2d9260b 100644
--- a/pages/server-sent-events/README.md
+++ b/pages/server-sent-events/README.md
@@ -9,7 +9,7 @@ You can use Edge Functions to create a long-running service that can stream data
Edge Functions are files held in the `netlify/edge-functions` directory.
```ts
-import type { Context } from "https://edge.netlify.com/";
+import type { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
let index = 0
diff --git a/pages/server-sent-events/index.js b/pages/server-sent-events/index.js
index 0cffbaf..4a3bdb2 100644
--- a/pages/server-sent-events/index.js
+++ b/pages/server-sent-events/index.js
@@ -12,7 +12,7 @@ export default {
This means you can create a long-running service that can stream data to the browser.
- import type { Context } from "https://edge.netlify.com/";
+ import type { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
let index = 0
diff --git a/pages/set-request-header/README.md b/pages/set-request-header/README.md
index 6089798..148ace1 100644
--- a/pages/set-request-header/README.md
+++ b/pages/set-request-header/README.md
@@ -9,7 +9,7 @@ Use an Edge Function to add HTTP headers to any HTTP request at The Edge.
Edge Functions are files held in the `netlify/edge-functions` directory.
```ts
-import type { Context } from "https://edge.netlify.com/";
+import type { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
const response = await context.next();
diff --git a/pages/set-request-header/index.js b/pages/set-request-header/index.js
index 3d4d37e..84fead2 100644
--- a/pages/set-request-header/index.js
+++ b/pages/set-request-header/index.js
@@ -8,7 +8,7 @@ export default {
Set custom HTTP request headers with an Edge Function
Use an Edge Function to add HTTP headers to any HTTP request.
- import type { Context } from "https://edge.netlify.com/";
+ import type { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
request.headers.set("X-Your-Custom-Header", "Your custom header value");
diff --git a/pages/set-response-header/README.md b/pages/set-response-header/README.md
index c8f9b8c..383c13c 100644
--- a/pages/set-response-header/README.md
+++ b/pages/set-response-header/README.md
@@ -9,7 +9,7 @@ Use an Edge Function to add HTTP headers to any HTTP response at The Edge.
Edge Functions are files held in the `netlify/edge-functions` directory.
```ts
-import type { Context } from "https://edge.netlify.com/";
+import type { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
const response = await context.next();
diff --git a/pages/set-response-header/index.js b/pages/set-response-header/index.js
index 7d5b367..e689e06 100644
--- a/pages/set-response-header/index.js
+++ b/pages/set-response-header/index.js
@@ -8,7 +8,7 @@ export default {
Set custom HTTP response headers with an Edge Function
Use an Edge Function to add HTTP headers to any HTTP response.
- import type { Context } from "https://edge.netlify.com/";
+ import type { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
const response = await context.next();
diff --git a/pages/transform/README.md b/pages/transform/README.md
index 1a77f4a..de9405e 100644
--- a/pages/transform/README.md
+++ b/pages/transform/README.md
@@ -11,7 +11,7 @@ request to `/hello` with JavaScript's toUpperCase() function, using
Edge Functions are files held in the `netlify/edge-functions` directory.
```ts
-import { Context } from "https://edge.netlify.com/";
+import { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
const url = new URL(request.url);
diff --git a/pages/transform/index.js b/pages/transform/index.js
index 0e6eaf7..f1ff79f 100644
--- a/pages/transform/index.js
+++ b/pages/transform/index.js
@@ -10,8 +10,10 @@ export default {
You can use Edge Functions to transform the content of an HTTP response. In this example, we transform the response of a request to /hello with a toUpperCase() function, using the query parameter method=transform.
+ This is a simple example, and for more complex transformations you may want to use HTMLRewriter.
+
- import { Context } from "https://edge.netlify.com/";
+ import { Context } from "@netlify/edge-functions";
export default async (request: Request, context: Context) => {
const url = new URL(request.url);
@@ -27,11 +29,8 @@ export default async (request: Request, context: Context) => {
};
- This transform Edge Function is set up to run using the method=transform query parameter on any URL, using this entry in the netlify.toml file:
+ This transform Edge Function is set up to run using the method=transform query parameter on any URL
- [[edge_functions]]
- function = "transform"
- path = "/*"
See this in action
- View the original response from /hello without a transform
diff --git a/public/a-static-page.html b/public/a-static-page.html
new file mode 100644
index 0000000..3806c9d
--- /dev/null
+++ b/public/a-static-page.html
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+ Catify
+
+
+
+
+ A static page
+
+ Catify me
+
+
+
+
+
+
\ No newline at end of file