in Sources/SwiftDocCUtilities/PreviewServer/PreviewHTTPHandler.swift [80:135]
func channelRead(context: ChannelHandlerContext, data: NIOAny) {
let requestPart = unwrapInboundIn(data)
switch (requestPart, state) {
case (.head(let head), _):
let handler: RequestHandlerFactory
if FileRequestHandler.isAssetPath(head.uri) {
// Serve a static asset file.
handler = FileRequestHandler(rootURL: rootURL, fileIO: fileIO)
} else {
// Serve the fallback index file.
handler = DefaultRequestHandler(rootURL: rootURL)
}
state = .requestInProgress(requestHead: head, handler: handler.create(channelHandler: self))
case (.end, .requestInProgress(let head, let handler)):
// In case the handler was initialized with user credentials,
// do verify they match the sent "Authorization" header
if let credentials = credentials {
// Verify the user sent credentials over via the HTTP headers
let authorizationHeaders = head.headers["Authorization"]
guard !authorizationHeaders.isEmpty else {
error(context: context, requestPart: requestPart, head: head, status: .unauthorized, headers: [("WWW-Authenticate", "Basic realm=\"Preview server\"")])
return
}
let credentialsToken = [credentials.user, credentials.pass].joined(separator: ":")
.data(using: .utf8)!.base64EncodedString()
guard authorizationHeaders[0] == "Basic \(credentialsToken)" else {
error(context: context, requestPart: requestPart, head: head, status: .forbidden)
return
}
}
defer {
// Complete the response to the client, reset ``state``
completeResponse(context, trailers: nil, promise: nil)
}
// Call the pre-defined during the `head` context handler.
do {
try handler(context, head)
} catch {
let errorHandler = ErrorRequestHandler(error: error as? RequestError)
.create(channelHandler: self)
// The error handler will never throw.
try! errorHandler(context, head)
}
// Ignore other parts of a request, e.g. POST data or others.
default: break
}
}