This commit contains the latest updates from the generic Website template, which move the toolchain to Swift 6.4, gate analytics and structured data behind traits, and rework page routing: - Updated the Swift toolchain for all the package dependencies and the Website service to version 6.4. (345b305) - Adapted all the existing middlewares in the Infrastructure package to Swift 6.4. (26008df) - Moved test resource teardown in the Persistence and the Website library into defer blocks. (27984a9) - Gated analytics behind a trait and reworked structured data in the Infrastructure package. (c7d4769) - Enabled the Analytics trait in the Website service. (f6a6bbd) - Reworked page routing in the Website service. (d1cb2c1) - Gated the structured data features in the Infrastructure package behind a trait. (f0a8791) - Enabled the StructuredData trait of the Infrastructure package in the Website service. (bbfdeb3) - Fixed the asset pin and a build warning in the Dockerfile of the Website service. (6ed0f9b) The root README change in 345b305 was left out, as this project no longer carries that file. From d1cb2c1, the RootController rework was left out, as the prototype serves a session-aware landing page and routes its other pages through their own controllers; the view-event reporter was appended to the prototype's shared script instead. The prototype code was adapted to the stricter Swift 6.4 settings: `String(format:)` was swapped for safe formatting, the NoIndex middleware takes a `@concurrent` next handler, and the tests flagged by warnings-as-errors were tightened. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
72 lines
2.4 KiB
Swift
72 lines
2.4 KiB
Swift
import Foundation
|
|
import HTTPTypes
|
|
import Hummingbird
|
|
|
|
/// Appends header names to the `Vary` header of every response passing through.
|
|
///
|
|
/// Placed just above the response-compression middleware, it marks each response as varying on `Accept-Encoding`: the static files and pre-rendered
|
|
/// pages are served with `Cache-Control: public`, so without the signal a shared cache could store a compressed body and hand it to a client that
|
|
/// never advertised support for the encoding.
|
|
///
|
|
/// Names already present on a response's `Vary` header — such as the `Accept-Language` the localized pages carry — are kept, and duplicates are not
|
|
/// added.
|
|
public struct VaryMiddleware<Context: RequestContext>: Sendable {
|
|
|
|
// MARK: Properties
|
|
|
|
/// The header names appended to every response's `Vary` header.
|
|
private let names: [String]
|
|
|
|
// MARK: Initializers
|
|
|
|
/// Creates a vary middleware.
|
|
/// - Parameter fields: the header names appended to every response's `Vary` header. Defaults to `Accept-Encoding`, the request header
|
|
/// the response-compression middleware acts on.
|
|
public init(
|
|
fields: [HTTPField.Name] = [.acceptEncoding]
|
|
) {
|
|
self.names = fields.map(\.rawName)
|
|
}
|
|
|
|
}
|
|
|
|
// MARK: - RouterMiddleware
|
|
|
|
extension VaryMiddleware: RouterMiddleware {
|
|
|
|
// MARK: Functions
|
|
|
|
/// Passes the request down the chain and appends the configured names to the response's `Vary` header on the way back up.
|
|
/// - 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 with the `Vary` names applied.
|
|
/// - Throws: any error thrown downstream.
|
|
public func handle(
|
|
_ request: Request,
|
|
context: Context,
|
|
next: @concurrent (Request, Context) async throws -> Response
|
|
) async throws -> Response {
|
|
var response = try await next(
|
|
request,
|
|
context
|
|
)
|
|
|
|
var vary = response.headers[.vary]?
|
|
.split(separator: ",")
|
|
.map { $0.trimmingCharacters(in: .whitespaces) } ?? []
|
|
|
|
for name in names where !vary.contains(where: {
|
|
$0.caseInsensitiveCompare(name) == .orderedSame
|
|
}) {
|
|
vary.append(name)
|
|
}
|
|
|
|
response.headers[.vary] = vary.joined(separator: ", ")
|
|
|
|
return response
|
|
}
|
|
|
|
}
|