-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor single middleware function into multiple functions that get …
…chained together (#671)
- Loading branch information
Showing
11 changed files
with
187 additions
and
79 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { NextRequest, NextResponse } from "next/server"; | ||
|
||
import { CustomMiddleware } from "./chain"; | ||
|
||
export function withAdminRedirectMiddleware(middleware: CustomMiddleware) { | ||
return async (request: NextRequest) => { | ||
if (request.nextUrl.pathname === "/admin" && process.env.ADMIN_URL) { | ||
return NextResponse.redirect(new URL(process.env.ADMIN_URL)); | ||
} | ||
return middleware(request); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import type { NextRequest } from "next/server"; | ||
import { NextResponse } from "next/server"; | ||
|
||
export type CustomMiddleware = (request: NextRequest) => NextResponse | Response | Promise<NextResponse | Response>; | ||
|
||
type MiddlewareFactory = (middleware: CustomMiddleware) => CustomMiddleware; | ||
// Utility function to chain multiple middlewares together | ||
export function chain(functions: MiddlewareFactory[], index = 0): CustomMiddleware { | ||
const current = functions[index]; | ||
|
||
if (current) { | ||
const next = chain(functions, index + 1); | ||
return current(next); | ||
} | ||
|
||
return () => NextResponse.next(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { NextRequest } from "next/server"; | ||
|
||
import { CustomMiddleware } from "./chain"; | ||
|
||
export function withContentSecurityPolicyHeadersMiddleware(middleware: CustomMiddleware) { | ||
return async (request: NextRequest) => { | ||
const response = await middleware(request); | ||
response.headers.set( | ||
"Content-Security-Policy", | ||
` | ||
default-src 'self'; | ||
form-action 'self'; | ||
object-src 'none'; | ||
img-src 'self' https: data:${process.env.NODE_ENV === "development" ? " http:" : ""}; | ||
media-src 'self' https: data:${process.env.NODE_ENV === "development" ? " http:" : ""}; | ||
style-src 'self' 'unsafe-inline'; | ||
font-src 'self' https: data:; | ||
script-src 'self' 'unsafe-inline' https:${process.env.NODE_ENV === "development" ? " 'unsafe-eval'" : ""}; | ||
connect-src 'self' https:${process.env.NODE_ENV === "development" ? " http:" : ""}; | ||
frame-ancestors ${process.env.ADMIN_URL ?? "none"}; | ||
upgrade-insecure-requests; | ||
block-all-mixed-content; | ||
frame-src 'self' https://*.youtube.com https://*.youtube-nocookie.com; | ||
` | ||
.replace(/\s{2,}/g, " ") | ||
.trim(), | ||
); | ||
if (process.env.ADMIN_URL) { | ||
response.headers.set("Access-Control-Allow-Origin", process.env.ADMIN_URL); | ||
} | ||
|
||
return response; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { NextRequest, NextResponse } from "next/server"; | ||
|
||
import { CustomMiddleware } from "./chain"; | ||
|
||
export function withDamRewriteMiddleware(middleware: CustomMiddleware) { | ||
return async (request: NextRequest) => { | ||
if (request.nextUrl.pathname.startsWith("/dam/")) { | ||
return NextResponse.rewrite(new URL(`${process.env.API_URL_INTERNAL}${request.nextUrl.pathname}`)); | ||
} | ||
return middleware(request); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { getHostByHeaders, getSiteConfigForHost } from "@src/util/siteConfig"; | ||
import { NextRequest, NextResponse } from "next/server"; | ||
|
||
import { CustomMiddleware } from "./chain"; | ||
|
||
/** | ||
* Rewrite request to include the matching domain (from http host) in the path, so the route can have [domain] as parameter. | ||
* | ||
* Doing this matching in the middleware makes it possible to keep static rendering, as the page doesn't need headers() to get the domain. | ||
*/ | ||
export function withDomainRewriteMiddleware(middleware: CustomMiddleware) { | ||
return async (request: NextRequest) => { | ||
const headers = request.headers; | ||
const host = getHostByHeaders(headers); | ||
const siteConfig = await getSiteConfigForHost(host); | ||
if (!siteConfig) { | ||
throw new Error(`Cannot get siteConfig for host ${host}`); | ||
} | ||
return NextResponse.rewrite( | ||
new URL( | ||
`/${siteConfig.scope.domain}${request.nextUrl.pathname}${ | ||
request.nextUrl.searchParams.toString().length > 0 ? `?${request.nextUrl.searchParams.toString()}` : "" | ||
}`, | ||
request.url, | ||
), | ||
{ request: { headers } }, | ||
); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { NextRequest, NextResponse } from "next/server"; | ||
|
||
import { CustomMiddleware } from "./chain"; | ||
|
||
/** | ||
* /block-preview/* and /site-preview must not use the domain rewrite, because we don't have a active domain. This middleware exists the chain in that case. | ||
*/ | ||
export function withPreviewMiddleware(middleware: CustomMiddleware) { | ||
return async (request: NextRequest) => { | ||
if (request.nextUrl.pathname.startsWith("/block-preview/") || request.nextUrl.pathname === "/site-preview") { | ||
// don't apply any other middlewares | ||
return NextResponse.next(); | ||
} | ||
return middleware(request); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import { getHostByHeaders, getSiteConfigForHost, getSiteConfigs } from "@src/util/siteConfig"; | ||
import { NextRequest, NextResponse } from "next/server"; | ||
|
||
import { CustomMiddleware } from "./chain"; | ||
|
||
/** | ||
* When http host isn't siteConfig.domains.main (instead .pattern or .additional match), redirect to main host. | ||
*/ | ||
export function withRedirectToMainHostMiddleware(middleware: CustomMiddleware) { | ||
return async (request: NextRequest) => { | ||
const headers = request.headers; | ||
const host = getHostByHeaders(headers); | ||
const siteConfig = await getSiteConfigForHost(host); | ||
|
||
if (!siteConfig) { | ||
// Redirect to Main Host | ||
const redirectSiteConfig = getSiteConfigs().find( | ||
(siteConfig) => | ||
siteConfig.domains.additional?.includes(host) || | ||
(siteConfig.domains.pattern && host.match(new RegExp(siteConfig.domains.pattern))), | ||
); | ||
if (redirectSiteConfig) { | ||
return NextResponse.redirect(redirectSiteConfig.url); | ||
} | ||
|
||
throw new Error(`Cannot get siteConfig for host ${host}`); | ||
} | ||
return middleware(request); | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { getHostByHeaders, getSiteConfigForHost } from "@src/util/siteConfig"; | ||
import { NextRequest, NextResponse } from "next/server"; | ||
|
||
import { CustomMiddleware } from "./chain"; | ||
|
||
/** | ||
* Verify when on site preview domain, a siteConfig exists (by scope set as cookie) | ||
*/ | ||
export function withSitePreviewMiddleware(middleware: CustomMiddleware) { | ||
return async (request: NextRequest) => { | ||
const host = getHostByHeaders(request.headers); | ||
const siteConfig = await getSiteConfigForHost(host); | ||
if (!siteConfig && host === process.env.PREVIEW_DOMAIN) { | ||
return NextResponse.json({ error: "Preview has to be called from within Comet Web preview" }, { status: 404 }); | ||
} | ||
return middleware(request); | ||
}; | ||
} |
This file was deleted.
Oops, something went wrong.