Middleware

Middleware allows you to transform and modify HTTP requests and responses as they flow through bunny.net's network. By using middleware functions, you can manipulate the request before it reaches your origin server and alter the response before it is sent back to the client.

This provides powerful capabilities for customizing behavior, implementing access control, injecting headers, and more.

Workflow

When a client makes a request to a Pull Zone in Bunny.net, the request can pass through middleware functions at different stages:

  • onOriginRequest: This function is called before the request is sent to the origin server. You can modify the request or even short-circuit the process by returning a response directly.
  • onOriginResponse: This function is called after the origin server responds but before the response is sent back to the client. You can modify the response here, such as altering headers or content.

Example Script

Below is an example script demonstrating how to use middleware functions to implement access control based on custom headers:

import * as BunnySDK from "https://esm.sh/@bunny.net/[email protected]";

// The url defined here is only effective with local scripts, when you deploy in
// production it'll be the `Origin` from your PullZone that is going to be used.
BunnySDK.net.http.servePullZone({ url: "https://echo.free.beeceptor.com/" })
  .onOriginRequest(
    (ctx: { request: Request }) => {
      const optFT = ctx.request.headers.get("feature-flags");
      const featureFlags = optFT ? optFT.split(",").map((v) => v.trimStart()) : [];


      // Route-based matching and feature flag check
      const path = new URL(ctx.request.url).pathname;
      if (path === "/d") {
        if (!featureFlags.includes("route-d-preview")) {
          return Promise.resolve(new Response("You cannot use this route.", { status: 400 }));
        }
      }

      return Promise.resolve(ctx.request);
    },
  ).onOriginResponse((ctx: { request: Request, response: Response }) => {
    const response = ctx.response;
    response.headers.append("X-Via", "MyMiddleware");

    return Promise.resolve(response);
  });

You can run this example locally using Deno deno run -A script.ts :

# Disallowed
curl
http://127.0.0.1:8080/d --header
'feature-flags: something-else'


# Allowed
curl
http://127.0.0.1:8080/d --header
'feature-flags: route-d-preview, something-else'

In the example above, the script sets up a Pull Zone server using Bunny.net's Edge Script SDK. It defines two middleware functions: onOriginRequest and onOriginResponse.

The onOriginRequest function checks if the incoming request to the /d route includes a specific feature flag in the feature-flags header. If the feature flag is missing, it returns a 400 Bad Request response, effectively blocking access to that route. This function allows you to implement custom access control logic based on headers or other request properties.

The onOriginResponse function appends a custom header X-Via: MyMiddleware to the response before it's sent back to the client. This can be useful for adding metadata or for debugging purposes.

Testing the Middleware

To test the middleware, you can use the following curl commands.
For a disallowed request (missing the required feature flag):

curl http://127.0.0.1:8080/d --header 'feature-flags: something-else'

This request will receive a 400 Bad Request response with the message "You cannot use this route."
For an allowed request (includes the required feature flag):

curl http://127.0.0.1:8080/d --header 'feature-flags: route-d-preview, something-else'

This request will proceed to the origin server, and the response will include the X-Via: MyMiddleware header.

Middleware Functions

onOriginRequest

The onOriginRequest function adds a middleware function that intercepts every request going to the origin server. If the response is not cached or not served directly by the Pull Zone, this function will be called before the request is sent to the origin.
You can use this function to modify the request, implement access control, or even short-circuit the request by returning a response directly.

Signature:

declare const onOriginRequest: (middleware: { request: Request }) => Promise<Request> | Promise<Response>

onOriginResponse

The onOriginResponse function adds a middleware function that intercepts the response from the origin server before it is sent back to the client. This function is called only when the response is not cached or served directly by the Pull Zone.
You can use this function to modify the response, such as altering headers, status codes, or even the body content.

Signature :

declare const onOriginRequest: (middleware: { request: Request, response:
Response }) => Promise<Response>

Both middleware functions can perform asynchronous operations as they return Promises. In onOriginRequest, returning a response directly allows you to short-circuit the request, preventing it from reaching the origin server. Modifications in onOriginResponse occur before the response is cached, allowing you to control what gets stored in the cache.