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

Update from Hummingbird Project Template #91

Merged
merged 3 commits into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,12 @@ concurrency:

jobs:
validate:
runs-on: macOS-latest
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Install Dependencies
run: |
brew install mint
mint install NickLockwood/[email protected] --no-link
- name: run script
run: ./scripts/validate.sh
63 changes: 63 additions & 0 deletions .swift-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"version" : 1,
"indentation" : {
"spaces" : 4
},
"tabWidth" : 4,
"fileScopedDeclarationPrivacy" : {
"accessLevel" : "private"
},
"spacesAroundRangeFormationOperators" : false,
"indentConditionalCompilationBlocks" : false,
"indentSwitchCaseLabels" : false,
"lineBreakAroundMultilineExpressionChainComponents" : false,
"lineBreakBeforeControlFlowKeywords" : false,
"lineBreakBeforeEachArgument" : true,
"lineBreakBeforeEachGenericRequirement" : true,
"lineLength" : 150,
"maximumBlankLines" : 1,
"respectsExistingLineBreaks" : true,
"prioritizeKeepingFunctionOutputTogether" : true,
"multiElementCollectionTrailingCommas" : true,
"rules" : {
"AllPublicDeclarationsHaveDocumentation" : false,
"AlwaysUseLiteralForEmptyCollectionInit" : false,
"AlwaysUseLowerCamelCase" : false,
"AmbiguousTrailingClosureOverload" : true,
"BeginDocumentationCommentWithOneLineSummary" : false,
"DoNotUseSemicolons" : true,
"DontRepeatTypeInStaticProperties" : true,
"FileScopedDeclarationPrivacy" : true,
"FullyIndirectEnum" : true,
"GroupNumericLiterals" : true,
"IdentifiersMustBeASCII" : true,
"NeverForceUnwrap" : false,
"NeverUseForceTry" : false,
"NeverUseImplicitlyUnwrappedOptionals" : false,
"NoAccessLevelOnExtensionDeclaration" : true,
"NoAssignmentInExpressions" : true,
"NoBlockComments" : true,
"NoCasesWithOnlyFallthrough" : true,
"NoEmptyTrailingClosureParentheses" : true,
"NoLabelsInCasePatterns" : true,
"NoLeadingUnderscores" : false,
"NoParensAroundConditions" : true,
"NoVoidReturnOnFunctionSignature" : true,
"OmitExplicitReturns" : true,
"OneCasePerLine" : true,
"OneVariableDeclarationPerLine" : true,
"OnlyOneTrailingClosureArgument" : true,
"OrderedImports" : true,
"ReplaceForEachWithForLoop" : true,
"ReturnVoidInsteadOfEmptyTuple" : true,
"UseEarlyExits" : false,
"UseExplicitNilCheckInConditions" : false,
"UseLetInEveryBoundCaseVariable" : false,
"UseShorthandTypeNames" : true,
"UseSingleLinePropertyGetter" : false,
"UseSynthesizedInitializer" : false,
"UseTripleSlashForDocumentationComments" : true,
"UseWhereClausesInForLoops" : false,
"ValidateDocumentationComments" : false
}
}
26 changes: 0 additions & 26 deletions .swiftformat

This file was deleted.

2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ The main development branch of the repository is `main`.

### Formatting

We use Nick Lockwood's SwiftFormat for formatting code. PRs will not be accepted if they haven't be formatted. The current version of SwiftFormat we are using is v0.53.10.
We use Apple's swift-format for formatting code. PRs will not be accepted if they haven't be formatted.
69 changes: 44 additions & 25 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,31 +21,50 @@ let package = Package(
.package(url: "https://github.com/apple/swift-nio-ssl.git", from: "2.5.0"),
],
targets: [
.target(name: "HummingbirdWebSocket", dependencies: [
.product(name: "WSCore", package: "swift-websocket"),
.product(name: "Hummingbird", package: "hummingbird"),
.product(name: "NIOHTTPTypes", package: "swift-nio-extras"),
.product(name: "NIOHTTPTypesHTTP1", package: "swift-nio-extras"),
], swiftSettings: swiftSettings),
.target(name: "HummingbirdWSClient", dependencies: [
.product(name: "WSClient", package: "swift-websocket"),
], swiftSettings: swiftSettings),
.target(name: "HummingbirdWSCompression", dependencies: [
.product(name: "WSCompression", package: "swift-websocket"),
], swiftSettings: swiftSettings),
.target(name: "HummingbirdWSTesting", dependencies: [
.byName(name: "HummingbirdWSClient"),
.product(name: "HummingbirdTesting", package: "hummingbird"),
], swiftSettings: swiftSettings),
.testTarget(name: "HummingbirdWebSocketTests", dependencies: [
.byName(name: "HummingbirdWebSocket"),
.byName(name: "HummingbirdWSClient"),
.byName(name: "HummingbirdWSCompression"),
.byName(name: "HummingbirdWSTesting"),
.product(name: "Hummingbird", package: "hummingbird"),
.product(name: "HummingbirdTesting", package: "hummingbird"),
.product(name: "HummingbirdTLS", package: "hummingbird"),
]),
.target(
name: "HummingbirdWebSocket",
dependencies: [
.product(name: "WSCore", package: "swift-websocket"),
.product(name: "Hummingbird", package: "hummingbird"),
.product(name: "NIOHTTPTypes", package: "swift-nio-extras"),
.product(name: "NIOHTTPTypesHTTP1", package: "swift-nio-extras"),
],
swiftSettings: swiftSettings
),
.target(
name: "HummingbirdWSClient",
dependencies: [
.product(name: "WSClient", package: "swift-websocket")
],
swiftSettings: swiftSettings
),
.target(
name: "HummingbirdWSCompression",
dependencies: [
.product(name: "WSCompression", package: "swift-websocket")
],
swiftSettings: swiftSettings
),
.target(
name: "HummingbirdWSTesting",
dependencies: [
.byName(name: "HummingbirdWSClient"),
.product(name: "HummingbirdTesting", package: "hummingbird"),
],
swiftSettings: swiftSettings
),
.testTarget(
name: "HummingbirdWebSocketTests",
dependencies: [
.byName(name: "HummingbirdWebSocket"),
.byName(name: "HummingbirdWSClient"),
.byName(name: "HummingbirdWSCompression"),
.byName(name: "HummingbirdWSTesting"),
.product(name: "Hummingbird", package: "hummingbird"),
.product(name: "HummingbirdTesting", package: "hummingbird"),
.product(name: "HummingbirdTLS", package: "hummingbird"),
]
),
],
swiftLanguageVersions: [.v5, .version("6")]
)
4 changes: 3 additions & 1 deletion Snippets/AutobahnServerTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ logger.logLevel = .trace

let app = Application(
router: Router(),
server: .http1WebSocketUpgrade(configuration: .init(maxFrameSize: 16_777_216, extensions: [.perMessageDeflate(maxDecompressedFrameSize: 16_777_216)])) { _, _, _ in
server: .http1WebSocketUpgrade(
configuration: .init(maxFrameSize: 16_777_216, extensions: [.perMessageDeflate(maxDecompressedFrameSize: 16_777_216)])
) { _, _, _ in
return .upgrade([:]) { inbound, outbound, _ in
for try await msg in inbound.messages(maxSize: .max) {
switch msg {
Expand Down
11 changes: 6 additions & 5 deletions Snippets/WebsocketTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,12 @@ router.ws("/ws") { inbound, outbound, _ in
if frame.opcode == .text, String(buffer: frame.data) == "disconnect", frame.fin == true {
break
}
let opcode: WebSocketOpcode = switch frame.opcode {
case .text: .text
case .binary: .binary
case .continuation: .continuation
}
let opcode: WebSocketOpcode =
switch frame.opcode {
case .text: .text
case .binary: .binary
case .continuation: .continuation
}
let frame = WebSocketFrame(
fin: frame.fin,
opcode: opcode,
Expand Down
16 changes: 10 additions & 6 deletions Sources/HummingbirdWebSocket/HTTPServerBuilder+WebSocket.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@ extension HTTPServerBuilder {
public static func http1WebSocketUpgrade(
configuration: WebSocketServerConfiguration = .init(),
additionalChannelHandlers: @autoclosure @escaping @Sendable () -> [any RemovableChannelHandler] = [],
shouldUpgrade: @escaping @Sendable (HTTPRequest, Channel, Logger) async throws -> ShouldUpgradeResult<WebSocketDataHandler<HTTP1WebSocketUpgradeChannel.Context>>
shouldUpgrade: @escaping @Sendable (HTTPRequest, Channel, Logger) async throws -> ShouldUpgradeResult<
WebSocketDataHandler<HTTP1WebSocketUpgradeChannel.Context>
>
) -> HTTPServerBuilder {
return .init { responder in
return HTTP1WebSocketUpgradeChannel(
.init { responder in
HTTP1WebSocketUpgradeChannel(
responder: responder,
configuration: configuration,
additionalChannelHandlers: additionalChannelHandlers,
Expand All @@ -41,10 +43,12 @@ extension HTTPServerBuilder {
public static func http1WebSocketUpgrade(
configuration: WebSocketServerConfiguration = .init(),
additionalChannelHandlers: @autoclosure @escaping @Sendable () -> [any RemovableChannelHandler] = [],
shouldUpgrade: @escaping @Sendable (HTTPRequest, Channel, Logger) throws -> ShouldUpgradeResult<WebSocketDataHandler<HTTP1WebSocketUpgradeChannel.Context>>
shouldUpgrade: @escaping @Sendable (HTTPRequest, Channel, Logger) throws -> ShouldUpgradeResult<
WebSocketDataHandler<HTTP1WebSocketUpgradeChannel.Context>
>
) -> HTTPServerBuilder {
return .init { responder in
return HTTP1WebSocketUpgradeChannel(
.init { responder in
HTTP1WebSocketUpgradeChannel(
responder: responder,
configuration: configuration,
additionalChannelHandlers: additionalChannelHandlers,
Expand Down
87 changes: 48 additions & 39 deletions Sources/HummingbirdWebSocket/WebSocketChannel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,24 +73,27 @@ public struct HTTP1WebSocketUpgradeChannel: ServerChildChannel, HTTPChannelHandl
responseHeaders: headers,
logger: logger
)
return (headers, { asyncChannel, logger in
let context = Context(logger: logger)
do {
_ = try await WebSocketHandler.handle(
type: .server,
configuration: .init(
extensions: extensions,
autoPing: configuration.autoPing,
validateUTF8: configuration.validateUTF8
),
asyncChannel: asyncChannel,
context: context,
handler: handler
)
} catch {
logger.debug("WebSocket handler error", metadata: ["error.type": "\(error)"])
return (
headers,
{ asyncChannel, logger in
let context = Context(logger: logger)
do {
_ = try await WebSocketHandler.handle(
type: .server,
configuration: .init(
extensions: extensions,
autoPing: configuration.autoPing,
validateUTF8: configuration.validateUTF8
),
asyncChannel: asyncChannel,
context: context,
handler: handler
)
} catch {
logger.debug("WebSocket handler error", metadata: ["error.type": "\(error)"])
}
}
})
)
}
}
}
Expand All @@ -105,7 +108,12 @@ public struct HTTP1WebSocketUpgradeChannel: ServerChildChannel, HTTPChannelHandl
configuration: WebSocketServerConfiguration,
shouldUpgrade: @escaping @Sendable (HTTPRequest, Channel, Logger) async throws -> ShouldUpgradeResult<WebSocketDataHandler<Context>>
) {
self.init(responder: responder, configuration: configuration, additionalChannelHandlers: additionalChannelHandlers, shouldUpgrade: shouldUpgrade)
self.init(
responder: responder,
configuration: configuration,
additionalChannelHandlers: additionalChannelHandlers,
shouldUpgrade: shouldUpgrade
)
}

/// Initialize HTTP1AndWebSocketChannel with async `shouldUpgrade` function
Expand Down Expand Up @@ -133,24 +141,27 @@ public struct HTTP1WebSocketUpgradeChannel: ServerChildChannel, HTTPChannelHandl
responseHeaders: headers,
logger: logger
)
return (headers, { asyncChannel, logger in
let context = Context(logger: logger)
do {
_ = try await WebSocketHandler.handle(
type: .server,
configuration: .init(
extensions: extensions,
autoPing: configuration.autoPing,
validateUTF8: configuration.validateUTF8
),
asyncChannel: asyncChannel,
context: context,
handler: handler
)
} catch {
logger.debug("WebSocket handler error", metadata: ["error.type": "\(error)"])
return (
headers,
{ asyncChannel, logger in
let context = Context(logger: logger)
do {
_ = try await WebSocketHandler.handle(
type: .server,
configuration: .init(
extensions: extensions,
autoPing: configuration.autoPing,
validateUTF8: configuration.validateUTF8
),
asyncChannel: asyncChannel,
context: context,
handler: handler
)
} catch {
logger.debug("WebSocket handler error", metadata: ["error.type": "\(error)"])
}
}
})
)
}
}
return promise.futureResult
Expand All @@ -165,7 +176,7 @@ public struct HTTP1WebSocketUpgradeChannel: ServerChildChannel, HTTPChannelHandl
/// - logger: Logger used by upgrade
/// - Returns: Negotiated result future
public func setup(channel: Channel, logger: Logger) -> EventLoopFuture<Value> {
return channel.eventLoop.makeCompletedFuture {
channel.eventLoop.makeCompletedFuture {
let upgradeAttempted = NIOLoopBoundBox(false, eventLoop: channel.eventLoop)
let logger = logger.with(metadataKey: "hb_id", value: .stringConvertible(RequestID()))
let upgrader = NIOTypedWebSocketServerUpgrader<UpgradeResult>(
Expand All @@ -186,9 +197,7 @@ public struct HTTP1WebSocketUpgradeChannel: ServerChildChannel, HTTPChannelHandl
upgraders: [upgrader],
notUpgradingCompletionHandler: { channel in
let childChannelHandlers: [any ChannelHandler] =
[HTTP1ToHTTPServerCodec(secure: false)] +
self.additionalChannelHandlers() +
[HTTPUserEventHandler(logger: logger)]
[HTTP1ToHTTPServerCodec(secure: false)] + self.additionalChannelHandlers() + [HTTPUserEventHandler(logger: logger)]
return channel.eventLoop.makeCompletedFuture {
try channel.pipeline.syncOperations.addHandlers(childChannelHandlers)
let asyncChannel = try NIOAsyncChannel<HTTPRequestPart, HTTPResponsePart>(wrappingChannelSynchronously: channel)
Expand Down
4 changes: 2 additions & 2 deletions Sources/HummingbirdWebSocket/WebSocketRouter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ extension RouterMethods {
shouldUpgrade: @Sendable @escaping (Request, Context) async throws -> RouterShouldUpgrade = { _, _ in .upgrade([:]) },
onUpgrade handler: @escaping WebSocketDataHandler<WebSocketRouterContext<Context>>
) -> Self where Context: WebSocketRequestContext {
return on(path, method: .get) { request, context -> Response in
on(path, method: .get) { request, context -> Response in
let result = try await shouldUpgrade(request, context)
switch result {
case .dontUpgrade:
Expand Down Expand Up @@ -215,7 +215,7 @@ extension HTTPServerBuilder {
) -> HTTPServerBuilder where WSResponderBuilder.Responder.Context: WebSocketRequestContext {
let webSocketReponder = webSocketRouter.buildResponder()
return .init { responder in
return HTTP1WebSocketUpgradeChannel(
HTTP1WebSocketUpgradeChannel(
responder: responder,
webSocketResponder: webSocketReponder,
configuration: configuration,
Expand Down
Loading