Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove "HB" prefix #395

Merged
merged 11 commits into from Mar 11, 2024
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