Implemented phase 2 for the POC prototype in the Website service.
This commit is contained in:
1 parent
09c7b8a1a7
commit
43dcc03da6
28 files changed
+1468
-65
No files matched your search
@@ -1,5 +1,6 @@
|
||||
import Foundation
|
||||
import Hummingbird
|
||||
import HummingbirdElementary
|
||||
import Infrastructure
|
||||
import Localization
|
||||
|
||||
@@ -18,6 +19,12 @@ public struct RootController<Context: RequestContext> {
|
||||
|
||||
// MARK: Properties
|
||||
|
||||
/// What a page rendered per request is built from, the same as the cached ones.
|
||||
private let page: @Sendable (Locale, Viewer?) -> IndexPage
|
||||
|
||||
/// The store the signed-in viewer is read from, or `nil` to serve everyone the cached page.
|
||||
private let sessions: SessionStore?
|
||||
|
||||
/// Negotiates the language the bare route answers in.
|
||||
private let negotiate: Negotiate
|
||||
|
||||
@@ -32,26 +39,35 @@ public struct RootController<Context: RequestContext> {
|
||||
/// - siteOrigin: the public origin the page derives its canonical URL and language alternates from, or `nil` (the default) to omit them.
|
||||
/// - analytics: the analytics tracker the landing page embeds, or `nil` (the default) to omit it.
|
||||
/// - listings: the listings the landing page shows in its rows; none by default.
|
||||
/// - sessions: the store the signed-in viewer is read from, or `nil` (the default) to serve everyone the cached page.
|
||||
public init(
|
||||
assetVersion: String? = nil,
|
||||
siteOrigin: String? = nil,
|
||||
analytics: Analytics? = nil,
|
||||
listings: HomeListings = .init()
|
||||
listings: HomeListings = .init(),
|
||||
sessions: SessionStore? = nil
|
||||
) {
|
||||
let page: @Sendable (Locale, Viewer?) -> IndexPage = {
|
||||
.init(
|
||||
locale: $0,
|
||||
assetVersion: assetVersion,
|
||||
siteOrigin: siteOrigin,
|
||||
analytics: analytics,
|
||||
listings: listings,
|
||||
viewer: $1
|
||||
)
|
||||
}
|
||||
|
||||
self.negotiate = .init(bundle: .module)
|
||||
self.page = page
|
||||
self.sessions = sessions
|
||||
// The bare route negotiates, so the pages declare `Vary: Accept-Language`; the prefixed editions share the cache
|
||||
// and carry it too.
|
||||
self.responses = .init(
|
||||
bundle: .module,
|
||||
variesOnAcceptLanguage: true
|
||||
) {
|
||||
IndexPage(
|
||||
locale: $0,
|
||||
assetVersion: assetVersion,
|
||||
siteOrigin: siteOrigin,
|
||||
analytics: analytics,
|
||||
listings: listings
|
||||
)
|
||||
page($0, nil)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,10 +119,11 @@ private extension RootController {
|
||||
func index(
|
||||
request: Request,
|
||||
context: Context
|
||||
) -> Response {
|
||||
responses.response(
|
||||
for: negotiate(for: request),
|
||||
request: request
|
||||
) async -> Response {
|
||||
await respond(
|
||||
in: negotiate(for: request),
|
||||
request: request,
|
||||
context: context
|
||||
)
|
||||
}
|
||||
|
||||
@@ -118,13 +135,37 @@ private extension RootController {
|
||||
/// - Returns: the handler answering requests for that edition of the page.
|
||||
func index(
|
||||
in language: Language
|
||||
) -> @Sendable (Request, Context) -> Response {
|
||||
{ request, _ in
|
||||
responses.response(
|
||||
for: language.identifier,
|
||||
) -> @Sendable (Request, Context) async -> Response {
|
||||
{ request, context in
|
||||
await respond(
|
||||
in: language.identifier,
|
||||
request: request,
|
||||
context: context
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Answers with the landing page in the given language: the cached page signed out, and one rendered around the viewer signed in.
|
||||
/// - Parameters:
|
||||
/// - language: the identifier of the language to answer in.
|
||||
/// - request: the incoming request.
|
||||
/// - context: the context the request is resolved against.
|
||||
func respond(
|
||||
in language: String,
|
||||
request: Request,
|
||||
context: Context
|
||||
) async -> Response {
|
||||
guard let viewer = await sessions?.viewer(for: request) else {
|
||||
return responses.response(
|
||||
for: language,
|
||||
request: request
|
||||
)
|
||||
}
|
||||
|
||||
return HTMLResponse(additionalHeaders: .perViewer) { [page] in
|
||||
page(.init(identifier: language), viewer)
|
||||
}
|
||||
.response(from: request, context: context)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user