|
1 | 1 | import { NextResponse } from 'next/server'
|
2 |
| -import { NextFetchEvent, NextRequest } from 'next/server' |
| 2 | +import type { NextRequest } from 'next/server' |
3 | 3 |
|
4 |
| -export function middleware(request: NextRequest, ev: NextFetchEvent) { |
| 4 | +/** |
| 5 | + * Supercharge your Next middleware with Netlify Edge Functions |
| 6 | + */ |
| 7 | +class NetlifyResponse { |
| 8 | + static async next(request: NextRequest): Promise<NetlifyNextResponse> { |
| 9 | + const context = (request.geo as any).__nf_context |
| 10 | + if (!context) { |
| 11 | + throw new Error('NetlifyResponse can only be used with Netlify Edge Functions') |
| 12 | + } |
| 13 | + const response: Response = await context.next() |
| 14 | + return new NetlifyNextResponse(response) |
| 15 | + } |
| 16 | +} |
| 17 | + |
| 18 | +type NextDataTransform = <T extends Record<string, any>>(props: T) => T |
| 19 | + |
| 20 | +// A NextReponse that will pass through the Netlify origin response |
| 21 | +// We can't pass it through directly, because Next disallows returning a response body |
| 22 | +class NetlifyNextResponse extends NextResponse { |
| 23 | + private originResponse: Response |
| 24 | + private transforms: NextDataTransform[] |
| 25 | + constructor(originResponse: Response) { |
| 26 | + super() |
| 27 | + this.originResponse = originResponse |
| 28 | + Object.defineProperty(this, 'transforms', { |
| 29 | + value: [], |
| 30 | + enumerable: false, |
| 31 | + writable: false, |
| 32 | + }) |
| 33 | + } |
| 34 | + |
| 35 | + /** |
| 36 | + * Transform the page props before they are passed to the client. |
| 37 | + * This works for both HTML pages and JSON data |
| 38 | + */ |
| 39 | + transformData(transform: NextDataTransform) { |
| 40 | + // The transforms are evaluated after the middleware is returned |
| 41 | + this.transforms.push(transform) |
| 42 | + } |
| 43 | + get headers(): Headers { |
| 44 | + // If we have the origin response, we should use its headers |
| 45 | + return this.originResponse?.headers || super.headers |
| 46 | + } |
| 47 | +} |
| 48 | + |
| 49 | +export async function middleware(request: NextRequest) { |
5 | 50 | let response
|
6 | 51 | const {
|
7 | 52 | nextUrl: { pathname },
|
8 | 53 | } = request
|
9 | 54 |
|
| 55 | + if (pathname.startsWith('/static')) { |
| 56 | + // Unlike NextResponse.next(), this actually sends the request to the origin |
| 57 | + const res = await NetlifyResponse.next(request) |
| 58 | + res.transformData((data) => { |
| 59 | + data.pageProps.message = `This was static but has been transformed in ${request.geo.country}` |
| 60 | + return data |
| 61 | + }) |
| 62 | + |
| 63 | + return res |
| 64 | + } |
| 65 | + |
10 | 66 | if (pathname.startsWith('/cookies')) {
|
11 | 67 | response = NextResponse.next()
|
12 | 68 | response.cookies.set('netlifyCookie', 'true')
|
|
0 commit comments