-
-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use a response writer at the Server level (#519)
* Use a response writer at the server level * Comments, rename symbols * Update Sources/HummingbirdCore/Response/ResponseWriter.swift Co-authored-by: Joannis Orlandos <[email protected]> * ResponseWriter second attempt ResponseWriter returns a ResponseBodyWriter when headers are written. * Comments * Make ResponseWriter non Copyable * Update Sources/HummingbirdCore/Response/ResponseWriter.swift Co-authored-by: Joannis Orlandos <[email protected]> * Fix trailing headers, by requiring user to finish ResponseBodyWriter * comments * formatting --------- Co-authored-by: Joannis Orlandos <[email protected]>
- Loading branch information
1 parent
e8d7a49
commit 80fd368
Showing
12 changed files
with
258 additions
and
128 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
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,88 @@ | ||
//===----------------------------------------------------------------------===// | ||
// | ||
// This source file is part of the Hummingbird server framework project | ||
// | ||
// Copyright (c) 2024 the Hummingbird authors | ||
// Licensed under Apache License v2.0 | ||
// | ||
// See LICENSE.txt for license information | ||
// See hummingbird/CONTRIBUTORS.txt for the list of Hummingbird authors | ||
// | ||
// SPDX-License-Identifier: Apache-2.0 | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
import HTTPTypes | ||
import NIOCore | ||
import NIOHTTPTypes | ||
|
||
/// ResponseWriter that writes directly to AsyncChannel | ||
public struct ResponseWriter: ~Copyable { | ||
@usableFromInline | ||
let outbound: NIOAsyncChannelOutboundWriter<HTTPResponsePart> | ||
|
||
/// Write HTTP head part and return ``ResponseBodyWriter`` to write response body | ||
/// | ||
/// - Parameter head: Response head | ||
/// - Returns: Response body writer used to write HTTP response body | ||
@inlinable | ||
public consuming func writeHead(_ head: HTTPResponse) async throws -> some ResponseBodyWriter { | ||
try await self.outbound.write(.head(head)) | ||
return RootResponseBodyWriter(outbound: self.outbound) | ||
} | ||
|
||
/// Write Informational HTTP head part | ||
/// | ||
/// Calling this with a non informational HTTP response head will cause a precondition error | ||
/// - Parameter head: Informational response head | ||
@inlinable | ||
public func writeInformationalHead(_ head: HTTPResponse) async throws { | ||
precondition((100..<200).contains(head.status.code), "Informational HTTP responses require a status code in the range of 100 through 199") | ||
try await self.outbound.write(.head(head)) | ||
} | ||
|
||
/// Write full HTTP response that doesn't include a body | ||
/// | ||
/// - Parameter head: Response head | ||
@inlinable | ||
public consuming func writeResponse(_ head: HTTPResponse) async throws { | ||
try await self.outbound.write(contentsOf: [.head(head), .end(nil)]) | ||
} | ||
} | ||
|
||
/// ResponseBodyWriter that writes ByteBuffers to AsyncChannel outbound writer | ||
@usableFromInline | ||
struct RootResponseBodyWriter: Sendable, ResponseBodyWriter { | ||
typealias Out = HTTPResponsePart | ||
/// The components of a HTTP response from the view of a HTTP server. | ||
public typealias OutboundWriter = NIOAsyncChannelOutboundWriter<Out> | ||
|
||
@usableFromInline | ||
let outbound: OutboundWriter | ||
|
||
@usableFromInline | ||
init(outbound: OutboundWriter) { | ||
self.outbound = outbound | ||
} | ||
|
||
/// Write a single ByteBuffer | ||
/// - Parameter buffer: single buffer to write | ||
@inlinable | ||
func write(_ buffer: ByteBuffer) async throws { | ||
try await self.outbound.write(.body(buffer)) | ||
} | ||
|
||
/// Write a sequence of ByteBuffers | ||
/// - Parameter buffers: Sequence of buffers | ||
@inlinable | ||
func write(contentsOf buffers: some Sequence<ByteBuffer>) async throws { | ||
try await self.outbound.write(contentsOf: buffers.map { .body($0) }) | ||
} | ||
|
||
/// Finish writing body | ||
/// - Parameter trailingHeaders: Any trailing headers you want to include at end | ||
@inlinable | ||
consuming func finish(_ trailingHeaders: HTTPFields?) async throws { | ||
try await self.outbound.write(.end(trailingHeaders)) | ||
} | ||
} |
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
Oops, something went wrong.