Skip to content

Commit

Permalink
Remove "HB" prefix (#395)
Browse files Browse the repository at this point in the history
* Rename ChildChannel -> ServerChildChannel, Response -> RequestResponder

* MiddlewareProtocol -> RouterMiddleware

* Replace HB logger labels

* Rename URL -> URI

* Client -> ClientConnection

* ResponderBuilder -> RequestResponderBuilder

* Remove HB prefix

* RequestResponder -> HTTPResponder

* Deprecated typealiases

* Add HBMiddlewareProtocol

* Add HBResponseCodable to deprecations
  • Loading branch information
adam-fowler committed Mar 11, 2024
1 parent 7ad7e0c commit 5dbdee8
Show file tree
Hide file tree
Showing 126 changed files with 1,568 additions and 1,364 deletions.
2 changes: 1 addition & 1 deletion Benchmarks/Benchmarks/HTTP1/HTTP1ChannelBenchmarks.swift
Expand Up @@ -27,7 +27,7 @@ extension Benchmark {
name: String,
configuration: Benchmark.Configuration = Benchmark.defaultConfiguration,
write: @escaping @Sendable (Benchmark, NIOAsyncTestingChannel) async throws -> Void,
responder: @escaping @Sendable (HBRequest, Channel) async throws -> HBResponse
responder: @escaping @Sendable (Request, Channel) async throws -> Response
) {
let http1 = HTTP1Channel(responder: responder)
let channel = NIOAsyncTestingChannel()
Expand Down
30 changes: 15 additions & 15 deletions Benchmarks/Benchmarks/Router/RouterBenchmarks.swift
Expand Up @@ -16,36 +16,36 @@ import Benchmark
import HTTPTypes
import Hummingbird
import NIOHTTPTypes
@_spi(HBInternal) import HummingbirdCore
@_spi(Internal) import HummingbirdCore
import Logging
import NIOCore
import NIOPosix

/// Implementation of a basic request context that supports everything the Hummingbird library needs
struct BasicBenchmarkContext: HBRequestContext {
var coreContext: HBCoreRequestContext
struct BasicBenchmarkContext: RequestContext {
var coreContext: CoreRequestContext

public init(channel: Channel, logger: Logger) {
self.coreContext = .init(allocator: channel.allocator, logger: logger)
}
}

/// Writes ByteBuffers to AsyncChannel outbound writer
struct BenchmarkBodyWriter: Sendable, HBResponseBodyWriter {
struct BenchmarkBodyWriter: Sendable, ResponseBodyWriter {
func write(_: ByteBuffer) async throws {}
}

extension Benchmark {
@discardableResult
convenience init?<Context: HBRequestContext>(
convenience init?<Context: RequestContext>(
name: String,
context: Context.Type = BasicBenchmarkContext.self,
configuration: Benchmark.Configuration = Benchmark.defaultConfiguration,
request: HTTPRequest,
writeBody: @escaping @Sendable (HBStreamedRequestBody.InboundStream.TestSource) async throws -> Void = { _ in },
setupRouter: @escaping @Sendable (HBRouter<Context>) async throws -> Void
writeBody: @escaping @Sendable (StreamedRequestBody.InboundStream.TestSource) async throws -> Void = { _ in },
setupRouter: @escaping @Sendable (Router<Context>) async throws -> Void
) {
let router = HBRouter(context: Context.self)
let router = Router(context: Context.self)
self.init(name, configuration: configuration) { benchmark in
let responder = router.buildResponder()
benchmark.startMeasurement()
Expand All @@ -58,11 +58,11 @@ extension Benchmark {
logger: Logger(label: "Benchmark")
)
let (inbound, source) = NIOAsyncChannelInboundStream<HTTPRequestPart>.makeTestingStream()
let streamer = HBStreamedRequestBody(iterator: inbound.makeAsyncIterator())
let requestBody = HBRequestBody.stream(streamer)
let hbRequest = HBRequest(head: request, body: requestBody)
let streamer = StreamedRequestBody(iterator: inbound.makeAsyncIterator())
let requestBody = RequestBody.stream(streamer)
let Request = Request(head: request, body: requestBody)
group.addTask {
let response = try await responder.respond(to: hbRequest, context: context)
let response = try await responder.respond(to: Request, context: context)
_ = try await response.body.write(BenchmarkBodyWriter())
}
try await writeBody(source)
Expand Down Expand Up @@ -121,7 +121,7 @@ func routerBenchmarks() {
bodyStream.yield(.body(buffer))
} setupRouter: { router in
router.post { request, _ in
HBResponse(status: .ok, headers: [:], body: .init { writer in
Response(status: .ok, headers: [:], body: .init { writer in
for try await buffer in request.body {
try await writer.write(buffer)
}
Expand All @@ -134,8 +134,8 @@ func routerBenchmarks() {
configuration: .init(warmupIterations: 10),
request: .init(method: .get, scheme: "http", authority: "localhost", path: "/")
) { router in
struct EmptyMiddleware<Context>: HBMiddlewareProtocol {
func handle(_ request: HBRequest, context: Context, next: (HBRequest, Context) async throws -> HBResponse) async throws -> HBResponse {
struct EmptyMiddleware<Context>: MiddlewareProtocol {
func handle(_ request: Request, context: Context, next: (Request, Context) async throws -> Response) async throws -> Response {
return try await next(request, context)
}
}
Expand Down
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -26,12 +26,12 @@ It provides a router for directing different endpoints to their handlers, middle
import Hummingbird

// create router and add a single GET /hello route
let router = HBRouter()
let router = Router()
router.get("hello") { request, _ -> String in
return "Hello"
}
// create application using router
let app = HBApplication(
let app = Application(
router: router,
configuration: .init(address: .hostname("127.0.0.1", port: 8080))
)
Expand Down
60 changes: 30 additions & 30 deletions Sources/Hummingbird/Application.swift
Expand Up @@ -41,23 +41,23 @@ public enum EventLoopGroupProvider {
}
}

public protocol HBApplicationProtocol: Service where Context: HBRequestContext {
public protocol ApplicationProtocol: Service where Context: RequestContext {
/// Responder that generates a response from a requests and context
associatedtype Responder: HBResponder
associatedtype Responder: HTTPResponder
/// Child Channel setup. This defaults to support HTTP1
associatedtype ChildChannel: HBChildChannel & HTTPChannelHandler = HTTP1Channel
/// Context passed with HBRequest to responder
associatedtype ChildChannel: ServerChildChannel & HTTPChannelHandler = HTTP1Channel
/// Context passed with Request to responder
typealias Context = Responder.Context

/// Build the responder
var responder: Responder { get async throws }
/// Server channel setup
var server: HBHTTPChannelBuilder<ChildChannel> { get }
var server: HTTPChannelBuilder<ChildChannel> { get }

/// event loop group used by application
var eventLoopGroup: EventLoopGroup { get }
/// Application configuration
var configuration: HBApplicationConfiguration { get }
var configuration: ApplicationConfiguration { get }
/// Logger
var logger: Logger { get }
/// This is called once the server is running and we have an active Channel
Expand All @@ -69,16 +69,16 @@ public protocol HBApplicationProtocol: Service where Context: HBRequestContext {
var processesRunBeforeServerStart: [@Sendable () async throws -> Void] { get }
}

extension HBApplicationProtocol {
extension ApplicationProtocol {
/// Server channel setup
public var server: HBHTTPChannelBuilder<HTTP1Channel> { .http1() }
public var server: HTTPChannelBuilder<HTTP1Channel> { .http1() }
}

extension HBApplicationProtocol {
extension ApplicationProtocol {
/// Default event loop group used by application
public var eventLoopGroup: EventLoopGroup { MultiThreadedEventLoopGroup.singleton }
/// Default Configuration
public var configuration: HBApplicationConfiguration { .init() }
public var configuration: ApplicationConfiguration { .init() }
/// Default Logger
public var logger: Logger { Logger(label: self.configuration.serverName ?? "HummingBird") }
/// Default onServerRunning that does nothing
Expand All @@ -90,17 +90,17 @@ extension HBApplicationProtocol {
}

/// Conform to `Service` from `ServiceLifecycle`.
extension HBApplicationProtocol {
extension ApplicationProtocol {
/// Construct application and run it
public func run() async throws {
let dateCache = HBDateCache()
let dateCache = DateCache()
let responder = try await self.responder

// Function responding to HTTP request
@Sendable func respond(to request: HBRequest, channel: Channel) async throws -> HBResponse {
@Sendable func respond(to request: Request, channel: Channel) async throws -> Response {
let context = Self.Responder.Context(
channel: channel,
logger: self.logger.with(metadataKey: "hb_id", value: .stringConvertible(RequestID()))
logger: self.logger.with(metadataKey: "_id", value: .stringConvertible(RequestID()))
)
// respond to request
var response = try await responder.respond(to: request, context: context)
Expand All @@ -114,7 +114,7 @@ extension HBApplicationProtocol {
// get channel Setup
let channelSetup = try self.server.build(respond)
// create server
let server = HBServer(
let server = Server(
childChannelSetup: channelSetup,
configuration: self.configuration.httpServer,
onServerRunning: self.onServerRunning,
Expand Down Expand Up @@ -150,16 +150,16 @@ extension HBApplicationProtocol {
/// Application class. Brings together all the components of Hummingbird together
///
/// ```
/// let router = HBRouter()
/// let router = Router()
/// router.middleware.add(MyMiddleware())
/// router.get("hello") { _ in
/// return "hello"
/// }
/// let app = HBApplication(responder: router.buildResponder())
/// let app = Application(responder: router.buildResponder())
/// try await app.runService()
/// ```
/// Editing the application setup after calling `runService` will produce undefined behaviour.
public struct HBApplication<Responder: HBResponder, ChildChannel: HBChildChannel & HTTPChannelHandler>: HBApplicationProtocol where Responder.Context: HBRequestContext {
public struct Application<Responder: HTTPResponder, ChildChannel: ServerChildChannel & HTTPChannelHandler>: ApplicationProtocol where Responder.Context: RequestContext {
public typealias Context = Responder.Context
public typealias ChildChannel = ChildChannel
public typealias Responder = Responder
Expand All @@ -168,16 +168,16 @@ public struct HBApplication<Responder: HBResponder, ChildChannel: HBChildChannel

/// event loop group used by application
public let eventLoopGroup: EventLoopGroup
/// routes requests to requestResponders based on URI
/// routes requests to responders based on URI
public let responder: Responder
/// Configuration
public var configuration: HBApplicationConfiguration
public var configuration: ApplicationConfiguration
/// Logger
public var logger: Logger
/// on server running
private var _onServerRunning: @Sendable (Channel) async -> Void
/// Server channel setup
public let server: HBHTTPChannelBuilder<ChildChannel>
public let server: HTTPChannelBuilder<ChildChannel>
/// services attached to the application.
public var services: [any Service]
/// Processes to be run before server is started
Expand All @@ -196,8 +196,8 @@ public struct HBApplication<Responder: HBResponder, ChildChannel: HBChildChannel
/// - logger: Logger application uses
public init(
responder: Responder,
server: HBHTTPChannelBuilder<ChildChannel> = .http1(),
configuration: HBApplicationConfiguration = HBApplicationConfiguration(),
server: HTTPChannelBuilder<ChildChannel> = .http1(),
configuration: ApplicationConfiguration = ApplicationConfiguration(),
onServerRunning: @escaping @Sendable (Channel) async -> Void = { _ in },
eventLoopGroupProvider: EventLoopGroupProvider = .singleton,
logger: Logger? = nil
Expand All @@ -206,7 +206,7 @@ public struct HBApplication<Responder: HBResponder, ChildChannel: HBChildChannel
self.logger = logger
} else {
var logger = Logger(label: configuration.serverName ?? "Hummingbird")
logger.logLevel = HBEnvironment().get("LOG_LEVEL").map { Logger.Level(rawValue: $0) ?? .info } ?? .info
logger.logLevel = Environment().get("LOG_LEVEL").map { Logger.Level(rawValue: $0) ?? .info } ?? .info
self.logger = logger
}
self.responder = responder
Expand All @@ -228,10 +228,10 @@ public struct HBApplication<Responder: HBResponder, ChildChannel: HBChildChannel
/// - onServerRunning: Function called once the server is running
/// - eventLoopGroupProvider: Where to get our EventLoopGroup
/// - logger: Logger application uses
public init<ResponderBuilder: HBResponderBuilder>(
public init<ResponderBuilder: HTTPResponderBuilder>(
router: ResponderBuilder,
server: HBHTTPChannelBuilder<ChildChannel> = .http1(),
configuration: HBApplicationConfiguration = HBApplicationConfiguration(),
server: HTTPChannelBuilder<ChildChannel> = .http1(),
configuration: ApplicationConfiguration = ApplicationConfiguration(),
onServerRunning: @escaping @Sendable (Channel) async -> Void = { _ in },
eventLoopGroupProvider: EventLoopGroupProvider = .singleton,
logger: Logger? = nil
Expand All @@ -240,7 +240,7 @@ public struct HBApplication<Responder: HBResponder, ChildChannel: HBChildChannel
self.logger = logger
} else {
var logger = Logger(label: configuration.serverName ?? "Hummingbird")
logger.logLevel = HBEnvironment().get("LOG_LEVEL").map { Logger.Level(rawValue: $0) ?? .info } ?? .info
logger.logLevel = Environment().get("LOG_LEVEL").map { Logger.Level(rawValue: $0) ?? .info } ?? .info
self.logger = logger
}
self.responder = router.buildResponder()
Expand Down Expand Up @@ -284,8 +284,8 @@ public struct HBApplication<Responder: HBResponder, ChildChannel: HBChildChannel
}
}

extension HBApplication: CustomStringConvertible {
public var description: String { "HBApplication" }
extension Application: CustomStringConvertible {
public var description: String { "Application" }
}

extension Logger {
Expand Down
8 changes: 4 additions & 4 deletions Sources/Hummingbird/Codable/CodableProtocols.swift
Expand Up @@ -15,20 +15,20 @@
import HTTPTypes

/// protocol for encoders generating a Response
public protocol HBResponseEncoder: Sendable {
public protocol ResponseEncoder: Sendable {
/// Encode value returned by handler to request
///
/// - Parameters:
/// - value: value to encode
/// - request: request that generated this value
func encode(_ value: some Encodable, from request: HBRequest, context: some HBBaseRequestContext) throws -> HBResponse
func encode(_ value: some Encodable, from request: Request, context: some BaseRequestContext) throws -> Response
}

/// protocol for decoder deserializing from a Request body
public protocol HBRequestDecoder: Sendable {
public protocol RequestDecoder: Sendable {
/// Decode type from request
/// - Parameters:
/// - type: type to decode to
/// - request: request
func decode<T: Decodable>(_ type: T.Type, from request: HBRequest, context: some HBBaseRequestContext) async throws -> T
func decode<T: Decodable>(_ type: T.Type, from request: Request, context: some BaseRequestContext) async throws -> T
}
16 changes: 8 additions & 8 deletions Sources/Hummingbird/Codable/JSON/JSONCoding.swift
Expand Up @@ -17,35 +17,35 @@ import struct Foundation.Date
@_exported import class Foundation.JSONEncoder
import NIOFoundationCompat

extension JSONEncoder: HBResponseEncoder {
/// Extend JSONEncoder to support encoding `HBResponse`'s. Sets body and header values
extension JSONEncoder: ResponseEncoder {
/// Extend JSONEncoder to support encoding `Response`'s. Sets body and header values
/// - Parameters:
/// - value: Value to encode
/// - request: Request used to generate response
public func encode(_ value: some Encodable, from request: HBRequest, context: some HBBaseRequestContext) throws -> HBResponse {
public func encode(_ value: some Encodable, from request: Request, context: some BaseRequestContext) throws -> Response {
var buffer = context.allocator.buffer(capacity: 0)
let data = try self.encode(value)
buffer.writeBytes(data)
return HBResponse(
return Response(
status: .ok,
headers: [.contentType: "application/json; charset=utf-8"],
body: .init(byteBuffer: buffer)
)
}
}

extension JSONDecoder: HBRequestDecoder {
/// Extend JSONDecoder to decode from `HBRequest`.
extension JSONDecoder: RequestDecoder {
/// Extend JSONDecoder to decode from `Request`.
/// - Parameters:
/// - type: Type to decode
/// - request: Request to decode from
public func decode<T: Decodable>(_ type: T.Type, from request: HBRequest, context: some HBBaseRequestContext) async throws -> T {
public func decode<T: Decodable>(_ type: T.Type, from request: Request, context: some BaseRequestContext) async throws -> T {
let buffer = try await request.body.collect(upTo: context.maxUploadSize)
return try self.decode(T.self, from: buffer)
}
}

/// `HBRequestDecoder` and `HBResponseEncoder` both require conformance to `Sendable`. Given
/// `RequestDecoder` and `ResponseEncoder` both require conformance to `Sendable`. Given
/// `JSONEncoder`` and `JSONDecoder`` conform to Sendable in macOS 13+ I think I can just
/// back date the conformance to all versions of Swift, macOS we support
#if hasFeature(RetroactiveAttribute)
Expand Down

0 comments on commit 5dbdee8

Please sign in to comment.