Initial commit.
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
import Elementary
|
||||
import Foundation
|
||||
import Hummingbird
|
||||
|
||||
/// Serves a custom error page for requests that match neither a route nor a static file.
|
||||
///
|
||||
/// Placed ahead of `FileMiddleware` in the middleware chain, it catches the `.notFound` error that bubbles up when no file exists for the requested
|
||||
/// path and responds with the rendered error page and a `404 Not Found` status. The page is served in the language stored on the context by
|
||||
/// ``LocalizationMiddleware``, falling back to the default language.
|
||||
public struct NotFoundMiddleware<Context: LocalizedRequestContext> {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
/// The error page, rendered once per supported language and reused for every not-found response.
|
||||
private let responses: LocalizedHTMLCollectionResponse
|
||||
|
||||
// MARK: Initializers
|
||||
|
||||
/// Creates a not-found middleware.
|
||||
/// - Parameters:
|
||||
/// - bundle: the bundle whose String Catalog names the languages the page is rendered for.
|
||||
/// - document: builds the error page to render for a given locale.
|
||||
public init<Document: HTMLDocument>(
|
||||
bundle: Bundle,
|
||||
document: (Locale) -> Document
|
||||
) {
|
||||
self.responses = .init(
|
||||
bundle: bundle,
|
||||
status: .notFound,
|
||||
document: document
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: - RouterMiddleware
|
||||
|
||||
extension NotFoundMiddleware: RouterMiddleware {
|
||||
|
||||
// MARK: Functions
|
||||
|
||||
/// Passes the request down the chain, rendering the error page if it results in a not-found response.
|
||||
///
|
||||
/// Any error other than `.notFound` is rethrown unchanged.
|
||||
/// - Parameters:
|
||||
/// - request: the incoming request.
|
||||
/// - context: the context the request is resolved against.
|
||||
/// - next: the next responder in the middleware chain.
|
||||
/// - Returns: the downstream response, or the rendered error page with a `404 Not Found` status.
|
||||
/// - Throws: any non-not-found error thrown downstream.
|
||||
public func handle(
|
||||
_ request: Request,
|
||||
context: Context,
|
||||
next: (Request, Context) async throws -> Response
|
||||
) async throws -> Response {
|
||||
do {
|
||||
return try await next(request, context)
|
||||
}
|
||||
catch let error {
|
||||
guard
|
||||
let responseError = error as? any HTTPResponseError,
|
||||
responseError.status == .notFound
|
||||
else {
|
||||
throw error
|
||||
}
|
||||
|
||||
return responses.response(
|
||||
for: context.language,
|
||||
request: request
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user