diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 7cddf305..434025a9 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -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/SwiftFormat@0.53.10 --no-link - name: run script run: ./scripts/validate.sh diff --git a/.swift-format b/.swift-format new file mode 100644 index 00000000..bb3dcff3 --- /dev/null +++ b/.swift-format @@ -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 + } +} diff --git a/.swiftformat b/.swiftformat deleted file mode 100644 index 14fb33f2..00000000 --- a/.swiftformat +++ /dev/null @@ -1,26 +0,0 @@ -# Minimum swiftformat version ---minversion 0.53.10 - -# Swift version ---swiftversion 5.9 - -# file options ---exclude .build - -# rules ---disable redundantReturn, extensionAccessControl, typeSugar, conditionalAssignment, preferForLoop, redundantInternal, redundantStaticSelf - -# format options ---ifdef no-indent ---nospaceoperators ...,..< ---patternlet inline ---self insert ---stripunusedargs unnamed-only - -#--maxwidth 150 ---wraparguments before-first ---wrapparameters before-first ---wrapcollections before-first - -#file header -# --header "//===----------------------------------------------------------------------===//\n//\n// This source file is part of the Hummingbird server framework project\n//\n// Copyright (c) {created.year}-{year} the Hummingbird authors\n// Licensed under Apache License v2.0\n//\n// See LICENSE.txt for license information\n// See hummingbird/CONTRIBUTORS.txt for the list of Hummingbird authors\n//\n// SPDX-License-Identifier: Apache-2.0\n//\n//===----------------------------------------------------------------------===//" diff --git a/Benchmarks/Benchmarks/Router/Benchmarks.swift b/Benchmarks/Benchmarks/Router/Benchmarks.swift index 06055ac9..ccce7cad 100644 --- a/Benchmarks/Benchmarks/Router/Benchmarks.swift +++ b/Benchmarks/Benchmarks/Router/Benchmarks.swift @@ -18,12 +18,12 @@ import Hummingbird let benchmarks = { Benchmark.defaultConfiguration = .init( - metrics: ProcessInfo.processInfo.environment["CI"] != nil ? - [ + metrics: ProcessInfo.processInfo.environment["CI"] != nil + ? [ .instructions, .mallocCountTotal, - ] : - [ + ] + : [ .cpuTotal, .instructions, .mallocCountTotal, diff --git a/Benchmarks/Benchmarks/Router/RouterBenchmarks.swift b/Benchmarks/Benchmarks/Router/RouterBenchmarks.swift index fda4ff00..622342bb 100644 --- a/Benchmarks/Benchmarks/Router/RouterBenchmarks.swift +++ b/Benchmarks/Benchmarks/Router/RouterBenchmarks.swift @@ -106,7 +106,7 @@ extension Benchmark { struct EmptyMiddleware: RouterMiddleware { func handle(_ request: Request, context: Context, next: (Request, Context) async throws -> Response) async throws -> Response { - return try await next(request, context) + try await next(request, context) } } @@ -170,12 +170,16 @@ func routerBenchmarks() { } createRouter: { let router = Router(context: BasicBenchmarkContext.self) router.post { request, _ in - Response(status: .ok, headers: [:], body: .init { writer in - for try await buffer in request.body { - try await writer.write(buffer) + Response( + status: .ok, + headers: [:], + body: .init { writer in + for try await buffer in request.body { + try await writer.write(buffer) + } + try await writer.finish(nil) } - try await writer.finish(nil) - }) + ) } return router } diff --git a/Benchmarks/Package.swift b/Benchmarks/Package.swift index d17c34cc..abb4c079 100644 --- a/Benchmarks/Package.swift +++ b/Benchmarks/Package.swift @@ -21,8 +21,8 @@ let package = Package( ], path: "Benchmarks/Router", plugins: [ - .plugin(name: "BenchmarkPlugin", package: "package-benchmark"), + .plugin(name: "BenchmarkPlugin", package: "package-benchmark") ] - ), + ) ] ) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 14b9831c..8f5de310 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -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. \ No newline at end of file diff --git a/Package.swift b/Package.swift index 70e19281..f2a28e3f 100644 --- a/Package.swift +++ b/Package.swift @@ -123,21 +123,26 @@ let package = Package( swiftSettings: [.enableExperimentalFeature("StrictConcurrency=complete")] ), // test targets - .testTarget(name: "HummingbirdTests", dependencies: [ - .byName(name: "Hummingbird"), - .byName(name: "HummingbirdTLS"), - .byName(name: "HummingbirdHTTP2"), - .byName(name: "HummingbirdTesting"), - .byName(name: "HummingbirdRouter"), - ]), - .testTarget(name: "HummingbirdRouterTests", dependencies: [ - .byName(name: "HummingbirdRouter"), - .byName(name: "HummingbirdTesting"), - ]), + .testTarget( + name: "HummingbirdTests", + dependencies: [ + .byName(name: "Hummingbird"), + .byName(name: "HummingbirdTLS"), + .byName(name: "HummingbirdHTTP2"), + .byName(name: "HummingbirdTesting"), + .byName(name: "HummingbirdRouter"), + ] + ), + .testTarget( + name: "HummingbirdRouterTests", + dependencies: [ + .byName(name: "HummingbirdRouter"), + .byName(name: "HummingbirdTesting"), + ] + ), .testTarget( name: "HummingbirdCoreTests", - dependencies: - [ + dependencies: [ .byName(name: "HummingbirdCore"), .byName(name: "HummingbirdTLS"), .byName(name: "HummingbirdTesting"), @@ -147,8 +152,7 @@ let package = Package( ), .testTarget( name: "HummingbirdHTTP2Tests", - dependencies: - [ + dependencies: [ .byName(name: "HummingbirdCore"), .byName(name: "HummingbirdHTTP2"), .byName(name: "HummingbirdTesting"), diff --git a/Sources/Hummingbird/Application.swift b/Sources/Hummingbird/Application.swift index 2cb893d6..c72d48f3 100644 --- a/Sources/Hummingbird/Application.swift +++ b/Sources/Hummingbird/Application.swift @@ -169,7 +169,8 @@ extension ApplicationProtocol { /// try await app.runService() /// ``` /// Editing the application setup after calling `runService` will produce undefined behaviour. -public struct Application: ApplicationProtocol where Responder.Context: InitializableFromSource { +public struct Application: ApplicationProtocol +where Responder.Context: InitializableFromSource { // MARK: Member variables /// event loop group used by application @@ -280,7 +281,7 @@ public struct Application: ApplicationProtocol where R } public func buildResponder() async throws -> Responder { - return self.responder + self.responder } public func onServerRunning(_ channel: Channel) async { diff --git a/Sources/Hummingbird/Codable/JSON/JSONCoding.swift b/Sources/Hummingbird/Codable/JSON/JSONCoding.swift index 900ade14..a8777884 100644 --- a/Sources/Hummingbird/Codable/JSON/JSONCoding.swift +++ b/Sources/Hummingbird/Codable/JSON/JSONCoding.swift @@ -12,10 +12,11 @@ // //===----------------------------------------------------------------------===// +import NIOFoundationCompat + import struct Foundation.Date import class Foundation.JSONDecoder import class Foundation.JSONEncoder -import NIOFoundationCompat extension JSONEncoder: ResponseEncoder { /// Extend JSONEncoder to support encoding `Response`'s. Sets body and header values diff --git a/Sources/Hummingbird/Codable/ResponseEncodable.swift b/Sources/Hummingbird/Codable/ResponseEncodable.swift index 63c2e751..2c248f6d 100644 --- a/Sources/Hummingbird/Codable/ResponseEncodable.swift +++ b/Sources/Hummingbird/Codable/ResponseEncodable.swift @@ -24,7 +24,7 @@ public protocol ResponseCodable: ResponseEncodable, Decodable {} /// Extend ResponseEncodable to conform to ResponseGenerator extension ResponseEncodable { public func response(from request: Request, context: some RequestContext) throws -> Response { - return try context.responseEncoder.encode(self, from: request, context: context) + try context.responseEncoder.encode(self, from: request, context: context) } } @@ -34,7 +34,7 @@ extension Array: ResponseGenerator where Element: Encodable {} /// Extend Array to conform to ResponseEncodable extension Array: ResponseEncodable where Element: Encodable { public func response(from request: Request, context: some RequestContext) throws -> Response { - return try context.responseEncoder.encode(self, from: request, context: context) + try context.responseEncoder.encode(self, from: request, context: context) } } @@ -44,6 +44,6 @@ extension Dictionary: ResponseGenerator where Key: Encodable, Value: Encodable { /// Extend Array to conform to ResponseEncodable extension Dictionary: ResponseEncodable where Key: Encodable, Value: Encodable { public func response(from request: Request, context: some RequestContext) throws -> Response { - return try context.responseEncoder.encode(self, from: request, context: context) + try context.responseEncoder.encode(self, from: request, context: context) } } diff --git a/Sources/Hummingbird/Codable/URLEncodedForm/URLEncodedFormDecoder.swift b/Sources/Hummingbird/Codable/URLEncodedForm/URLEncodedFormDecoder.swift index 2f6c3d22..7a563eb0 100644 --- a/Sources/Hummingbird/Codable/URLEncodedForm/URLEncodedFormDecoder.swift +++ b/Sources/Hummingbird/Codable/URLEncodedForm/URLEncodedFormDecoder.swift @@ -55,7 +55,7 @@ public struct URLEncodedFormDecoder: Sendable { /// The options set on the top-level encoder. fileprivate var options: _Options { - return _Options( + _Options( dateDecodingStrategy: self.dateDecodingStrategy, userInfo: self.userInfo ) @@ -99,7 +99,7 @@ private class _URLEncodedFormDecoder: Decoder { /// Contextual user-provided information for use during encoding. public var userInfo: [CodingUserInfoKey: Any] { - return self.options.userInfo + self.options.userInfo } // MARK: - Initialization @@ -126,7 +126,7 @@ private class _URLEncodedFormDecoder: Decoder { } func singleValueContainer() throws -> SingleValueDecodingContainer { - return self + self } struct KDC: KeyedDecodingContainerProtocol { @@ -143,81 +143,111 @@ private class _URLEncodedFormDecoder: Decoder { } func contains(_ key: Key) -> Bool { - return self.container.values[key.stringValue] != nil + self.container.values[key.stringValue] != nil } func decodeNil(forKey key: Key) throws -> Bool { - guard let node = container.values[key.stringValue] else { throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) } + guard let node = container.values[key.stringValue] else { + throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) + } return try self.decoder.unboxNil(node) } func decode(_ type: Bool.Type, forKey key: Key) throws -> Bool { - guard let node = container.values[key.stringValue] else { throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) } + guard let node = container.values[key.stringValue] else { + throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) + } return try self.decoder.unbox(node, as: Bool.self) } func decode(_ type: String.Type, forKey key: Key) throws -> String { - guard let node = container.values[key.stringValue] else { throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) } + guard let node = container.values[key.stringValue] else { + throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) + } return try self.decoder.unbox(node, as: String.self) } func decode(_ type: Double.Type, forKey key: Key) throws -> Double { - guard let node = container.values[key.stringValue] else { throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) } + guard let node = container.values[key.stringValue] else { + throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) + } return try self.decoder.unbox(node, as: Double.self) } func decode(_ type: Float.Type, forKey key: Key) throws -> Float { - guard let node = container.values[key.stringValue] else { throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) } + guard let node = container.values[key.stringValue] else { + throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) + } return try self.decoder.unbox(node, as: Float.self) } func decode(_ type: Int.Type, forKey key: Key) throws -> Int { - guard let node = container.values[key.stringValue] else { throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) } + guard let node = container.values[key.stringValue] else { + throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) + } return try self.decoder.unbox(node, as: Int.self) } func decode(_ type: Int8.Type, forKey key: Key) throws -> Int8 { - guard let node = container.values[key.stringValue] else { throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) } + guard let node = container.values[key.stringValue] else { + throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) + } return try self.decoder.unbox(node, as: Int8.self) } func decode(_ type: Int16.Type, forKey key: Key) throws -> Int16 { - guard let node = container.values[key.stringValue] else { throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) } + guard let node = container.values[key.stringValue] else { + throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) + } return try self.decoder.unbox(node, as: Int16.self) } func decode(_ type: Int32.Type, forKey key: Key) throws -> Int32 { - guard let node = container.values[key.stringValue] else { throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) } + guard let node = container.values[key.stringValue] else { + throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) + } return try self.decoder.unbox(node, as: Int32.self) } func decode(_ type: Int64.Type, forKey key: Key) throws -> Int64 { - guard let node = container.values[key.stringValue] else { throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) } + guard let node = container.values[key.stringValue] else { + throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) + } return try self.decoder.unbox(node, as: Int64.self) } func decode(_ type: UInt.Type, forKey key: Key) throws -> UInt { - guard let node = container.values[key.stringValue] else { throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) } + guard let node = container.values[key.stringValue] else { + throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) + } return try self.decoder.unbox(node, as: UInt.self) } func decode(_ type: UInt8.Type, forKey key: Key) throws -> UInt8 { - guard let node = container.values[key.stringValue] else { throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) } + guard let node = container.values[key.stringValue] else { + throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) + } return try self.decoder.unbox(node, as: UInt8.self) } func decode(_ type: UInt16.Type, forKey key: Key) throws -> UInt16 { - guard let node = container.values[key.stringValue] else { throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) } + guard let node = container.values[key.stringValue] else { + throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) + } return try self.decoder.unbox(node, as: UInt16.self) } func decode(_ type: UInt32.Type, forKey key: Key) throws -> UInt32 { - guard let node = container.values[key.stringValue] else { throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) } + guard let node = container.values[key.stringValue] else { + throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) + } return try self.decoder.unbox(node, as: UInt32.self) } func decode(_ type: UInt64.Type, forKey key: Key) throws -> UInt64 { - guard let node = container.values[key.stringValue] else { throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) } + guard let node = container.values[key.stringValue] else { + throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) + } return try self.decoder.unbox(node, as: UInt64.self) } @@ -225,15 +255,20 @@ private class _URLEncodedFormDecoder: Decoder { self.decoder.codingPath.append(key) defer { self.decoder.codingPath.removeLast() } - guard let node = container.values[key.stringValue] else { throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) } + guard let node = container.values[key.stringValue] else { + throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) + } return try self.decoder.unbox(node, as: T.self) } - func nestedContainer(keyedBy type: NestedKey.Type, forKey key: Key) throws -> KeyedDecodingContainer where NestedKey: CodingKey { + func nestedContainer(keyedBy type: NestedKey.Type, forKey key: Key) throws -> KeyedDecodingContainer + where NestedKey: CodingKey { self.decoder.codingPath.append(key) defer { self.decoder.codingPath.removeLast() } - guard let node = container.values[key.stringValue] else { throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) } + guard let node = container.values[key.stringValue] else { + throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) + } guard case .map(let map) = node else { throw DecodingError.dataCorrupted(.init(codingPath: self.codingPath, debugDescription: "Expected a dictionary")) } @@ -245,7 +280,9 @@ private class _URLEncodedFormDecoder: Decoder { self.decoder.codingPath.append(key) defer { self.decoder.codingPath.removeLast() } - guard let node = container.values[key.stringValue] else { throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) } + guard let node = container.values[key.stringValue] else { + throw DecodingError.keyNotFound(key, .init(codingPath: self.codingPath, debugDescription: "")) + } guard case .array(let array) = node else { throw DecodingError.dataCorrupted(.init(codingPath: self.codingPath, debugDescription: "Expected a dictionary")) } @@ -353,7 +390,8 @@ private class _URLEncodedFormDecoder: Decoder { try self.decodeNextNode() } - mutating func nestedContainer(keyedBy type: NestedKey.Type) throws -> KeyedDecodingContainer where NestedKey: CodingKey { + mutating func nestedContainer(keyedBy type: NestedKey.Type) throws -> KeyedDecodingContainer + where NestedKey: CodingKey { guard !self.isAtEnd else { throw DecodingError.dataCorrupted(.init(codingPath: self.codingPath, debugDescription: "Unkeyed container index out of range")) } @@ -605,13 +643,15 @@ extension _URLEncodedFormDecoder { func unbox(_ node: URLEncodedFormNode, as type: Data.Type) throws -> Data { let string = try unbox(node, as: String.self) guard let data = Data(base64Encoded: string) else { - throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: self.codingPath, debugDescription: "Encountered Data is not valid Base64.")) + throw DecodingError.dataCorrupted( + DecodingError.Context(codingPath: self.codingPath, debugDescription: "Encountered Data is not valid Base64.") + ) } return data } func unbox(_ node: URLEncodedFormNode, as type: T.Type) throws -> T where T: Decodable { - return try self.unbox_(node, as: T.self) as! T + try self.unbox_(node, as: T.self) as! T } func unbox_(_ node: URLEncodedFormNode, as type: Decodable.Type) throws -> Any { @@ -635,11 +675,11 @@ private struct URLEncodedFormDecodingStorage { init() {} /// return the container at the top of the storage - var topContainer: URLEncodedFormNode { return self.containers.last! } + var topContainer: URLEncodedFormNode { self.containers.last! } /// push a new container onto the storage mutating func push(container: URLEncodedFormNode) { self.containers.append(container) } /// pop a container from the storage - @discardableResult mutating func popContainer() -> URLEncodedFormNode { return self.containers.removeLast() } + @discardableResult mutating func popContainer() -> URLEncodedFormNode { self.containers.removeLast() } } diff --git a/Sources/Hummingbird/Codable/URLEncodedForm/URLEncodedFormEncoder.swift b/Sources/Hummingbird/Codable/URLEncodedForm/URLEncodedFormEncoder.swift index 98218823..dfced414 100644 --- a/Sources/Hummingbird/Codable/URLEncodedForm/URLEncodedFormEncoder.swift +++ b/Sources/Hummingbird/Codable/URLEncodedForm/URLEncodedFormEncoder.swift @@ -55,7 +55,7 @@ public struct URLEncodedFormEncoder: Sendable { /// The options set on the top-level encoder. fileprivate var options: _Options { - return _Options( + _Options( dateEncodingStrategy: self.dateEncodingStrategy, userInfo: self.userInfo ) @@ -104,7 +104,7 @@ private class _URLEncodedFormEncoder: Encoder { /// Contextual user-provided information for use during encoding. public var userInfo: [CodingUserInfoKey: Any] { - return self.options.userInfo + self.options.userInfo } /// Initialization @@ -127,7 +127,7 @@ private class _URLEncodedFormEncoder: Encoder { } struct KEC: KeyedEncodingContainerProtocol { - var codingPath: [CodingKey] { return self.encoder.codingPath } + var codingPath: [CodingKey] { self.encoder.codingPath } let container: URLEncodedFormNode.Map let encoder: _URLEncodedFormEncoder @@ -170,7 +170,8 @@ private class _URLEncodedFormEncoder: Encoder { self.container.addChild(key: key.stringValue, value: childContainer) } - mutating func nestedContainer(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer where NestedKey: CodingKey { + mutating func nestedContainer(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer + where NestedKey: CodingKey { self.encoder.codingPath.append(key) defer { self.encoder.codingPath.removeLast() } @@ -192,11 +193,11 @@ private class _URLEncodedFormEncoder: Encoder { } mutating func superEncoder() -> Encoder { - return self.encoder + self.encoder } mutating func superEncoder(forKey key: Key) -> Encoder { - return self.encoder + self.encoder } } @@ -206,7 +207,7 @@ private class _URLEncodedFormEncoder: Encoder { } struct UKEC: UnkeyedEncodingContainer { - var codingPath: [CodingKey] { return self.encoder.codingPath } + var codingPath: [CodingKey] { self.encoder.codingPath } let container: URLEncodedFormNode.Array let encoder: _URLEncodedFormEncoder var count: Int @@ -275,7 +276,7 @@ private class _URLEncodedFormEncoder: Encoder { } mutating func superEncoder() -> Encoder { - return self.encoder + self.encoder } } } @@ -313,7 +314,7 @@ extension _URLEncodedFormEncoder: SingleValueEncodingContainer { } func singleValueContainer() -> SingleValueEncodingContainer { - return self + self } } @@ -388,6 +389,6 @@ private struct URLEncodedFormEncoderStorage { /// pop a container from the storage @discardableResult mutating func popContainer() -> URLEncodedFormNode { - return self.containers.removeLast() + self.containers.removeLast() } } diff --git a/Sources/Hummingbird/Codable/URLEncodedForm/URLEncodedFormNode.swift b/Sources/Hummingbird/Codable/URLEncodedForm/URLEncodedFormNode.swift index ac59fb52..82385f61 100644 --- a/Sources/Hummingbird/Codable/URLEncodedForm/URLEncodedFormNode.swift +++ b/Sources/Hummingbird/Codable/URLEncodedForm/URLEncodedFormNode.swift @@ -133,7 +133,7 @@ enum URLEncodedFormNode: CustomStringConvertible, Equatable { } var percentEncoded: String { - return self.value.addingPercentEncoding(withAllowedCharacters: URLEncodedForm.unreservedCharacters) ?? self.value + self.value.addingPercentEncoding(withAllowedCharacters: URLEncodedForm.unreservedCharacters) ?? self.value } static func == (lhs: URLEncodedFormNode.NodeValue, rhs: URLEncodedFormNode.NodeValue) -> Bool { diff --git a/Sources/Hummingbird/Configuration.swift b/Sources/Hummingbird/Configuration.swift index 5a178486..ffc57717 100644 --- a/Sources/Hummingbird/Configuration.swift +++ b/Sources/Hummingbird/Configuration.swift @@ -15,6 +15,7 @@ import HummingbirdCore import Logging import NIOCore + #if canImport(Network) import Network #endif @@ -89,7 +90,7 @@ public struct ApplicationConfiguration: Sendable { ) { self.address = address self.serverName = serverName - self.backlog = 256 // not used by Network framework + self.backlog = 256 // not used by Network framework self.reuseAddress = reuseAddress self.availableConnectionsDelegate = availableConnectionsDelegate self.tlsOptions = tlsOptions @@ -104,7 +105,7 @@ public struct ApplicationConfiguration: Sendable { backlog: Int? = nil, reuseAddress: Bool? = nil ) -> Self { - return .init( + .init( address: address ?? self.address, serverName: serverName ?? self.serverName, backlog: backlog ?? self.backlog, @@ -115,7 +116,7 @@ public struct ApplicationConfiguration: Sendable { /// return HTTP server configuration #if canImport(Network) var httpServer: ServerConfiguration { - return .init( + .init( address: self.address, serverName: self.serverName, backlog: self.backlog, @@ -126,7 +127,7 @@ public struct ApplicationConfiguration: Sendable { } #else var httpServer: ServerConfiguration { - return .init( + .init( address: self.address, serverName: self.serverName, backlog: self.backlog, diff --git a/Sources/Hummingbird/Environment.swift b/Sources/Hummingbird/Environment.swift index 4635f019..a61babe0 100644 --- a/Sources/Hummingbird/Environment.swift +++ b/Sources/Hummingbird/Environment.swift @@ -12,6 +12,10 @@ // //===----------------------------------------------------------------------===// +import Foundation +import HummingbirdCore +import NIOCore + #if canImport(Glibc) import Glibc #elseif canImport(Musl) @@ -21,9 +25,6 @@ import Darwin.C #else #error("Unsupported platform") #endif -import Foundation -import HummingbirdCore -import NIOCore /// Access environment variables public struct Environment: Sendable, Decodable, ExpressibleByDictionaryLiteral { @@ -76,7 +77,7 @@ public struct Environment: Sendable, Decodable, ExpressibleByDictionaryLiteral { /// Get environment variable with name /// - Parameter s: Environment variable name public func get(_ s: String) -> String? { - return self.values[s.lowercased()] + self.values[s.lowercased()] } /// Get environment variable with name as a certain type @@ -84,7 +85,7 @@ public struct Environment: Sendable, Decodable, ExpressibleByDictionaryLiteral { /// - s: Environment variable name /// - as: Type we want variable to be cast to public func get(_ s: String, as: T.Type) -> T? { - return self.values[s.lowercased()].map { T(String($0)) } ?? nil + self.values[s.lowercased()].map { T(String($0)) } ?? nil } /// Set environment variable @@ -136,7 +137,7 @@ public struct Environment: Sendable, Decodable, ExpressibleByDictionaryLiteral { } let fileRegion = try FileRegion(fileHandle: fileHandle) let contents = try fileHandle.withUnsafeFileDescriptor { descriptor in - return Array(unsafeUninitializedCapacity: fileRegion.readableBytes) { bytes, size in + return [UInt8](unsafeUninitializedCapacity: fileRegion.readableBytes) { bytes, size in size = fileRegion.readableBytes read(descriptor, .init(bytes.baseAddress), size) } diff --git a/Sources/Hummingbird/Exports.swift b/Sources/Hummingbird/Exports.swift index 6b764f7f..f0eb56e8 100644 --- a/Sources/Hummingbird/Exports.swift +++ b/Sources/Hummingbird/Exports.swift @@ -12,26 +12,24 @@ // //===----------------------------------------------------------------------===// -@_exported @_documentation(visibility: internal) import struct HummingbirdCore.BindAddress -@_exported @_documentation(visibility: internal) import struct HummingbirdCore.Request -@_exported @_documentation(visibility: internal) import struct HummingbirdCore.RequestBody -@_exported @_documentation(visibility: internal) import struct HummingbirdCore.Response -@_exported @_documentation(visibility: internal) import struct HummingbirdCore.ResponseBody -@_exported @_documentation(visibility: internal) import protocol HummingbirdCore.ResponseBodyWriter -#if canImport(Network) -@_exported @_documentation(visibility: internal) import struct HummingbirdCore.TSTLSOptions -#endif - -@_exported @_documentation(visibility: internal) import struct NIOCore.ByteBuffer -@_exported @_documentation(visibility: internal) import struct NIOCore.ByteBufferAllocator - @_exported @_documentation(visibility: internal) import struct HTTPTypes.HTTPFields @_exported @_documentation(visibility: internal) import struct HTTPTypes.HTTPRequest @_exported @_documentation(visibility: internal) import struct HTTPTypes.HTTPResponse - +@_exported @_documentation(visibility: internal) import struct HummingbirdCore.BindAddress // Temporary exports of unavailable typealiases @_exported @_documentation(visibility: internal) import struct HummingbirdCore.HBRequest @_exported @_documentation(visibility: internal) import struct HummingbirdCore.HBRequestBody @_exported @_documentation(visibility: internal) import struct HummingbirdCore.HBResponse @_exported @_documentation(visibility: internal) import struct HummingbirdCore.HBResponseBody @_exported @_documentation(visibility: internal) import protocol HummingbirdCore.HBResponseBodyWriter +@_exported @_documentation(visibility: internal) import struct HummingbirdCore.Request +@_exported @_documentation(visibility: internal) import struct HummingbirdCore.RequestBody +@_exported @_documentation(visibility: internal) import struct HummingbirdCore.Response +@_exported @_documentation(visibility: internal) import struct HummingbirdCore.ResponseBody +@_exported @_documentation(visibility: internal) import protocol HummingbirdCore.ResponseBodyWriter +@_exported @_documentation(visibility: internal) import struct NIOCore.ByteBuffer +@_exported @_documentation(visibility: internal) import struct NIOCore.ByteBufferAllocator + +#if canImport(Network) +@_exported @_documentation(visibility: internal) import struct HummingbirdCore.TSTLSOptions +#endif diff --git a/Sources/Hummingbird/Files/FileIO.swift b/Sources/Hummingbird/Files/FileIO.swift index a485750d..46620188 100644 --- a/Sources/Hummingbird/Files/FileIO.swift +++ b/Sources/Hummingbird/Files/FileIO.swift @@ -36,7 +36,11 @@ public struct FileIO: Sendable { /// - context: Context this request is being called in /// - chunkLength: Size of the chunks read from disk and loaded into memory (in bytes). Defaults to the value suggested by `swift-nio`. /// - Returns: Response body - public func loadFile(path: String, context: some RequestContext, chunkLength: Int = NonBlockingFileIO.defaultChunkSize) async throws -> ResponseBody { + public func loadFile( + path: String, + context: some RequestContext, + chunkLength: Int = NonBlockingFileIO.defaultChunkSize + ) async throws -> ResponseBody { do { let stat = try await fileIO.lstat(path: path) guard stat.st_size > 0 else { return .init() } @@ -56,7 +60,12 @@ public struct FileIO: Sendable { /// - context: Context this request is being called in /// - chunkLength: Size of the chunks read from disk and loaded into memory (in bytes). Defaults to the value suggested by `swift-nio`. /// - Returns: Response body plus file size - public func loadFile(path: String, range: ClosedRange, context: some RequestContext, chunkLength: Int = NonBlockingFileIO.defaultChunkSize) async throws -> ResponseBody { + public func loadFile( + path: String, + range: ClosedRange, + context: some RequestContext, + chunkLength: Int = NonBlockingFileIO.defaultChunkSize + ) async throws -> ResponseBody { do { let stat = try await fileIO.lstat(path: path) guard stat.st_size > 0 else { return .init() } @@ -105,8 +114,13 @@ public struct FileIO: Sendable { } /// Return response body that will read file - func readFile(path: String, range: ClosedRange, context: some RequestContext, chunkLength: Int = NonBlockingFileIO.defaultChunkSize) -> ResponseBody { - return ResponseBody(contentLength: range.count) { writer in + func readFile( + path: String, + range: ClosedRange, + context: some RequestContext, + chunkLength: Int = NonBlockingFileIO.defaultChunkSize + ) -> ResponseBody { + ResponseBody(contentLength: range.count) { writer in try await self.fileIO.withFileHandle(path: path, mode: .read) { handle in let endOffset = range.endIndex let chunkLength = chunkLength diff --git a/Sources/Hummingbird/HTTP/Cookie.swift b/Sources/Hummingbird/HTTP/Cookie.swift index 3de7c534..47388ded 100644 --- a/Sources/Hummingbird/HTTP/Cookie.swift +++ b/Sources/Hummingbird/HTTP/Cookie.swift @@ -33,20 +33,20 @@ public struct Cookie: Sendable, CustomStringConvertible { public let properties: Properties /// indicates the maximum lifetime of the cookie - public var expires: Date? { return self.properties[.expires].map { DateCache.rfc1123Formatter.date(from: $0) } ?? nil } + public var expires: Date? { self.properties[.expires].map { DateCache.rfc1123Formatter.date(from: $0) } ?? nil } /// indicates the maximum lifetime of the cookie in seconds. Max age has precedence over expires /// (not all user agents support max-age) - public var maxAge: Int? { return self.properties[.maxAge].map { Int($0) } ?? nil } + public var maxAge: Int? { self.properties[.maxAge].map { Int($0) } ?? nil } /// specifies those hosts to which the cookie will be sent - public var domain: String? { return self.properties[.domain] } + public var domain: String? { self.properties[.domain] } /// The scope of each cookie is limited to a set of paths, controlled by the Path attribute - public var path: String? { return self.properties[.path] } + public var path: String? { self.properties[.path] } /// The Secure attribute limits the scope of the cookie to "secure" channels - public var secure: Bool { return self.properties[.secure] != nil } + public var secure: Bool { self.properties[.secure] != nil } /// The HttpOnly attribute limits the scope of the cookie to HTTP requests - public var httpOnly: Bool { return self.properties[.httpOnly] != nil } + public var httpOnly: Bool { self.properties[.httpOnly] != nil } /// The SameSite attribute lets servers specify whether/when cookies are sent with cross-origin requests - public var sameSite: SameSite? { return self.properties[.sameSite].map { SameSite(rawValue: $0) } ?? nil } + public var sameSite: SameSite? { self.properties[.sameSite].map { SameSite(rawValue: $0) } ?? nil } /// Create `Cookie` /// - Parameters: diff --git a/Sources/Hummingbird/HTTP/Cookies.swift b/Sources/Hummingbird/HTTP/Cookies.swift index faceb4c7..69cc4920 100644 --- a/Sources/Hummingbird/HTTP/Cookies.swift +++ b/Sources/Hummingbird/HTTP/Cookies.swift @@ -20,16 +20,18 @@ public struct Cookies: Sendable { /// - Parameter request: request to get cookies from init(from request: Request) { self.cookieStrings = request.headers[values: .cookie].flatMap { - return $0.split(separator: ";").map { $0.drop { $0.isWhitespace } } + $0.split(separator: ";").map { $0.drop { $0.isWhitespace } } } } /// access cookies via dictionary subscript public subscript(_ key: String) -> Cookie? { - guard let cookieString = cookieStrings.first(where: { - guard let cookieName = Cookie.getName(from: $0) else { return false } - return cookieName == key - }) else { + guard + let cookieString = cookieStrings.first(where: { + guard let cookieName = Cookie.getName(from: $0) else { return false } + return cookieName == key + }) + else { return nil } return Cookie(from: cookieString) diff --git a/Sources/Hummingbird/HTTP/MediaType.swift b/Sources/Hummingbird/HTTP/MediaType.swift index 436e6c9a..1bc8551d 100644 --- a/Sources/Hummingbird/HTTP/MediaType.swift +++ b/Sources/Hummingbird/HTTP/MediaType.swift @@ -100,7 +100,7 @@ public struct MediaType: Sendable, CustomStringConvertible { } } if let category, - let subCategory + let subCategory { self.type = category self.subType = subCategory.lowercased() @@ -112,7 +112,7 @@ public struct MediaType: Sendable, CustomStringConvertible { /// Return media type with new parameter public func withParameter(name: String, value: String) -> MediaType { - return .init(type: self.type, subType: self.subType, parameter: (name, value)) + .init(type: self.type, subType: self.subType, parameter: (name, value)) } /// Output @@ -127,7 +127,7 @@ public struct MediaType: Sendable, CustomStringConvertible { /// Return if media type matches the input public func isType(_ type: MediaType) -> Bool { guard self.type == type.type, - self.subType == type.subType || type.subType == "*" + self.subType == type.subType || type.subType == "*" else { return false } @@ -142,7 +142,7 @@ public struct MediaType: Sendable, CustomStringConvertible { /// - Parameter extension: file extension /// - Returns: media type public static func getMediaType(forExtension extension: String) -> MediaType? { - return extensionMediaTypeMap[`extension`] + extensionMediaTypeMap[`extension`] } /// Media type categories diff --git a/Sources/Hummingbird/Middleware/FileMiddleware.swift b/Sources/Hummingbird/Middleware/FileMiddleware.swift index e109b193..4b64d8fb 100644 --- a/Sources/Hummingbird/Middleware/FileMiddleware.swift +++ b/Sources/Hummingbird/Middleware/FileMiddleware.swift @@ -41,7 +41,8 @@ public protocol FileMiddlewareFileAttributes { /// "if-modified-since", "if-none-match", "if-range" and 'range" headers. It will output "content-length", /// "modified-date", "eTag", "content-type", "cache-control" and "content-range" headers where /// they are relevant. -public struct FileMiddleware: RouterMiddleware where Provider.FileAttributes: FileMiddlewareFileAttributes { +public struct FileMiddleware: RouterMiddleware +where Provider.FileAttributes: FileMiddlewareFileAttributes { let cacheControl: CacheControl let searchForIndexHtml: Bool let urlBasePath: String? @@ -174,7 +175,7 @@ extension FileMiddleware { /// Return file attributes, and actual file path private func getFileAttributes(_ path: String) async throws -> (path: String, id: Provider.FileIdentifier, attributes: Provider.FileAttributes) { guard let id = self.fileProvider.getFileIdentifier(path), - let attributes = try await self.fileProvider.getAttributes(id: id) + let attributes = try await self.fileProvider.getAttributes(id: id) else { throw HTTPError(.notFound) } @@ -184,7 +185,7 @@ extension FileMiddleware { guard self.searchForIndexHtml else { throw HTTPError(.notFound) } let indexPath = self.appendingPathComponent(path, "index.html") guard let indexID = self.fileProvider.getFileIdentifier(indexPath), - let indexAttributes = try await self.fileProvider.getAttributes(id: indexID) + let indexAttributes = try await self.fileProvider.getAttributes(id: indexID) else { throw HTTPError(.notFound) } @@ -286,7 +287,8 @@ extension FileMiddleware { return lowerBound...Int.max } else { guard let lowerBound = Int(lower), - let upperBound = Int(upper) else { return nil } + let upperBound = Int(upper) + else { return nil } return lowerBound...upperBound } } catch { @@ -296,7 +298,7 @@ extension FileMiddleware { private func createETag(_ strings: [String]) -> String { let string = strings.joined(separator: "-") - let buffer = Array(unsafeUninitializedCapacity: 16) { bytes, size in + let buffer = [UInt8](unsafeUninitializedCapacity: 16) { bytes, size in var index = 0 for i in 0..<16 { bytes[i] = 0 diff --git a/Sources/Hummingbird/Middleware/LogRequestMiddleware.swift b/Sources/Hummingbird/Middleware/LogRequestMiddleware.swift index 922c9721..5c50aebd 100644 --- a/Sources/Hummingbird/Middleware/LogRequestMiddleware.swift +++ b/Sources/Hummingbird/Middleware/LogRequestMiddleware.swift @@ -58,16 +58,17 @@ public struct LogRequestsMiddleware: RouterMiddleware { self.logLevel = logLevel self.includeHeaders = includeHeaders // only include headers in the redaction list if we are outputting them - self.redactHeaders = switch includeHeaders.value { - case .all(let exceptions): - // don't include headers in the except list - redactHeaders.filter { header in !exceptions.contains(header) } - case .some(let included): - // only include headers in the included list - redactHeaders.filter { header in included.contains(header) } - case .none: - [] - } + self.redactHeaders = + switch includeHeaders.value { + case .all(let exceptions): + // don't include headers in the except list + redactHeaders.filter { header in !exceptions.contains(header) } + case .some(let included): + // only include headers in the included list + redactHeaders.filter { header in included.contains(header) } + case .none: + [] + } } public func handle(_ request: Request, context: Context, next: (Request, Context) async throws -> Response) async throws -> Response { @@ -106,7 +107,8 @@ public struct LogRequestsMiddleware: RouterMiddleware { } func filterHeaders(headers: HTTPFields, filter: [HTTPField.Name]) -> [String: String] { - let headers = filter + let headers = + filter .compactMap { entry -> (key: String, value: String)? in guard let value = headers[entry] else { return nil } if self.redactHeaders.contains(entry) { @@ -119,7 +121,8 @@ public struct LogRequestsMiddleware: RouterMiddleware { } func allHeaders(headers: HTTPFields, except: [HTTPField.Name]) -> [String: String] { - let headers = headers + let headers = + headers .compactMap { entry -> (key: String, value: String)? in if except.contains(where: { entry.name == $0 }) { return nil } if self.redactHeaders.contains(entry.name) { diff --git a/Sources/Hummingbird/Middleware/Middleware.swift b/Sources/Hummingbird/Middleware/Middleware.swift index 65bcaa56..78ea74a0 100644 --- a/Sources/Hummingbird/Middleware/Middleware.swift +++ b/Sources/Hummingbird/Middleware/Middleware.swift @@ -57,7 +57,7 @@ struct MiddlewareResponder: HTTPResponder { let next: @Sendable (Request, Context) async throws -> Response func respond(to request: Request, context: Context) async throws -> Response { - return try await self.middleware.handle(request, context: context) { request, context in + try await self.middleware.handle(request, context: context) { request, context in try await self.next(request, context) } } diff --git a/Sources/Hummingbird/Middleware/MiddlewareModule/MiddlewareFixedTypeBuilder.swift b/Sources/Hummingbird/Middleware/MiddlewareModule/MiddlewareFixedTypeBuilder.swift index 5089cd25..a270f30b 100644 --- a/Sources/Hummingbird/Middleware/MiddlewareModule/MiddlewareFixedTypeBuilder.swift +++ b/Sources/Hummingbird/Middleware/MiddlewareModule/MiddlewareFixedTypeBuilder.swift @@ -19,11 +19,11 @@ @resultBuilder public enum MiddlewareFixedTypeBuilder { public static func buildExpression(_ m0: M0) -> M0 where M0.Input == Input, M0.Output == Output, M0.Context == Context { - return m0 + m0 } public static func buildBlock(_ m0: M0) -> M0 { - return m0 + m0 } public static func buildPartialBlock(first: M0) -> M0 { @@ -54,6 +54,6 @@ public enum MiddlewareFixedTypeBuilder { } public static func buildArray(_ components: [M0]) -> _SpreadMiddleware { - return _SpreadMiddleware(middlewares: components) + _SpreadMiddleware(middlewares: components) } } diff --git a/Sources/Hummingbird/Middleware/MiddlewareModule/_Middleware2.swift b/Sources/Hummingbird/Middleware/MiddlewareModule/_Middleware2.swift index ed866157..d7c6a99c 100644 --- a/Sources/Hummingbird/Middleware/MiddlewareModule/_Middleware2.swift +++ b/Sources/Hummingbird/Middleware/MiddlewareModule/_Middleware2.swift @@ -25,7 +25,8 @@ /// } /// ``` @_documentation(visibility: internal) -public struct _Middleware2: MiddlewareProtocol where M0.Input == M1.Input, M0.Context == M1.Context, M0.Output == M1.Output { +public struct _Middleware2: MiddlewareProtocol +where M0.Input == M1.Input, M0.Context == M1.Context, M0.Output == M1.Output { public typealias Input = M0.Input public typealias Output = M0.Output public typealias Context = M0.Context diff --git a/Sources/Hummingbird/Middleware/MiddlewareModule/_SpreadMiddleware.swift b/Sources/Hummingbird/Middleware/MiddlewareModule/_SpreadMiddleware.swift index 2de7f5ab..13f02aba 100644 --- a/Sources/Hummingbird/Middleware/MiddlewareModule/_SpreadMiddleware.swift +++ b/Sources/Hummingbird/Middleware/MiddlewareModule/_SpreadMiddleware.swift @@ -37,14 +37,23 @@ public struct _SpreadMiddleware: MiddlewareProtocol { public func handle(_ input: Input, context: Context, next: (Input, Context) async throws -> Output) async throws -> Output { return try await handle(middlewares: self.middlewares, input: input, context: context, next: next) - func handle(middlewares: some Collection, input: Input, context: Context, next: (Input, Context) async throws -> Output) async throws -> Output { + func handle( + middlewares: some Collection, + input: Input, + context: Context, + next: (Input, Context) async throws -> Output + ) async throws -> Output { guard let current = middlewares.first else { return try await next(input, context) } - return try await current.handle(input, context: context, next: { input, context in - try await handle(middlewares: middlewares.dropFirst(), input: input, context: context, next: next) - }) + return try await current.handle( + input, + context: context, + next: { input, context in + try await handle(middlewares: middlewares.dropFirst(), input: input, context: context, next: next) + } + ) } } } diff --git a/Sources/Hummingbird/Router/EndpointResponder.swift b/Sources/Hummingbird/Router/EndpointResponder.swift index 6726af07..a0714e9e 100644 --- a/Sources/Hummingbird/Router/EndpointResponder.swift +++ b/Sources/Hummingbird/Router/EndpointResponder.swift @@ -24,7 +24,7 @@ struct EndpointResponders: Sendable { @inlinable public func getResponder(for method: __shared HTTPRequest.Method) -> (any HTTPResponder)? { - return self.methods[method] + self.methods[method] } mutating func addResponder(for method: HTTPRequest.Method, responder: any HTTPResponder) { diff --git a/Sources/Hummingbird/Router/Parameters+UUID.swift b/Sources/Hummingbird/Router/Parameters+UUID.swift index feee602b..6dbcfb90 100644 --- a/Sources/Hummingbird/Router/Parameters+UUID.swift +++ b/Sources/Hummingbird/Router/Parameters+UUID.swift @@ -22,7 +22,7 @@ extension Parameters { /// - s: parameter id /// - as: type we want returned public func get(_ s: String, as: UUID.Type) -> UUID? { - return self[s[...]].map { UUID(uuidString: String($0)) } ?? nil + self[s[...]].map { UUID(uuidString: String($0)) } ?? nil } /// Return parameter with specified id as a certain type @@ -45,7 +45,7 @@ extension Parameters { /// - s: parameter id /// - as: type we want returned public func getAll(_ s: String, as: UUID.Type) -> [UUID] { - return self[values: s[...]].compactMap { UUID(uuidString: String($0)) } + self[values: s[...]].compactMap { UUID(uuidString: String($0)) } } /// Return parameter with specified id as a certain type @@ -53,7 +53,7 @@ extension Parameters { /// - s: parameter id /// - as: type we want returned public func requireAll(_ s: String, as: UUID.Type) throws -> [UUID] { - return try self[values: s[...]].map { + try self[values: s[...]].map { guard let result = UUID(uuidString: String($0)) else { throw HTTPError(.badRequest, message: "One of the parameters '\($0)' can not be converted to the expected type (UUID)") } diff --git a/Sources/Hummingbird/Router/Parameters.swift b/Sources/Hummingbird/Router/Parameters.swift index dc9353e9..04586bb2 100644 --- a/Sources/Hummingbird/Router/Parameters.swift +++ b/Sources/Hummingbird/Router/Parameters.swift @@ -19,32 +19,32 @@ import HummingbirdCore /// from URIs public typealias Parameters = FlatDictionary -public extension Parameters { +extension Parameters { /// Return parameter with specified id /// - Parameter s: parameter id - func get(_ s: String) -> String? { - return self[s[...]].map { String($0) } + public func get(_ s: String) -> String? { + self[s[...]].map { String($0) } } /// Return parameter with specified id as a certain type /// - Parameters: /// - s: parameter id /// - as: type we want returned - func get(_ s: String, as: T.Type) -> T? { - return self[s[...]].map { T(String($0)) } ?? nil + public func get(_ s: String, as: T.Type) -> T? { + self[s[...]].map { T(String($0)) } ?? nil } /// Return parameter with specified id as a certain type /// - Parameters: /// - s: parameter id /// - as: type we want returned - func get(_ s: String, as: T.Type) -> T? where T.RawValue == String { - return self[s[...]].map { T(rawValue: String($0)) } ?? nil + public func get(_ s: String, as: T.Type) -> T? where T.RawValue == String { + self[s[...]].map { T(rawValue: String($0)) } ?? nil } /// Return parameter with specified id /// - Parameter s: parameter id - func require(_ s: String) throws -> String { + public func require(_ s: String) throws -> String { guard let param = self[s[...]].map({ String($0) }) else { throw HTTPError(.badRequest, message: "Expected parameter does not exist") } @@ -55,7 +55,7 @@ public extension Parameters { /// - Parameters: /// - s: parameter id /// - as: type we want returned - func require(_ s: String, as: T.Type) throws -> T { + public func require(_ s: String, as: T.Type) throws -> T { guard let param = self[s[...]] else { throw HTTPError(.badRequest, message: "Expected parameter does not exist") } @@ -70,7 +70,7 @@ public extension Parameters { /// - Parameters: /// - s: parameter id /// - as: type we want returned - func require(_ s: String, as: T.Type) throws -> T where T.RawValue == String { + public func require(_ s: String, as: T.Type) throws -> T where T.RawValue == String { guard let param = self[s[...]] else { throw HTTPError(.badRequest, message: "Expected parameter does not exist") } @@ -84,32 +84,32 @@ public extension Parameters { /// Return parameter with specified id as a certain type /// - Parameters: /// - s: parameter id - func getAll(_ s: String) -> [String] { - return self[values: s[...]].compactMap { String($0) } + public func getAll(_ s: String) -> [String] { + self[values: s[...]].compactMap { String($0) } } /// Return parameter with specified id as a certain type /// - Parameters: /// - s: parameter id /// - as: type we want returned - func getAll(_ s: String, as: T.Type) -> [T] { - return self[values: s[...]].compactMap { T(String($0)) } + public func getAll(_ s: String, as: T.Type) -> [T] { + self[values: s[...]].compactMap { T(String($0)) } } /// Return parameter with specified id as a certain type /// - Parameters: /// - s: parameter id /// - as: type we want returned - func getAll(_ s: String, as: T.Type) -> [T] where T.RawValue == String { - return self[values: s[...]].compactMap { T(rawValue: String($0)) } + public func getAll(_ s: String, as: T.Type) -> [T] where T.RawValue == String { + self[values: s[...]].compactMap { T(rawValue: String($0)) } } /// Return parameter with specified id as a certain type /// - Parameters: /// - s: parameter id /// - as: type we want returned - func requireAll(_ s: String, as: T.Type) throws -> [T] { - return try self[values: s[...]].map { + public func requireAll(_ s: String, as: T.Type) throws -> [T] { + try self[values: s[...]].map { guard let result = T(String($0)) else { throw HTTPError(.badRequest, message: "One of the parameters '\($0)' can not be converted to the expected type (\(T.self))") } @@ -121,8 +121,8 @@ public extension Parameters { /// - Parameters: /// - s: parameter id /// - as: type we want returned - func requireAll(_ s: String, as: T.Type) throws -> [T] where T.RawValue == String { - return try self[values: s[...]].map { + public func requireAll(_ s: String, as: T.Type) throws -> [T] where T.RawValue == String { + try self[values: s[...]].map { guard let result = T(rawValue: String($0)) else { throw HTTPError(.badRequest, message: "One of the parameters '\($0)' can not be converted to the expected type (\(T.self))") } @@ -132,18 +132,18 @@ public extension Parameters { } /// Catch all support -public extension Parameters { - static let recursiveCaptureKey: Substring = ":**:" +extension Parameters { + public static let recursiveCaptureKey: Substring = ":**:" /// Return path elements caught by recursive capture - func getCatchAll() -> [Substring] { - return self[Self.recursiveCaptureKey].map { $0.split(separator: "/", omittingEmptySubsequences: true) } ?? [] + public func getCatchAll() -> [Substring] { + self[Self.recursiveCaptureKey].map { $0.split(separator: "/", omittingEmptySubsequences: true) } ?? [] } /// Set path components caught by recursive capture /// - Parameters: /// - value: parameter value - mutating func setCatchAll(_ value: Substring) { + public mutating func setCatchAll(_ value: Substring) { guard !self.has(Self.recursiveCaptureKey) else { return } self[Self.recursiveCaptureKey] = value } diff --git a/Sources/Hummingbird/Router/RouterMethods.swift b/Sources/Hummingbird/Router/RouterMethods.swift index 4b61d7d9..9633bf62 100644 --- a/Sources/Hummingbird/Router/RouterMethods.swift +++ b/Sources/Hummingbird/Router/RouterMethods.swift @@ -51,7 +51,7 @@ extension RouterMethods { /// Return a group inside the current group /// - Parameter path: path prefix to add to routes inside this group public func group(_ path: RouterPath = "") -> RouterGroup { - return RouterGroup( + RouterGroup( path: path, parent: self ) @@ -77,7 +77,7 @@ extension RouterMethods { _ path: RouterPath = "", context: TargetContext.Type ) -> RouterGroup where TargetContext.Source == Context { - return RouterGroup( + RouterGroup( path: path, parent: TransformingRouterGroup(parent: self) ) @@ -103,7 +103,7 @@ extension RouterMethods { _ path: RouterPath = "", context: TargetContext.Type ) -> RouterGroup where TargetContext.ParentContext == Context { - return RouterGroup( + RouterGroup( path: path, parent: ThrowingTransformingRouterGroup(parent: self) ) @@ -127,7 +127,7 @@ extension RouterMethods { @discardableResult public func addMiddleware( @MiddlewareFixedTypeBuilder buildMiddlewareStack: () -> some MiddlewareProtocol ) -> Self { - return self.add(middleware: buildMiddlewareStack()) + self.add(middleware: buildMiddlewareStack()) } /// GET path for async closure returning type conforming to ResponseGenerator @@ -135,7 +135,7 @@ extension RouterMethods { _ path: RouterPath = "", use handler: @Sendable @escaping (Request, Context) async throws -> some ResponseGenerator ) -> Self { - return self.on(path, method: .get, use: handler) + self.on(path, method: .get, use: handler) } /// PUT path for async closure returning type conforming to ResponseGenerator @@ -143,7 +143,7 @@ extension RouterMethods { _ path: RouterPath = "", use handler: @Sendable @escaping (Request, Context) async throws -> some ResponseGenerator ) -> Self { - return self.on(path, method: .put, use: handler) + self.on(path, method: .put, use: handler) } /// DELETE path for async closure returning type conforming to ResponseGenerator @@ -151,7 +151,7 @@ extension RouterMethods { _ path: RouterPath = "", use handler: @Sendable @escaping (Request, Context) async throws -> some ResponseGenerator ) -> Self { - return self.on(path, method: .delete, use: handler) + self.on(path, method: .delete, use: handler) } /// HEAD path for async closure returning type conforming to ResponseGenerator @@ -159,7 +159,7 @@ extension RouterMethods { _ path: RouterPath = "", use handler: @Sendable @escaping (Request, Context) async throws -> some ResponseGenerator ) -> Self { - return self.on(path, method: .head, use: handler) + self.on(path, method: .head, use: handler) } /// POST path for async closure returning type conforming to ResponseGenerator @@ -167,7 +167,7 @@ extension RouterMethods { _ path: RouterPath = "", use handler: @Sendable @escaping (Request, Context) async throws -> some ResponseGenerator ) -> Self { - return self.on(path, method: .post, use: handler) + self.on(path, method: .post, use: handler) } /// PATCH path for async closure returning type conforming to ResponseGenerator @@ -175,13 +175,13 @@ extension RouterMethods { _ path: RouterPath = "", use handler: @Sendable @escaping (Request, Context) async throws -> some ResponseGenerator ) -> Self { - return self.on(path, method: .patch, use: handler) + self.on(path, method: .patch, use: handler) } internal func constructResponder( use closure: @Sendable @escaping (Request, Context) async throws -> some ResponseGenerator ) -> CallbackResponder { - return CallbackResponder { request, context in + CallbackResponder { request, context in let output = try await closure(request, context) return try output.response(from: request, context: context) } diff --git a/Sources/Hummingbird/Router/RouterPath.swift b/Sources/Hummingbird/Router/RouterPath.swift index f9e158c9..6ef5247a 100644 --- a/Sources/Hummingbird/Router/RouterPath.swift +++ b/Sources/Hummingbird/Router/RouterPath.swift @@ -18,11 +18,11 @@ public struct RouterPath: Sendable, ExpressibleByStringLiteral, ExpressibleByStr package enum _Internal: Equatable, Sendable { case path(Substring) case capture(Substring) - case prefixCapture(suffix: Substring, parameter: Substring) // *.jpg - case suffixCapture(prefix: Substring, parameter: Substring) // file.* + case prefixCapture(suffix: Substring, parameter: Substring) // *.jpg + case suffixCapture(prefix: Substring, parameter: Substring) // file.* case wildcard - case prefixWildcard(Substring) // *.jpg - case suffixWildcard(Substring) // file.* + case prefixWildcard(Substring) // *.jpg + case suffixWildcard(Substring) // file.* case recursiveWildcard case null } @@ -204,11 +204,11 @@ public struct RouterPath: Sendable, ExpressibleByStringLiteral, ExpressibleByStr extension RouterPath: Collection { public func index(after i: Int) -> Int { - return self.components.index(after: i) + self.components.index(after: i) } public subscript(_ index: Int) -> RouterPath.Element { - return self.components[index] + self.components[index] } public var startIndex: Int { self.components.startIndex } diff --git a/Sources/Hummingbird/Router/Trie/Trie+resolve.swift b/Sources/Hummingbird/Router/Trie/Trie+resolve.swift index 2e0ac28c..74a014e7 100644 --- a/Sources/Hummingbird/Router/Trie/Trie+resolve.swift +++ b/Sources/Hummingbird/Router/Trie/Trie+resolve.swift @@ -58,11 +58,13 @@ extension RouterTrie { } var nodeIndex = 1 - guard let node = descend( - component: component, - nextPathComponentIndex: 1, - nodeIndex: &nodeIndex - ) else { + guard + let node = descend( + component: component, + nextPathComponentIndex: 1, + nodeIndex: &nodeIndex + ) + else { return nil } diff --git a/Sources/Hummingbird/Router/Trie/Trie+serialize.swift b/Sources/Hummingbird/Router/Trie/Trie+serialize.swift index e4439f00..f92150ce 100644 --- a/Sources/Hummingbird/Router/Trie/Trie+serialize.swift +++ b/Sources/Hummingbird/Router/Trie/Trie+serialize.swift @@ -41,12 +41,12 @@ extension RouterTrie { token = .path(constantIndex: setStringValue(path)) case .capture(let parameterName): token = .capture(parameterIndex: setStringValue(parameterName)) - case .prefixCapture(suffix: let suffix, parameter: let parameterName): + case .prefixCapture(let suffix, parameter: let parameterName): token = .prefixCapture( parameterIndex: setStringValue(parameterName), suffixIndex: setStringValue(suffix) ) - case .suffixCapture(prefix: let prefix, parameter: let parameterName): + case .suffixCapture(let prefix, parameter: let parameterName): token = .suffixCapture( prefixIndex: setStringValue(prefix), parameterIndex: setStringValue(parameterName) diff --git a/Sources/Hummingbird/Router/TrieRouter.swift b/Sources/Hummingbird/Router/TrieRouter.swift index 03b86511..02ad09c6 100644 --- a/Sources/Hummingbird/Router/TrieRouter.swift +++ b/Sources/Hummingbird/Router/TrieRouter.swift @@ -73,7 +73,7 @@ import HummingbirdCore } func getChild(_ key: RouterPath.Element) -> Node? { - return self.children.first { $0.key == key } + self.children.first { $0.key == key } } func getChild(_ key: Substring) -> Node? { diff --git a/Sources/Hummingbird/Server/Request.swift b/Sources/Hummingbird/Server/Request.swift index df8b0eec..96fab5ad 100644 --- a/Sources/Hummingbird/Server/Request.swift +++ b/Sources/Hummingbird/Server/Request.swift @@ -57,7 +57,7 @@ extension Request { } } -internal extension CodingKey { +extension CodingKey { /// returns a coding key as a path key string var pathKeyValue: String { if let value = intValue { @@ -67,7 +67,7 @@ internal extension CodingKey { } } -internal extension Array { +extension [CodingKey] { /// returns a path key using a dot character as a separator var pathKeyValue: String { map(\.pathKeyValue).joined(separator: ".") diff --git a/Sources/Hummingbird/Server/Response.swift b/Sources/Hummingbird/Server/Response.swift index 8db63925..3c2da07a 100644 --- a/Sources/Hummingbird/Server/Response.swift +++ b/Sources/Hummingbird/Server/Response.swift @@ -51,6 +51,6 @@ extension Response { /// - type: Redirection type /// - Returns: Response with redirection public static func redirect(to location: String, type: RedirectType = .normal) -> Response { - return .init(status: type.status, headers: [.location: location]) + .init(status: type.status, headers: [.location: location]) } } diff --git a/Sources/Hummingbird/Utils/DateCache.swift b/Sources/Hummingbird/Utils/DateCache.swift index c41707de..780fe3db 100644 --- a/Sources/Hummingbird/Utils/DateCache.swift +++ b/Sources/Hummingbird/Utils/DateCache.swift @@ -16,6 +16,8 @@ import AsyncAlgorithms import Atomics import NIOCore import NIOPosix +import ServiceLifecycle + #if canImport(Glibc) import Glibc #elseif canImport(Musl) @@ -25,7 +27,6 @@ import Darwin.C #else #error("Unsupported platform") #endif -import ServiceLifecycle /// Current date formatted cache service /// @@ -57,7 +58,7 @@ final class DateCache: Service { } public var date: String { - return self.dateContainer.load(ordering: .acquiring).date + self.dateContainer.load(ordering: .acquiring).date } /// Render Epoch seconds as RFC1123 formatted date diff --git a/Sources/Hummingbird/Utils/HexDigest.swift b/Sources/Hummingbird/Utils/HexDigest.swift index 96265995..65031aeb 100644 --- a/Sources/Hummingbird/Utils/HexDigest.swift +++ b/Sources/Hummingbird/Utils/HexDigest.swift @@ -15,7 +15,7 @@ extension Sequence { /// return a hexEncoded string buffer from an array of bytes func hexDigest() -> String { - return self.map { String($0, radix: 16, padding: 2) }.joined(separator: "") + self.map { String($0, radix: 16, padding: 2) }.joined(separator: "") } } diff --git a/Sources/HummingbirdCore/Request/URI.swift b/Sources/HummingbirdCore/Request/URI.swift index b7c0d582..ebdbaf61 100644 --- a/Sources/HummingbirdCore/Request/URI.swift +++ b/Sources/HummingbirdCore/Request/URI.swift @@ -21,27 +21,27 @@ public struct URI: Sendable, CustomStringConvertible, ExpressibleByStringLiteral self.rawValue = rawValue } - public static var http: Self { return .init(rawValue: "http") } - public static var https: Self { return .init(rawValue: "https") } - public static var unix: Self { return .init(rawValue: "unix") } - public static var http_unix: Self { return .init(rawValue: "http_unix") } - public static var https_unix: Self { return .init(rawValue: "https_unix") } - public static var ws: Self { return .init(rawValue: "ws") } - public static var wss: Self { return .init(rawValue: "wss") } + public static var http: Self { .init(rawValue: "http") } + public static var https: Self { .init(rawValue: "https") } + public static var unix: Self { .init(rawValue: "unix") } + public static var http_unix: Self { .init(rawValue: "http_unix") } + public static var https_unix: Self { .init(rawValue: "https_unix") } + public static var ws: Self { .init(rawValue: "ws") } + public static var wss: Self { .init(rawValue: "wss") } } public let string: String /// URL scheme - public var scheme: Scheme? { return self._scheme.map { .init(rawValue: $0.string) } } + public var scheme: Scheme? { self._scheme.map { .init(rawValue: $0.string) } } /// URL host - public var host: String? { return self._host.map(\.string) } + public var host: String? { self._host.map(\.string) } /// URL port - public var port: Int? { return self._port.map { Int($0.string) } ?? nil } + public var port: Int? { self._port.map { Int($0.string) } ?? nil } /// URL path - public var path: String { return self._path.map(\.string) ?? "/" } + public var path: String { self._path.map(\.string) ?? "/" } /// URL query - public var query: String? { return self._query.map { String($0.string) }} + public var query: String? { self._query.map { String($0.string) } } /// URL query parameter map public var queryParameters: FlatDictionary { guard var query = _query else { diff --git a/Sources/HummingbirdCore/Response/ResponseBody.swift b/Sources/HummingbirdCore/Response/ResponseBody.swift index c4ebc86b..66387be0 100644 --- a/Sources/HummingbirdCore/Response/ResponseBody.swift +++ b/Sources/HummingbirdCore/Response/ResponseBody.swift @@ -101,7 +101,7 @@ public struct ResponseBody: Sendable { /// response has been fully written. If you drop the response in a middleware run after this /// point the post write closure will not get run. package func withPostWriteClosure(_ postWrite: @escaping @Sendable () async -> Void) -> Self { - return .init(contentLength: self.contentLength) { writer in + .init(contentLength: self.contentLength) { writer in do { try await self.write(writer) await postWrite() diff --git a/Sources/HummingbirdCore/Server/HTTP/HTTP1Channel.swift b/Sources/HummingbirdCore/Server/HTTP/HTTP1Channel.swift index ab04c363..4ae4d0af 100644 --- a/Sources/HummingbirdCore/Server/HTTP/HTTP1Channel.swift +++ b/Sources/HummingbirdCore/Server/HTTP/HTTP1Channel.swift @@ -75,11 +75,11 @@ public struct HTTP1Channel: ServerChildChannel, HTTPChannelHandler { /// - logger: Logger used during setup /// - Returns: Object to process input/output on child channel public func setup(channel: Channel, logger: Logger) -> EventLoopFuture { - return channel.eventLoop.makeCompletedFuture { + channel.eventLoop.makeCompletedFuture { try channel.pipeline.syncOperations.configureHTTPServerPipeline( - withPipeliningAssistance: false, // HTTP is pipelined by NIOAsyncChannel + withPipeliningAssistance: false, // HTTP is pipelined by NIOAsyncChannel withErrorHandling: true, - withOutboundHeaderValidation: false // Swift HTTP Types are already doing this validation + withOutboundHeaderValidation: false // Swift HTTP Types are already doing this validation ) try channel.pipeline.syncOperations.addHandler(HTTP1ToHTTPServerCodec(secure: false)) try channel.pipeline.syncOperations.addHandlers(self.configuration.additionalChannelHandlers()) diff --git a/Sources/HummingbirdCore/Server/HTTP/HTTPServerBuilder.swift b/Sources/HummingbirdCore/Server/HTTP/HTTPServerBuilder.swift index e02f2cae..d9954090 100644 --- a/Sources/HummingbirdCore/Server/HTTP/HTTPServerBuilder.swift +++ b/Sources/HummingbirdCore/Server/HTTP/HTTPServerBuilder.swift @@ -67,8 +67,8 @@ extension HTTPServerBuilder { public static func http1( additionalChannelHandlers: @autoclosure @escaping @Sendable () -> [any RemovableChannelHandler] ) -> HTTPServerBuilder { - return .init { responder in - return HTTP1Channel(responder: responder, additionalChannelHandlers: additionalChannelHandlers) + .init { responder in + HTTP1Channel(responder: responder, additionalChannelHandlers: additionalChannelHandlers) } } @@ -86,8 +86,8 @@ extension HTTPServerBuilder { public static func http1( configuration: HTTP1Channel.Configuration = .init() ) -> HTTPServerBuilder { - return .init { responder in - return HTTP1Channel(responder: responder, configuration: configuration) + .init { responder in + HTTP1Channel(responder: responder, configuration: configuration) } } } diff --git a/Sources/HummingbirdCore/Server/Server.swift b/Sources/HummingbirdCore/Server/Server.swift index 17394220..0e15d573 100644 --- a/Sources/HummingbirdCore/Server/Server.swift +++ b/Sources/HummingbirdCore/Server/Server.swift @@ -16,11 +16,12 @@ import Logging import NIOCore import NIOExtras import NIOPosix +import ServiceLifecycle + #if canImport(Network) import Network import NIOTransportServices #endif -import ServiceLifecycle /// HTTP server class public actor Server: Service { @@ -193,17 +194,24 @@ public actor Server: Service { /// Start server /// - Parameter responder: Object that provides responses to requests sent to the server /// - Returns: EventLoopFuture that is fulfilled when server has started - nonisolated func makeServer(childChannelSetup: ChildChannel, configuration: ServerConfiguration) async throws -> (AsyncServerChannel, ServerQuiescingHelper) { + nonisolated func makeServer( + childChannelSetup: ChildChannel, + configuration: ServerConfiguration + ) async throws -> (AsyncServerChannel, ServerQuiescingHelper) { var bootstrap: ServerBootstrapProtocol #if canImport(Network) if let tsBootstrap = self.createTSBootstrap(configuration: configuration) { bootstrap = tsBootstrap } else { #if os(iOS) || os(tvOS) - self.logger.warning("Running BSD sockets on iOS or tvOS is not recommended. Please use NIOTSEventLoopGroup, to run with the Network framework") + self.logger.warning( + "Running BSD sockets on iOS or tvOS is not recommended. Please use NIOTSEventLoopGroup, to run with the Network framework" + ) #endif if configuration.tlsOptions.options != nil { - self.logger.warning("tlsOptions set in Configuration will not be applied to a BSD sockets server. Please use NIOTSEventLoopGroup, to run with the Network framework") + self.logger.warning( + "tlsOptions set in Configuration will not be applied to a BSD sockets server. Please use NIOTSEventLoopGroup, to run with the Network framework" + ) } bootstrap = self.createSocketsBootstrap(configuration: configuration) } @@ -282,7 +290,7 @@ public actor Server: Service { private nonisolated func createSocketsBootstrap( configuration: ServerConfiguration ) -> ServerBootstrap { - return ServerBootstrap(group: self.eventLoopGroup) + ServerBootstrap(group: self.eventLoopGroup) // Specify backlog and enable SO_REUSEADDR for the server itself .serverChannelOption(ChannelOptions.backlog, value: numericCast(configuration.backlog)) .serverChannelOption(ChannelOptions.socketOption(.so_reuseaddr), value: configuration.reuseAddress ? 1 : 0) @@ -295,11 +303,12 @@ public actor Server: Service { private nonisolated func createTSBootstrap( configuration: ServerConfiguration ) -> NIOTSListenerBootstrap? { - guard let bootstrap = NIOTSListenerBootstrap(validatingGroup: self.eventLoopGroup)? - .serverChannelOption(ChannelOptions.socketOption(.so_reuseaddr), value: configuration.reuseAddress ? 1 : 0) - // Set the handlers that are applied to the accepted Channels - .childChannelOption(ChannelOptions.socketOption(.so_reuseaddr), value: configuration.reuseAddress ? 1 : 0) - .childChannelOption(ChannelOptions.allowRemoteHalfClosure, value: true) + guard + let bootstrap = NIOTSListenerBootstrap(validatingGroup: self.eventLoopGroup)? + .serverChannelOption(ChannelOptions.socketOption(.so_reuseaddr), value: configuration.reuseAddress ? 1 : 0) + // Set the handlers that are applied to the accepted Channels + .childChannelOption(ChannelOptions.socketOption(.so_reuseaddr), value: configuration.reuseAddress ? 1 : 0) + .childChannelOption(ChannelOptions.allowRemoteHalfClosure, value: true) else { return nil } diff --git a/Sources/HummingbirdCore/Server/TSTLSOptions.swift b/Sources/HummingbirdCore/Server/TSTLSOptions.swift index ff72dd61..5788f75c 100644 --- a/Sources/HummingbirdCore/Server/TSTLSOptions.swift +++ b/Sources/HummingbirdCore/Server/TSTLSOptions.swift @@ -43,7 +43,7 @@ public struct TSTLSOptions: Sendable { let secIdentity: SecIdentity public static func secIdentity(_ secIdentity: SecIdentity) -> Self { - return .init(secIdentity: secIdentity) + .init(secIdentity: secIdentity) } public static func p12(filename: String, password: String) throws -> Self { @@ -101,7 +101,7 @@ public struct TSTLSOptions: Sendable { /// TSTLSOptions holding options public static func options(_ options: NWProtocolTLS.Options) -> Self { - return .init(value: .some(options)) + .init(value: .some(options)) } public static func options( @@ -117,7 +117,9 @@ public struct TSTLSOptions: Sendable { } public static func options( - clientIdentity: Identity, trustRoots: Certificates = .none, serverName: String? = nil + clientIdentity: Identity, + trustRoots: Certificates = .none, + serverName: String? = nil ) -> Self? { let options = NWProtocolTLS.Options() @@ -143,7 +145,8 @@ public struct TSTLSOptions: Sendable { } sec_protocol_verify_complete(result) } - }, Self.tlsDispatchQueue + }, + Self.tlsDispatchQueue ) } return .init(value: .some(options)) @@ -151,7 +154,7 @@ public struct TSTLSOptions: Sendable { /// Empty TSTLSOptions public static var none: Self { - return .init(value: .none) + .init(value: .none) } var options: NWProtocolTLS.Options? { diff --git a/Sources/HummingbirdCore/Utils/FlatDictionary.swift b/Sources/HummingbirdCore/Utils/FlatDictionary.swift index bdfb2bc3..e238c327 100644 --- a/Sources/HummingbirdCore/Utils/FlatDictionary.swift +++ b/Sources/HummingbirdCore/Utils/FlatDictionary.swift @@ -33,7 +33,7 @@ public struct FlatDictionary: Collection, ExpressibleByDic /// The position of the element just after the last element public var endIndex: Index { self.elements.endIndex } /// Access element at specific position - public subscript(_ index: Index) -> Element { return self.elements[index] } + public subscript(_ index: Index) -> Element { self.elements[index] } /// Returns the index immediately after the given index public func index(after index: Index) -> Index { self.elements.index(after: index) } diff --git a/Sources/HummingbirdCore/Utils/HBParser.swift b/Sources/HummingbirdCore/Utils/HBParser.swift index d96eb098..28f54736 100644 --- a/Sources/HummingbirdCore/Utils/HBParser.swift +++ b/Sources/HummingbirdCore/Utils/HBParser.swift @@ -51,12 +51,12 @@ package struct Parser: Sendable { /// Return contents of parser as a string package var count: Int { - return self.range.count + self.range.count } /// Return contents of parser as a string package var string: String { - return makeString(self.buffer[self.range]) + makeString(self.buffer[self.range]) } private var buffer: [UInt8] @@ -74,20 +74,20 @@ extension Parser { self.range = range precondition(range.startIndex >= 0 && range.endIndex <= self.buffer.endIndex) - precondition(range.startIndex == self.buffer.endIndex || self.buffer[range.startIndex] & 0xC0 != 0x80) // check we arent in the middle of a UTF8 character + precondition(range.startIndex == self.buffer.endIndex || self.buffer[range.startIndex] & 0xC0 != 0x80) // check we arent in the middle of a UTF8 character } /// initialise a parser that parses a section of the buffer attached to this parser func subParser(_ range: Range) -> Parser { - return Parser(self, range: range) + Parser(self, range: range) } } -package extension Parser { +extension Parser { /// Return current character /// - Throws: .overflow /// - Returns: Current character - mutating func character() throws -> Unicode.Scalar { + package mutating func character() throws -> Unicode.Scalar { guard !self.reachedEnd() else { throw Error.overflow } return unsafeCurrentAndAdvance() } @@ -96,10 +96,13 @@ package extension Parser { /// - Parameter char: character to compare against /// - Throws: .overflow /// - Returns: If current character was the one we expected - mutating func read(_ char: Unicode.Scalar) throws -> Bool { + package mutating func read(_ char: Unicode.Scalar) throws -> Bool { let initialIndex = self.index let c = try character() - guard c == char else { self.index = initialIndex; return false } + guard c == char else { + self.index = initialIndex + return false + } return true } @@ -107,10 +110,13 @@ package extension Parser { /// - Parameter characterSet: Set of characters to compare against /// - Throws: .overflow /// - Returns: If current character is in character set - mutating func read(_ characterSet: Set) throws -> Bool { + package mutating func read(_ characterSet: Set) throws -> Bool { let initialIndex = self.index let c = try character() - guard characterSet.contains(c) else { self.index = initialIndex; return false } + guard characterSet.contains(c) else { + self.index = initialIndex + return false + } return true } @@ -118,11 +124,14 @@ package extension Parser { /// - Parameter string: String to compare against /// - Throws: .overflow, .emptyString /// - Returns: If characters at current position equal string - mutating func read(_ string: String) throws -> Bool { + package mutating func read(_ string: String) throws -> Bool { let initialIndex = self.index guard string.count > 0 else { throw Error.emptyString } let subString = try read(count: string.count) - guard subString.string == string else { self.index = initialIndex; return false } + guard subString.string == string else { + self.index = initialIndex + return false + } return true } @@ -130,7 +139,7 @@ package extension Parser { /// - Parameter count: Number of characters to read /// - Throws: .overflow /// - Returns: The string read from the buffer - mutating func read(count: Int) throws -> Parser { + package mutating func read(count: Int) throws -> Parser { var count = count var readEndIndex = self.index while count > 0 { @@ -147,7 +156,7 @@ package extension Parser { /// - Parameter until: Unicode.Scalar to read until /// - Throws: .overflow if we hit the end of the buffer before reading character /// - Returns: String read from buffer - @discardableResult mutating func read(until: Unicode.Scalar, throwOnOverflow: Bool = true) throws -> Parser { + @discardableResult package mutating func read(until: Unicode.Scalar, throwOnOverflow: Bool = true) throws -> Parser { let startIndex = self.index while !self.reachedEnd() { if unsafeCurrent() == until { @@ -166,7 +175,7 @@ package extension Parser { /// - Parameter characterSet: Unicode.Scalar set to check against /// - Throws: .overflow /// - Returns: String read from buffer - @discardableResult mutating func read(until characterSet: Set, throwOnOverflow: Bool = true) throws -> Parser { + @discardableResult package mutating func read(until characterSet: Set, throwOnOverflow: Bool = true) throws -> Parser { let startIndex = self.index while !self.reachedEnd() { if characterSet.contains(unsafeCurrent()) { @@ -185,7 +194,7 @@ package extension Parser { /// - Parameter until: Function to test /// - Throws: .overflow /// - Returns: String read from buffer - @discardableResult mutating func read(until: (Unicode.Scalar) -> Bool, throwOnOverflow: Bool = true) throws -> Parser { + @discardableResult package mutating func read(until: (Unicode.Scalar) -> Bool, throwOnOverflow: Bool = true) throws -> Parser { let startIndex = self.index while !self.reachedEnd() { if until(unsafeCurrent()) { @@ -204,7 +213,7 @@ package extension Parser { /// - Parameter characterSet: Unicode.Scalar set to check against /// - Throws: .overflow /// - Returns: String read from buffer - @discardableResult mutating func read(until keyPath: KeyPath, throwOnOverflow: Bool = true) throws -> Parser { + @discardableResult package mutating func read(until keyPath: KeyPath, throwOnOverflow: Bool = true) throws -> Parser { let startIndex = self.index while !self.reachedEnd() { if unsafeCurrent()[keyPath: keyPath] { @@ -225,7 +234,7 @@ package extension Parser { /// - Parameter skipToEnd: Should we set the position to after the found string /// - Throws: .overflow, .emptyString /// - Returns: String read from buffer - @discardableResult mutating func read(untilString: String, throwOnOverflow: Bool = true, skipToEnd: Bool = false) throws -> Parser { + @discardableResult package mutating func read(untilString: String, throwOnOverflow: Bool = true, skipToEnd: Bool = false) throws -> Parser { var untilString = untilString return try untilString.withUTF8 { utf8 in guard utf8.count > 0 else { throw Error.emptyString } @@ -261,7 +270,7 @@ package extension Parser { /// Read from buffer from current position until the end of the buffer /// - Returns: String read from buffer - @discardableResult mutating func readUntilTheEnd() -> Parser { + @discardableResult package mutating func readUntilTheEnd() -> Parser { let startIndex = self.index self.index = self.range.endIndex return self.subParser(startIndex.. Int { + @discardableResult package mutating func read(while: Unicode.Scalar) -> Int { var count = 0 while !self.reachedEnd(), - unsafeCurrent() == `while` + unsafeCurrent() == `while` { unsafeAdvance() count += 1 @@ -284,10 +293,10 @@ package extension Parser { /// Read while character at current position is in supplied set /// - Parameter while: character set to check /// - Returns: String read from buffer - @discardableResult mutating func read(while characterSet: Set) -> Parser { + @discardableResult package mutating func read(while characterSet: Set) -> Parser { let startIndex = self.index while !self.reachedEnd(), - characterSet.contains(unsafeCurrent()) + characterSet.contains(unsafeCurrent()) { unsafeAdvance() } @@ -297,10 +306,10 @@ package extension Parser { /// Read while character returns true for supplied closure /// - Parameter while: character set to check /// - Returns: String read from buffer - @discardableResult mutating func read(while: (Unicode.Scalar) -> Bool) -> Parser { + @discardableResult package mutating func read(while: (Unicode.Scalar) -> Bool) -> Parser { let startIndex = self.index while !self.reachedEnd(), - `while`(unsafeCurrent()) + `while`(unsafeCurrent()) { unsafeAdvance() } @@ -310,10 +319,10 @@ package extension Parser { /// Read while character returns true for supplied KeyPath /// - Parameter while: character set to check /// - Returns: String read from buffer - @discardableResult mutating func read(while keyPath: KeyPath) -> Parser { + @discardableResult package mutating func read(while keyPath: KeyPath) -> Parser { let startIndex = self.index while !self.reachedEnd(), - unsafeCurrent()[keyPath: keyPath] + unsafeCurrent()[keyPath: keyPath] { unsafeAdvance() } @@ -323,7 +332,7 @@ package extension Parser { /// Split parser into sections separated by character /// - Parameter separator: Separator character /// - Returns: arrays of sub parsers - mutating func split(separator: Unicode.Scalar) -> [Parser] { + package mutating func split(separator: Unicode.Scalar) -> [Parser] { var subParsers: [Parser] = [] while !self.reachedEnd() { do { @@ -341,24 +350,24 @@ package extension Parser { /// Return whether we have reached the end of the buffer /// - Returns: Have we reached the end - func reachedEnd() -> Bool { - return self.index == self.range.endIndex + package func reachedEnd() -> Bool { + self.index == self.range.endIndex } } /// Public versions of internal functions which include tests for overflow -package extension Parser { +extension Parser { /// Return the character at the current position /// - Throws: .overflow /// - Returns: Unicode.Scalar - func current() -> Unicode.Scalar { + package func current() -> Unicode.Scalar { guard !self.reachedEnd() else { return Unicode.Scalar(0) } return unsafeCurrent() } /// Move forward one character /// - Throws: .overflow - mutating func advance() throws { + package mutating func advance() throws { guard !self.reachedEnd() else { throw Error.overflow } return self.unsafeAdvance() } @@ -366,7 +375,7 @@ package extension Parser { /// Move forward so many character /// - Parameter amount: number of characters to move forward /// - Throws: .overflow - mutating func advance(by amount: Int) throws { + package mutating func advance(by amount: Int) throws { var amount = amount while amount > 0 { guard !self.reachedEnd() else { throw Error.overflow } @@ -377,7 +386,7 @@ package extension Parser { /// Move backwards one character /// - Throws: .overflow - mutating func retreat() throws { + package mutating func retreat() throws { guard self.index > self.range.startIndex else { throw Error.overflow } self.index = backOneUTF8Character(at: self.index) } @@ -385,7 +394,7 @@ package extension Parser { /// Move back so many characters /// - Parameter amount: number of characters to move back /// - Throws: .overflow - mutating func retreat(by amount: Int) throws { + package mutating func retreat(by amount: Int) throws { var amount = amount while amount > 0 { guard self.index > self.range.startIndex else { throw Error.overflow } @@ -395,20 +404,20 @@ package extension Parser { } /// Move parser to beginning of string - mutating func moveToStart() { + package mutating func moveToStart() { self.index = self.range.startIndex } /// Move parser to end of string - mutating func moveToEnd() { + package mutating func moveToEnd() { self.index = self.range.endIndex } - mutating func unsafeAdvance() { + package mutating func unsafeAdvance() { self.index = skipUTF8Character(at: self.index) } - mutating func unsafeAdvance(by amount: Int) { + package mutating func unsafeAdvance(by amount: Int) { var amount = amount while amount > 0 { self.index = skipUTF8Character(at: self.index) @@ -422,7 +431,7 @@ extension Parser: Sequence { public typealias Element = Unicode.Scalar public func makeIterator() -> Iterator { - return Iterator(self) + Iterator(self) } public struct Iterator: IteratorProtocol { @@ -442,22 +451,22 @@ extension Parser: Sequence { } // internal versions without checks -private extension Parser { - func unsafeCurrent() -> Unicode.Scalar { - return decodeUTF8Character(at: self.index).0 +extension Parser { + fileprivate func unsafeCurrent() -> Unicode.Scalar { + decodeUTF8Character(at: self.index).0 } - mutating func unsafeCurrentAndAdvance() -> Unicode.Scalar { + fileprivate mutating func unsafeCurrentAndAdvance() -> Unicode.Scalar { let (unicodeScalar, index) = decodeUTF8Character(at: self.index) self.index = index return unicodeScalar } - mutating func _setPosition(_ index: Int) { + fileprivate mutating func _setPosition(_ index: Int) { self.index = index } - func makeString(_ bytes: Bytes) -> String where Bytes.Element == UInt8, Bytes.Index == Int { + fileprivate func makeString(_ bytes: Bytes) -> String where Bytes.Element == UInt8, Bytes.Index == Int { if let string = bytes.withContiguousStorageIfAvailable({ String(decoding: $0, as: Unicode.UTF8.self) }) { return string } else { @@ -624,7 +633,7 @@ extension Parser { do { if #available(macOS 11, macCatalyst 14.0, iOS 14.0, tvOS 14.0, *) { return try String(unsafeUninitializedCapacity: range.endIndex - index) { bytes -> Int in - return try _percentDecode(self.buffer[self.index.., http2ConnectionInitializer: @escaping NIOChannelInitializerWithOutput ) -> EventLoopFuture>> { - return self.eventLoop.makeCompletedFuture { - let alpnHandler = NIOTypedApplicationProtocolNegotiationHandler>() { result in + self.eventLoop.makeCompletedFuture { + let alpnHandler = NIOTypedApplicationProtocolNegotiationHandler> { result in switch result { case .negotiated("h2"): // Successful upgrade to HTTP/2. Let the user configure the pipeline. @@ -175,7 +175,8 @@ extension Channel { } try self.pipeline.syncOperations.addHandler(alpnHandler) }.flatMap { _ in - self.pipeline.handler(type: NIOTypedApplicationProtocolNegotiationHandler>.self).map { alpnHandler in + self.pipeline.handler(type: NIOTypedApplicationProtocolNegotiationHandler>.self).map { + alpnHandler in alpnHandler.protocolNegotiationResult } } diff --git a/Sources/HummingbirdHTTP2/HTTPServerBuilder+http2.swift b/Sources/HummingbirdHTTP2/HTTPServerBuilder+http2.swift index b1c174a6..769f4197 100644 --- a/Sources/HummingbirdHTTP2/HTTPServerBuilder+http2.swift +++ b/Sources/HummingbirdHTTP2/HTTPServerBuilder+http2.swift @@ -36,8 +36,8 @@ extension HTTPServerBuilder { tlsConfiguration: TLSConfiguration, additionalChannelHandlers: @autoclosure @escaping @Sendable () -> [any RemovableChannelHandler] ) throws -> HTTPServerBuilder { - return .init { responder in - return try HTTP2UpgradeChannel( + .init { responder in + try HTTP2UpgradeChannel( tlsConfiguration: tlsConfiguration, additionalChannelHandlers: additionalChannelHandlers, responder: responder @@ -62,8 +62,8 @@ extension HTTPServerBuilder { tlsConfiguration: TLSConfiguration, configuration: HTTP2UpgradeChannel.Configuration = .init() ) throws -> HTTPServerBuilder { - return .init { responder in - return try HTTP2UpgradeChannel( + .init { responder in + try HTTP2UpgradeChannel( tlsConfiguration: tlsConfiguration, configuration: configuration, responder: responder diff --git a/Sources/HummingbirdRouter/ContextTransform.swift b/Sources/HummingbirdRouter/ContextTransform.swift index f40f6bbb..ece3066d 100644 --- a/Sources/HummingbirdRouter/ContextTransform.swift +++ b/Sources/HummingbirdRouter/ContextTransform.swift @@ -28,7 +28,8 @@ import Hummingbird /// } /// } /// ``` -public struct ContextTransform: RouterMiddleware where Handler.Input == Request, Handler.Output == Response, Handler.Context == HandlerContext, HandlerContext.Source == Context { +public struct ContextTransform: RouterMiddleware +where Handler.Input == Request, Handler.Output == Response, Handler.Context == HandlerContext, HandlerContext.Source == Context { public typealias Input = Request public typealias Output = Response @@ -64,7 +65,12 @@ public struct ContextTransform: RouterMiddleware where Handler.Input == Request, Handler.Output == Response, Handler.Context == HandlerContext, HandlerContext.ParentContext == Context { +public struct ThrowingContextTransform< + Context: RouterRequestContext, + HandlerContext: RouterRequestContext & ChildRequestContext, + Handler: MiddlewareProtocol +>: RouterMiddleware +where Handler.Input == Request, Handler.Output == Response, Handler.Context == HandlerContext, HandlerContext.ParentContext == Context { public typealias Input = Request public typealias Output = Response diff --git a/Sources/HummingbirdRouter/RouteBuilder.swift b/Sources/HummingbirdRouter/RouteBuilder.swift index fd4c7d3f..f15fa01c 100644 --- a/Sources/HummingbirdRouter/RouteBuilder.swift +++ b/Sources/HummingbirdRouter/RouteBuilder.swift @@ -38,7 +38,7 @@ public struct Handle Output) async throws -> Output { - return try await self.handler(input, context).response(from: input, context: context) + try await self.handler(input, context).response(from: input, context: context) } } @@ -50,13 +50,16 @@ public struct Handle { /// Provide generic requirements for MiddlewareProtocol - public static func buildExpression(_ m0: M0) -> M0 where M0.Input == Request, M0.Output == Response, M0.Context == Context { - return m0 + public static func buildExpression(_ m0: M0) -> M0 + where M0.Input == Request, M0.Output == Response, M0.Context == Context { + m0 } /// Build a ``Handle`` from a closure - public static func buildExpression(_ handler: @escaping @Sendable (Request, Context) async throws -> HandlerOutput) -> Handle { - return .init(handler) + public static func buildExpression( + _ handler: @escaping @Sendable (Request, Context) async throws -> HandlerOutput + ) -> Handle { + .init(handler) } public static func buildBlock(_ m0: Handle) -> Handle { @@ -80,7 +83,9 @@ public enum RouteBuilder { } /// Build the final result where input is multiple middleware with the final middleware being a ``Handle`` middleware. - public static func buildFinalResult(_ m0: _Middleware2>) -> _Middleware2> { + public static func buildFinalResult( + _ m0: _Middleware2> + ) -> _Middleware2> { m0 } } diff --git a/Sources/HummingbirdRouter/RouteGroup.swift b/Sources/HummingbirdRouter/RouteGroup.swift index 0324ef16..a4dcb3f4 100644 --- a/Sources/HummingbirdRouter/RouteGroup.swift +++ b/Sources/HummingbirdRouter/RouteGroup.swift @@ -15,7 +15,8 @@ import Hummingbird /// Router middleware that applies a middleware chain to URIs with a specified prefix -public struct RouteGroup: RouterMiddleware where Handler.Input == Request, Handler.Output == Response, Handler.Context == Context { +public struct RouteGroup: RouterMiddleware +where Handler.Input == Request, Handler.Output == Response, Handler.Context == Context { public typealias Input = Request public typealias Output = Response diff --git a/Sources/HummingbirdRouter/RouteHandler.swift b/Sources/HummingbirdRouter/RouteHandler.swift index eed97236..e7b60727 100644 --- a/Sources/HummingbirdRouter/RouteHandler.swift +++ b/Sources/HummingbirdRouter/RouteHandler.swift @@ -42,7 +42,8 @@ public struct _RouteHandlerClosure: _RouteHandlerProtocol where M0.Input == Request, M0.Output == Response, M0.Context: RouterRequestContext { +public struct _RouteHandlerMiddleware: _RouteHandlerProtocol +where M0.Input == Request, M0.Output == Response, M0.Context: RouterRequestContext { public typealias Context = M0.Context /// Dummy function passed to middleware handle diff --git a/Sources/HummingbirdRouter/RouterBuilder.swift b/Sources/HummingbirdRouter/RouterBuilder.swift index 7e9dec32..a7ecc813 100644 --- a/Sources/HummingbirdRouter/RouterBuilder.swift +++ b/Sources/HummingbirdRouter/RouterBuilder.swift @@ -27,7 +27,8 @@ public struct RouterBuilderOptions: OptionSet, Sendable { } /// Router built using a result builder -public struct RouterBuilder: MiddlewareProtocol where Handler.Input == Request, Handler.Output == Response, Handler.Context == Context { +public struct RouterBuilder: MiddlewareProtocol +where Handler.Input == Request, Handler.Output == Response, Handler.Context == Context { public typealias Input = Request public typealias Output = Response @@ -80,6 +81,6 @@ extension RouterBuilder: HTTPResponder, HTTPResponderBuilder { } public func buildResponder() -> Self { - return self + self } } diff --git a/Sources/HummingbirdRouter/RouterController.swift b/Sources/HummingbirdRouter/RouterController.swift index 259ae41f..544bd4d5 100644 --- a/Sources/HummingbirdRouter/RouterController.swift +++ b/Sources/HummingbirdRouter/RouterController.swift @@ -41,7 +41,8 @@ public protocol RouterController { // MARK: MiddlewareFixedTypeBuilder + RouterController Builders extension MiddlewareFixedTypeBuilder { - public static func buildExpression(_ c0: C0) -> C0.Body where C0.Body.Input == Input, C0.Body.Output == Output, C0.Body.Context == Context { - return c0.body + public static func buildExpression(_ c0: C0) -> C0.Body + where C0.Body.Input == Input, C0.Body.Output == Output, C0.Body.Context == Context { + c0.body } } diff --git a/Sources/HummingbirdTLS/HTTPServerBuilder+tls.swift b/Sources/HummingbirdTLS/HTTPServerBuilder+tls.swift index 52325b1d..8f7b3415 100644 --- a/Sources/HummingbirdTLS/HTTPServerBuilder+tls.swift +++ b/Sources/HummingbirdTLS/HTTPServerBuilder+tls.swift @@ -33,8 +33,8 @@ extension HTTPServerBuilder { _ base: HTTPServerBuilder = .http1(), tlsConfiguration: TLSConfiguration ) throws -> HTTPServerBuilder { - return .init { responder in - return try base.buildChildChannel(responder).withTLS(tlsConfiguration: tlsConfiguration) + .init { responder in + try base.buildChildChannel(responder).withTLS(tlsConfiguration: tlsConfiguration) } } } diff --git a/Sources/HummingbirdTLS/TLSChannel.swift b/Sources/HummingbirdTLS/TLSChannel.swift index 8df0f7c1..217e0f12 100644 --- a/Sources/HummingbirdTLS/TLSChannel.swift +++ b/Sources/HummingbirdTLS/TLSChannel.swift @@ -37,7 +37,7 @@ public struct TLSChannel: ServerChildChannel { /// - Returns: Object to process input/output on child channel @inlinable public func setup(channel: Channel, logger: Logger) -> EventLoopFuture { - return channel.eventLoop.makeCompletedFuture { + channel.eventLoop.makeCompletedFuture { try channel.pipeline.syncOperations.addHandler(NIOSSLServerHandler(context: self.sslContext)) }.flatMap { self.baseChannel.setup(channel: channel, logger: logger) diff --git a/Sources/HummingbirdTesting/Application+Test.swift b/Sources/HummingbirdTesting/Application+Test.swift index 4969dba2..75769ef6 100644 --- a/Sources/HummingbirdTesting/Application+Test.swift +++ b/Sources/HummingbirdTesting/Application+Test.swift @@ -78,11 +78,12 @@ extension ApplicationProtocol { _ testingSetup: TestingSetup, _ test: @Sendable (any TestClientProtocol) async throws -> Value ) async throws -> Value { - let app: any ApplicationTestFramework = switch testingSetup.value { - case .router: try await RouterTestFramework(app: self) - case .live: LiveTestFramework(app: self) - case .ahc(let scheme): AsyncHTTPClientTestFramework(app: self, scheme: scheme) - } + let app: any ApplicationTestFramework = + switch testingSetup.value { + case .router: try await RouterTestFramework(app: self) + case .live: LiveTestFramework(app: self) + case .ahc(let scheme): AsyncHTTPClientTestFramework(app: self, scheme: scheme) + } return try await app.run(test) } } diff --git a/Sources/HummingbirdTesting/AsyncHTTPClientTestFramework.swift b/Sources/HummingbirdTesting/AsyncHTTPClientTestFramework.swift index 4b5003fe..3078b488 100644 --- a/Sources/HummingbirdTesting/AsyncHTTPClientTestFramework.swift +++ b/Sources/HummingbirdTesting/AsyncHTTPClientTestFramework.swift @@ -197,7 +197,7 @@ extension HTTPRequest.Method { case .MKACTIVITY: self = .init("MKACTIVITY")! case .UNSUBSCRIBE: self = .init("UNSUBSCRIBE")! case .SOURCE: self = .init("SOURCE")! - case .RAW(value: let value): + case .RAW(let value): guard let method = HTTPRequest.Method(value) else { throw HTTP1TypeConversionError.invalidMethod } @@ -225,9 +225,11 @@ extension HTTPFields { } if let name = HTTPField.Name(field.name) { if splitCookie, name == .cookie, #available(macOS 13.0, iOS 16.0, watchOS 9.0, tvOS 16.0, *) { - self.append(contentsOf: field.value.split(separator: "; ", omittingEmptySubsequences: false).map { - HTTPField(name: name, value: String($0)) - }) + self.append( + contentsOf: field.value.split(separator: "; ", omittingEmptySubsequences: false).map { + HTTPField(name: name, value: String($0)) + } + ) } else { self.append(HTTPField(name: name, value: field.value)) } diff --git a/Sources/HummingbirdTesting/RouterTestFramework.swift b/Sources/HummingbirdTesting/RouterTestFramework.swift index 1126e914..3f286a5a 100644 --- a/Sources/HummingbirdTesting/RouterTestFramework.swift +++ b/Sources/HummingbirdTesting/RouterTestFramework.swift @@ -14,12 +14,12 @@ import Atomics import HTTPTypes -import NIOEmbedded @_spi(Internal) import Hummingbird @_spi(Internal) import HummingbirdCore import Logging import NIOConcurrencyHelpers import NIOCore +import NIOEmbedded import NIOHTTPTypes import NIOPosix import ServiceLifecycle @@ -98,7 +98,7 @@ struct RouterTestFramework: ApplicationTestFramework w let makeContext: @Sendable (Logger) -> Responder.Context func executeRequest(uri: String, method: HTTPRequest.Method, headers: HTTPFields, body: ByteBuffer?) async throws -> TestResponse { - return try await withThrowingTaskGroup(of: TestResponse.self) { group in + try await withThrowingTaskGroup(of: TestResponse.self) { group in var headers = headers if let contentLength = body.map(\.readableBytes) { headers[.contentLength] = String(describing: contentLength) diff --git a/Sources/HummingbirdTesting/TestApplication.swift b/Sources/HummingbirdTesting/TestApplication.swift index f6ed0450..cf89f9e6 100644 --- a/Sources/HummingbirdTesting/TestApplication.swift +++ b/Sources/HummingbirdTesting/TestApplication.swift @@ -71,7 +71,7 @@ final class Promise: Sendable { /// wait from promise to be completed func wait() async -> Value { - return await withCheckedContinuation { cont in + await withCheckedContinuation { cont in self.state.withLockedValue { state in switch state { case .blocked(var continuations): diff --git a/Sources/HummingbirdTesting/TestClient.swift b/Sources/HummingbirdTesting/TestClient.swift index a3257439..faba6810 100644 --- a/Sources/HummingbirdTesting/TestClient.swift +++ b/Sources/HummingbirdTesting/TestClient.swift @@ -82,7 +82,7 @@ public struct TestClient: Sendable { try self.getBootstrap() .channelOption(ChannelOptions.socket(SocketOptionLevel(IPPROTO_TCP), TCP_NODELAY), value: 1) .channelInitializer { channel in - return channel.pipeline.addHTTPClientHandlers() + channel.pipeline.addHTTPClientHandlers() .flatMapThrowing { let handlers: [ChannelHandler] = [ HTTP1ToHTTPClientCodec(), @@ -184,7 +184,10 @@ public struct TestClient: Sendable { private func getBootstrap() throws -> NIOClientTCPBootstrap { if let tlsConfiguration = self.configuration.tlsConfiguration { let sslContext = try NIOSSLContext(configuration: tlsConfiguration) - let tlsProvider = try NIOSSLClientTLSProvider(context: sslContext, serverHostname: self.configuration.serverName ?? self.host) + let tlsProvider = try NIOSSLClientTLSProvider( + context: sslContext, + serverHostname: self.configuration.serverName ?? self.host + ) let bootstrap = NIOClientTCPBootstrap(ClientBootstrap(group: self.eventLoopGroup), tls: tlsProvider) bootstrap.enableTLS() return bootstrap diff --git a/Sources/PerformanceTest/main.swift b/Sources/PerformanceTest/main.swift index 30691ab7..7d71a91d 100644 --- a/Sources/PerformanceTest/main.swift +++ b/Sources/PerformanceTest/main.swift @@ -29,13 +29,13 @@ var router = Router() // number of raw requests // ./wrk -c 128 -d 15s -t 8 http://localhost:8080 router.get { _, _ in - return "Hello, world" + "Hello, world" } // request with a body // ./wrk -c 128 -d 15s -t 8 -s scripts/post.lua http://localhost:8080 router.post { request, _ in - return Response(status: .ok, body: .init(asyncSequence: request.body)) + Response(status: .ok, body: .init(asyncSequence: request.body)) } struct Object: ResponseEncodable { @@ -45,7 +45,7 @@ struct Object: ResponseEncodable { // return JSON // ./wrk -c 128 -d 15s -t 8 http://localhost:8080/json router.get("json") { _, _ in - return Object(message: "Hello, world") + Object(message: "Hello, world") } // return JSON diff --git a/Tests/HummingbirdCoreTests/CoreTests.swift b/Tests/HummingbirdCoreTests/CoreTests.swift index b4568cb5..1a32195b 100644 --- a/Tests/HummingbirdCoreTests/CoreTests.swift +++ b/Tests/HummingbirdCoreTests/CoreTests.swift @@ -384,10 +384,12 @@ final class HummingBirdCoreTests: XCTestCase { } try await responseWriter.writeResponse(.init(status: .ok)) }, - httpChannelSetup: .http1(configuration: .init( - additionalChannelHandlers: [HTTPServerIncompleteRequest()], - idleTimeout: .seconds(1) - )), + httpChannelSetup: .http1( + configuration: .init( + additionalChannelHandlers: [HTTPServerIncompleteRequest()], + idleTimeout: .seconds(1) + ) + ), configuration: .init(address: .hostname(port: 0)), eventLoopGroup: Self.eventLoopGroup, logger: Logger(label: "Hummingbird") @@ -422,10 +424,12 @@ final class HummingBirdCoreTests: XCTestCase { } try await responseWriter.writeResponse(.init(status: .ok)) }, - httpChannelSetup: .http1(configuration: .init( - additionalChannelHandlers: [HTTPServerIncompleteRequest()], - idleTimeout: .seconds(1) - )), + httpChannelSetup: .http1( + configuration: .init( + additionalChannelHandlers: [HTTPServerIncompleteRequest()], + idleTimeout: .seconds(1) + ) + ), configuration: .init(address: .hostname(port: 0)), eventLoopGroup: Self.eventLoopGroup, logger: Logger(label: "Hummingbird") @@ -561,6 +565,6 @@ extension DelayAsyncSequence: Sendable where CoreSequence: Sendable {} extension AsyncSequence { func delayed() -> DelayAsyncSequence { - return .init(seq: self) + .init(seq: self) } } diff --git a/Tests/HummingbirdCoreTests/TLSTests.swift b/Tests/HummingbirdCoreTests/TLSTests.swift index c4b8885c..134dd439 100644 --- a/Tests/HummingbirdCoreTests/TLSTests.swift +++ b/Tests/HummingbirdCoreTests/TLSTests.swift @@ -13,8 +13,8 @@ //===----------------------------------------------------------------------===// import HummingbirdCore -import HummingbirdTesting import HummingbirdTLS +import HummingbirdTesting import Logging import NIOConcurrencyHelpers import NIOCore diff --git a/Tests/HummingbirdHTTP2Tests/Certificates.swift b/Tests/HummingbirdHTTP2Tests/Certificates.swift index 72c022d6..1e551040 100644 --- a/Tests/HummingbirdHTTP2Tests/Certificates.swift +++ b/Tests/HummingbirdHTTP2Tests/Certificates.swift @@ -1,12 +1,12 @@ //===----------------------------------------------------------------------===// // -// This source file is part of the Hummingbird open source project +// This source file is part of the Hummingbird server framework project // -// Copyright (c) YEARS the Hummingbird authors +// Copyright (c) 2021-2024 the Hummingbird authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Hummingbird authors +// See hummingbird/CONTRIBUTORS.txt for the list of Hummingbird authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Tests/HummingbirdHTTP2Tests/HTTP2ServerConnectionManagerStateMachineTests.swift b/Tests/HummingbirdHTTP2Tests/HTTP2ServerConnectionManagerStateMachineTests.swift index 38e1d3f7..3179b80a 100644 --- a/Tests/HummingbirdHTTP2Tests/HTTP2ServerConnectionManagerStateMachineTests.swift +++ b/Tests/HummingbirdHTTP2Tests/HTTP2ServerConnectionManagerStateMachineTests.swift @@ -12,49 +12,77 @@ // //===----------------------------------------------------------------------===// -@testable import HummingbirdHTTP2 import NIOCore import NIOHTTP2 import XCTest +@testable import HummingbirdHTTP2 + final class HTTP2ServerConnectionManagerStateMachineTests: XCTestCase { func testAddRemoveClose() { var stateMachine = HTTP2ServerConnectionManager.StateMachine() stateMachine.streamOpened(.init(2)) XCTAssertEqual(stateMachine.streamClosed(.init(2)), .startIdleTimer) let triggerGracefulShutdownResult = stateMachine.triggerGracefulShutdown() - guard case .sendGoAway(let pingData) = triggerGracefulShutdownResult else { XCTFail(); return } + guard case .sendGoAway(let pingData) = triggerGracefulShutdownResult else { + XCTFail() + return + } let pingAckResult = stateMachine.receivedPingAck(data: pingData) - guard case .sendGoAway(let lastStreamId, let close) = pingAckResult else { XCTFail(); return } + guard case .sendGoAway(let lastStreamId, let close) = pingAckResult else { + XCTFail() + return + } XCTAssertEqual(close, true) XCTAssertEqual(lastStreamId, 2) - guard case .closed = stateMachine.state else { XCTFail(); return } + guard case .closed = stateMachine.state else { + XCTFail() + return + } } func testAddCloseRemove() { var stateMachine = HTTP2ServerConnectionManager.StateMachine() stateMachine.streamOpened(.init(2)) let triggerGracefulShutdownResult = stateMachine.triggerGracefulShutdown() - guard case .sendGoAway(let pingData) = triggerGracefulShutdownResult else { XCTFail(); return } + guard case .sendGoAway(let pingData) = triggerGracefulShutdownResult else { + XCTFail() + return + } let pingAckResult = stateMachine.receivedPingAck(data: pingData) - guard case .sendGoAway(let lastStreamId, let close) = pingAckResult else { XCTFail(); return } + guard case .sendGoAway(let lastStreamId, let close) = pingAckResult else { + XCTFail() + return + } XCTAssertEqual(close, false) XCTAssertEqual(lastStreamId, 2) XCTAssertEqual(stateMachine.streamClosed(.init(2)), .close) - guard case .closed = stateMachine.state else { XCTFail(); return } + guard case .closed = stateMachine.state else { + XCTFail() + return + } } func testCloseAddRemove() { var stateMachine = HTTP2ServerConnectionManager.StateMachine() let triggerGracefulShutdownResult = stateMachine.triggerGracefulShutdown() - guard case .sendGoAway(let pingData) = triggerGracefulShutdownResult else { XCTFail(); return } + guard case .sendGoAway(let pingData) = triggerGracefulShutdownResult else { + XCTFail() + return + } stateMachine.streamOpened(.init(2)) let pingAckResult = stateMachine.receivedPingAck(data: pingData) - guard case .sendGoAway(let lastStreamId, let close) = pingAckResult else { XCTFail(); return } + guard case .sendGoAway(let lastStreamId, let close) = pingAckResult else { + XCTFail() + return + } XCTAssertEqual(close, false) XCTAssertEqual(lastStreamId, 2) XCTAssertEqual(stateMachine.streamClosed(.init(2)), .close) - guard case .closed = stateMachine.state else { XCTFail(); return } + guard case .closed = stateMachine.state else { + XCTFail() + return + } } func testReceivedPing() { @@ -63,32 +91,62 @@ final class HTTP2ServerConnectionManagerStateMachineTests: XCTestCase { var stateMachine = HTTP2ServerConnectionManager.StateMachine() stateMachine.streamOpened(.init(4)) var pingResult = stateMachine.receivedPing(atTime: now, data: pingData) - guard case .sendPingAck(let data) = pingResult else { XCTFail(); return } + guard case .sendPingAck(let data) = pingResult else { + XCTFail() + return + } XCTAssertEqual(data, pingData) pingResult = stateMachine.receivedPing(atTime: now + .seconds(1), data: pingData) - guard case .sendPingAck = pingResult else { XCTFail(); return } + guard case .sendPingAck = pingResult else { + XCTFail() + return + } pingResult = stateMachine.receivedPing(atTime: now + .seconds(1), data: pingData) - guard case .sendPingAck = pingResult else { XCTFail(); return } + guard case .sendPingAck = pingResult else { + XCTFail() + return + } pingResult = stateMachine.receivedPing(atTime: now + .seconds(2), data: pingData) - guard case .enhanceYourCalmAndClose(let id) = pingResult else { XCTFail(); return } + guard case .enhanceYourCalmAndClose(let id) = pingResult else { + XCTFail() + return + } XCTAssertEqual(id, 4) - guard case .closed = stateMachine.state else { XCTFail(); return } + guard case .closed = stateMachine.state else { + XCTFail() + return + } } func testClosedState() { // get statemachine into closed state var stateMachine = HTTP2ServerConnectionManager.StateMachine() let triggerGracefulShutdownResult = stateMachine.triggerGracefulShutdown() - guard case .sendGoAway(let pingData) = triggerGracefulShutdownResult else { XCTFail(); return } + guard case .sendGoAway(let pingData) = triggerGracefulShutdownResult else { + XCTFail() + return + } let pingAckResult = stateMachine.receivedPingAck(data: pingData) - guard case .sendGoAway(_, let close) = pingAckResult else { XCTFail(); return } + guard case .sendGoAway(_, let close) = pingAckResult else { + XCTFail() + return + } XCTAssertEqual(close, true) // test closed state responses XCTAssertEqual(stateMachine.streamClosed(.init(0)), .none) - guard case .none = stateMachine.receivedPing(atTime: .now(), data: .init()) else { XCTFail(); return } - guard case .none = stateMachine.receivedPingAck(data: .init()) else { XCTFail(); return } - guard case .none = stateMachine.triggerGracefulShutdown() else { XCTFail(); return } + guard case .none = stateMachine.receivedPing(atTime: .now(), data: .init()) else { + XCTFail() + return + } + guard case .none = stateMachine.receivedPingAck(data: .init()) else { + XCTFail() + return + } + guard case .none = stateMachine.triggerGracefulShutdown() else { + XCTFail() + return + } } func testClosePingAckWrongData() { @@ -96,10 +154,19 @@ final class HTTP2ServerConnectionManagerStateMachineTests: XCTestCase { // get statemachine into closed state var stateMachine = HTTP2ServerConnectionManager.StateMachine() let triggerGracefulShutdownResult = stateMachine.triggerGracefulShutdown() - guard case .sendGoAway(let pingData) = triggerGracefulShutdownResult else { XCTFail(); return } + guard case .sendGoAway(let pingData) = triggerGracefulShutdownResult else { + XCTFail() + return + } var pingAckResult = stateMachine.receivedPingAck(data: randomPingData) - guard case .none = pingAckResult else { XCTFail(); return } + guard case .none = pingAckResult else { + XCTFail() + return + } pingAckResult = stateMachine.receivedPingAck(data: pingData) - guard case .sendGoAway = pingAckResult else { XCTFail(); return } + guard case .sendGoAway = pingAckResult else { + XCTFail() + return + } } } diff --git a/Tests/HummingbirdRouterTests/MiddlewareTests.swift b/Tests/HummingbirdRouterTests/MiddlewareTests.swift index 3510e89f..12a2cafd 100644 --- a/Tests/HummingbirdRouterTests/MiddlewareTests.swift +++ b/Tests/HummingbirdRouterTests/MiddlewareTests.swift @@ -159,10 +159,13 @@ final class MiddlewareTests: XCTestCase { RouteGroup("") { TransformMiddleware() Get("test") { request, _ in - Response(status: .ok, body: .init { writer in - try await writer.write(request.body) - try await writer.finish([.middleware: "test"]) - }) + Response( + status: .ok, + body: .init { writer in + try await writer.write(request.body) + try await writer.finish([.middleware: "test"]) + } + ) } } } diff --git a/Tests/HummingbirdTests/ApplicationTests.swift b/Tests/HummingbirdTests/ApplicationTests.swift index 017c38c5..e750f4ea 100644 --- a/Tests/HummingbirdTests/ApplicationTests.swift +++ b/Tests/HummingbirdTests/ApplicationTests.swift @@ -17,8 +17,8 @@ import HTTPTypes import Hummingbird import HummingbirdCore import HummingbirdHTTP2 -import HummingbirdTesting import HummingbirdTLS +import HummingbirdTesting import Logging import NIOConcurrencyHelpers import NIOCore @@ -37,7 +37,7 @@ final class ApplicationTests: XCTestCase { func testGetRoute() async throws { let router = Router() router.get("/hello") { _, _ -> ByteBuffer in - return ByteBuffer(string: "GET: Hello") + ByteBuffer(string: "GET: Hello") } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -51,7 +51,7 @@ final class ApplicationTests: XCTestCase { func testHTTPStatusRoute() async throws { let router = Router() router.get("/accepted") { _, _ -> HTTPResponse.Status in - return .accepted + .accepted } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -64,7 +64,7 @@ final class ApplicationTests: XCTestCase { func testStandardHeaders() async throws { let router = Router() router.get("/hello") { _, _ in - return "Hello" + "Hello" } let app = Application(responder: router.buildResponder()) try await app.test(.live) { client in @@ -78,10 +78,11 @@ final class ApplicationTests: XCTestCase { func testServerHeaders() async throws { let router = Router() router.get("/hello") { _, _ in - return "Hello" + "Hello" } let app = Application( - responder: router.buildResponder(), configuration: .init(serverName: "TestServer") + responder: router.buildResponder(), + configuration: .init(serverName: "TestServer") ) try await app.test(.live) { client in try await client.execute(uri: "/hello", method: .get) { response in @@ -93,7 +94,7 @@ final class ApplicationTests: XCTestCase { func testPostRoute() async throws { let router = Router() router.post("/hello") { _, _ -> String in - return "POST: Hello" + "POST: Hello" } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -108,10 +109,10 @@ final class ApplicationTests: XCTestCase { func testMultipleMethods() async throws { let router = Router() router.post("/hello") { _, _ -> String in - return "POST" + "POST" } router.get("/hello") { _, _ -> String in - return "GET" + "GET" } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -129,10 +130,10 @@ final class ApplicationTests: XCTestCase { let router = Router() router.group("hello") .post { _, _ -> String in - return "POST" + "POST" } .get { _, _ -> String in - return "GET" + "GET" } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -149,8 +150,9 @@ final class ApplicationTests: XCTestCase { func testQueryRoute() async throws { let router = Router() router.post("/query") { request, _ -> ByteBuffer in - return ByteBuffer( - string: request.uri.queryParameters["test"].map { String($0) } ?? "") + ByteBuffer( + string: request.uri.queryParameters["test"].map { String($0) } ?? "" + ) } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -166,7 +168,7 @@ final class ApplicationTests: XCTestCase { func testMultipleQueriesRoute() async throws { let router = Router() router.post("/add") { request, _ -> String in - return request.uri.queryParameters.getAll("value", as: Int.self).reduce(0, +) + request.uri.queryParameters.getAll("value", as: Int.self).reduce(0, +) .description } let app = Application(responder: router.buildResponder()) @@ -183,7 +185,7 @@ final class ApplicationTests: XCTestCase { func testArray() async throws { let router = Router() router.get("array") { _, _ -> [String] in - return ["yes", "no"] + ["yes", "no"] } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -276,7 +278,7 @@ final class ApplicationTests: XCTestCase { func testStreaming() async throws { let router = Router() router.post("streaming") { request, _ -> Response in - return Response(status: .ok, body: .init(asyncSequence: request.body)) + Response(status: .ok, body: .init(asyncSequence: request.body)) } router.post("size") { request, _ -> String in var size = 0 @@ -308,7 +310,7 @@ final class ApplicationTests: XCTestCase { func testStreamingSmallBuffer() async throws { let router = Router() router.post("streaming") { request, _ -> Response in - return Response(status: .ok, body: .init(asyncSequence: request.body)) + Response(status: .ok, body: .init(asyncSequence: request.body)) } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -327,7 +329,8 @@ final class ApplicationTests: XCTestCase { func testCollectBody() async throws { struct CollateMiddleware: RouterMiddleware { public func handle( - _ request: Request, context: Context, + _ request: Request, + context: Context, next: (Request, Context) async throws -> Response ) async throws -> Response { var request = request @@ -416,7 +419,7 @@ final class ApplicationTests: XCTestCase { router .group("/name") .patch { _, _ -> Name? in - return Name(first: "john", last: "smith") + Name(first: "john", last: "smith") } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -430,7 +433,7 @@ final class ApplicationTests: XCTestCase { func testTypedResponse() async throws { let router = Router() router.delete("/hello") { _, _ in - return EditedResponse( + EditedResponse( status: .preconditionRequired, headers: [.test: "value", .contentType: "application/json"], response: "Hello" @@ -454,7 +457,7 @@ final class ApplicationTests: XCTestCase { } let router = Router() router.patch("/hello") { _, _ in - return EditedResponse( + EditedResponse( status: .multipleChoices, headers: [.test: "value", .contentType: "application/json"], response: Result(value: "true") @@ -506,10 +509,13 @@ final class ApplicationTests: XCTestCase { func testChunkedTransferEncoding() async throws { let router = Router() .get("chunked") { _, _ in - Response(status: .ok, body: .init { writer in - try await writer.write(ByteBuffer(string: "Testing")) - try await writer.finish(nil) - }) + Response( + status: .ok, + body: .init { writer in + try await writer.write(ByteBuffer(string: "Testing")) + try await writer.finish(nil) + } + ) } let app = Application(responder: router.buildResponder()) try await app.test(.live) { client in @@ -561,7 +567,7 @@ final class ApplicationTests: XCTestCase { func createApplication() -> some ApplicationProtocol { let router = Router() router.get("/hello") { _, _ -> ByteBuffer in - return ByteBuffer(string: "GET: Hello") + ByteBuffer(string: "GET: Hello") } return Application(responder: router.buildResponder()) } @@ -734,7 +740,8 @@ final class ApplicationTests: XCTestCase { body: .init { writer in for try await buffer in request.body { let processed = ByteBuffer( - bytes: buffer.readableBytesView.map { $0 ^ 0xFF }) + bytes: buffer.readableBytesView.map { $0 ^ 0xFF } + ) try await writer.write(processed) } try await writer.finish(nil) @@ -745,7 +752,8 @@ final class ApplicationTests: XCTestCase { try await app.test(.live) { client in try await client.execute(uri: "/", method: .post, body: buffer) { response in XCTAssertEqual( - response.body, ByteBuffer(bytes: buffer.readableBytesView.map { $0 ^ 0xFF }) + response.body, + ByteBuffer(bytes: buffer.readableBytesView.map { $0 ^ 0xFF }) ) } } @@ -755,16 +763,20 @@ final class ApplicationTests: XCTestCase { func getServerTLSConfiguration() throws -> TLSConfiguration { let caCertificate = try NIOSSLCertificate( - bytes: [UInt8](caCertificateData.utf8), format: .pem + bytes: [UInt8](caCertificateData.utf8), + format: .pem ) let certificate = try NIOSSLCertificate( - bytes: [UInt8](serverCertificateData.utf8), format: .pem + bytes: [UInt8](serverCertificateData.utf8), + format: .pem ) let privateKey = try NIOSSLPrivateKey( - bytes: [UInt8](serverPrivateKeyData.utf8), format: .pem + bytes: [UInt8](serverPrivateKeyData.utf8), + format: .pem ) var tlsConfig = TLSConfiguration.makeServerConfiguration( - certificateChain: [.certificate(certificate)], privateKey: .privateKey(privateKey) + certificateChain: [.certificate(certificate)], + privateKey: .privateKey(privateKey) ) tlsConfig.trustRoots = .certificates([caCertificate]) return tlsConfig diff --git a/Tests/HummingbirdTests/Certificates.swift b/Tests/HummingbirdTests/Certificates.swift index 84f4f526..63c9eade 100644 --- a/Tests/HummingbirdTests/Certificates.swift +++ b/Tests/HummingbirdTests/Certificates.swift @@ -1,12 +1,12 @@ //===----------------------------------------------------------------------===// // -// This source file is part of the Hummingbird open source project +// This source file is part of the Hummingbird server framework project // -// Copyright (c) YEARS the Hummingbird authors +// Copyright (c) 2021-2024 the Hummingbird authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Hummingbird authors +// See hummingbird/CONTRIBUTORS.txt for the list of Hummingbird authors // // SPDX-License-Identifier: Apache-2.0 // diff --git a/Tests/HummingbirdTests/CookiesTests.swift b/Tests/HummingbirdTests/CookiesTests.swift index b88a60de..e1cbb14b 100644 --- a/Tests/HummingbirdTests/CookiesTests.swift +++ b/Tests/HummingbirdTests/CookiesTests.swift @@ -12,10 +12,11 @@ // //===----------------------------------------------------------------------===// -@testable import Hummingbird import HummingbirdTesting import XCTest +@testable import Hummingbird + final class CookieTests: XCTestCase { func testNameValue() { let cookie = Cookie(from: "name=value") @@ -82,7 +83,7 @@ final class CookieTests: XCTestCase { func testSetCookieViaRequest() async throws { let router = Router() router.post("/") { _, _ in - return EditedResponse(headers: [.setCookie: Cookie(name: "test", value: "value").description], response: "Hello") + EditedResponse(headers: [.setCookie: Cookie(name: "test", value: "value").description], response: "Hello") } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -95,7 +96,7 @@ final class CookieTests: XCTestCase { func testReadCookieFromRequest() async throws { let router = Router() router.post("/") { request, _ -> String? in - return request.cookies["test"]?.value + request.cookies["test"]?.value } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in diff --git a/Tests/HummingbirdTests/DateCacheTests.swift b/Tests/HummingbirdTests/DateCacheTests.swift index ddd425b5..1476cf56 100644 --- a/Tests/HummingbirdTests/DateCacheTests.swift +++ b/Tests/HummingbirdTests/DateCacheTests.swift @@ -13,10 +13,11 @@ //===----------------------------------------------------------------------===// import Foundation -@testable import Hummingbird import HummingbirdTesting import XCTest +@testable import Hummingbird + final class HummingbirdDateTests: XCTestCase { func testRFC1123Renderer() { let formatter = DateFormatter() @@ -33,7 +34,7 @@ final class HummingbirdDateTests: XCTestCase { func testDateHeader() async throws { let router = Router() router.get("date") { _, _ in - return "hello" + "hello" } let app = Application(responder: router.buildResponder()) diff --git a/Tests/HummingbirdTests/EnvironmentTests.swift b/Tests/HummingbirdTests/EnvironmentTests.swift index fa49b0f4..f27bf764 100644 --- a/Tests/HummingbirdTests/EnvironmentTests.swift +++ b/Tests/HummingbirdTests/EnvironmentTests.swift @@ -13,9 +13,10 @@ //===----------------------------------------------------------------------===// import Foundation -@testable import Hummingbird import XCTest +@testable import Hummingbird + final class EnvironmentTests: XCTestCase { func testInitFromEnvironment() { XCTAssertEqual(setenv("TEST_VAR", "testSetFromEnvironment", 1), 0) @@ -65,9 +66,9 @@ final class EnvironmentTests: XCTestCase { func testDotEnvLoading() async throws { let dotenv = """ - TEST=this - CREDENTIALS=sdkfjh - """ + TEST=this + CREDENTIALS=sdkfjh + """ let data = dotenv.data(using: .utf8) let envURL = URL(fileURLWithPath: ".env") try data?.write(to: envURL) @@ -82,8 +83,8 @@ final class EnvironmentTests: XCTestCase { func testDotEnvParsingError() throws { let dotenv = """ - TEST #thse - """ + TEST #thse + """ do { _ = try Environment.parseDotEnv(dotenv) XCTFail("Should fail") @@ -92,9 +93,9 @@ final class EnvironmentTests: XCTestCase { func testDotEnvSpeechMarks() throws { let dotenv = """ - TEST="test this" - CREDENTIALS=sdkfjh - """ + TEST="test this" + CREDENTIALS=sdkfjh + """ let result = try Environment.parseDotEnv(dotenv) XCTAssertEqual(result["test"], "test this") XCTAssertEqual(result["credentials"], "sdkfjh") @@ -102,10 +103,10 @@ final class EnvironmentTests: XCTestCase { func testDotEnvMultilineValue() throws { let dotenv = """ - TEST="test - this" - CREDENTIALS=sdkfjh - """ + TEST="test + this" + CREDENTIALS=sdkfjh + """ let result = try Environment.parseDotEnv(dotenv) XCTAssertEqual(result["test"], "test\nthis") XCTAssertEqual(result["credentials"], "sdkfjh") @@ -113,11 +114,11 @@ final class EnvironmentTests: XCTestCase { func testDotEnvComments() throws { let dotenv = """ - # Comment - TEST=this # Comment at end of line - CREDENTIALS=sdkfjh - # Comment at end - """ + # Comment + TEST=this # Comment at end of line + CREDENTIALS=sdkfjh + # Comment at end + """ let result = try Environment.parseDotEnv(dotenv) XCTAssertEqual(result["test"], "this") XCTAssertEqual(result["credentials"], "sdkfjh") @@ -125,11 +126,11 @@ final class EnvironmentTests: XCTestCase { func testDotEnvCommentAndEmptyLine() throws { let dotenv = """ - FOO=BAR - #BAZ= + FOO=BAR + #BAZ= - """ + """ let result = try Environment.parseDotEnv(dotenv) XCTAssertEqual(result["foo"], "BAR") XCTAssertEqual(result.count, 1) @@ -137,9 +138,9 @@ final class EnvironmentTests: XCTestCase { func testEmptyLineAtEnd() throws { let dotenv = """ - FOO=BAR + FOO=BAR - """ + """ let result = try Environment.parseDotEnv(dotenv) XCTAssertEqual(result["foo"], "BAR") XCTAssertEqual(result.count, 1) @@ -147,8 +148,8 @@ final class EnvironmentTests: XCTestCase { func testDotEnvOverridingEnvironment() async throws { let dotenv = """ - TEST_VAR=testDotEnvOverridingEnvironment - """ + TEST_VAR=testDotEnvOverridingEnvironment + """ let data = dotenv.data(using: .utf8) let envURL = URL(fileURLWithPath: ".override.env") try data?.write(to: envURL) diff --git a/Tests/HummingbirdTests/FileMiddlewareTests.swift b/Tests/HummingbirdTests/FileMiddlewareTests.swift index 5efa7424..c379b075 100644 --- a/Tests/HummingbirdTests/FileMiddlewareTests.swift +++ b/Tests/HummingbirdTests/FileMiddlewareTests.swift @@ -142,7 +142,8 @@ final class FileMiddlewareTests: XCTestCase { defer { XCTAssertNoThrow(try FileManager.default.removeItem(at: fileURL)) } try await app.test(.router) { client in - let (eTag, modificationDate) = try await client.execute(uri: filename, method: .get, headers: [.range: "bytes=-3999"]) { response -> (String, String) in + let (eTag, modificationDate) = try await client.execute(uri: filename, method: .get, headers: [.range: "bytes=-3999"]) { + response -> (String, String) in let eTag = try XCTUnwrap(response.headers[.eTag]) let modificationDate = try XCTUnwrap(response.headers[.lastModified]) let slice = buffer.getSlice(at: 0, length: 4000) @@ -367,11 +368,11 @@ final class FileMiddlewareTests: XCTestCase { } func getFileIdentifier(_ path: String) -> String? { - return path + path } func getAttributes(id path: String) async throws -> FileAttributes? { - return .init( + .init( isFolder: path.last == "/", size: path.utf8.count ) @@ -438,7 +439,7 @@ final class FileMiddlewareTests: XCTestCase { } func getFileIdentifier(_ path: String) -> String? { - return path + path } func getAttributes(id path: String) async throws -> FileAttributes? { diff --git a/Tests/HummingbirdTests/HummingBirdJSONTests.swift b/Tests/HummingbirdTests/HummingBirdJSONTests.swift index 1f3270bf..a5680c9a 100644 --- a/Tests/HummingbirdTests/HummingBirdJSONTests.swift +++ b/Tests/HummingbirdTests/HummingBirdJSONTests.swift @@ -47,7 +47,7 @@ final class HummingbirdJSONTests: XCTestCase { func testEncode() async throws { let router = Router() router.get("/user") { _, _ -> User in - return User(name: "John Smith", email: "john.smith@email.com", age: 25) + User(name: "John Smith", email: "john.smith@email.com", age: 25) } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -63,7 +63,7 @@ final class HummingbirdJSONTests: XCTestCase { func testEncode2() async throws { let router = Router() router.get("/json") { _, _ in - return ["message": "Hello, world!"] + ["message": "Hello, world!"] } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in diff --git a/Tests/HummingbirdTests/MetricsTests.swift b/Tests/HummingbirdTests/MetricsTests.swift index fc39be16..f2a0af74 100644 --- a/Tests/HummingbirdTests/MetricsTests.swift +++ b/Tests/HummingbirdTests/MetricsTests.swift @@ -26,7 +26,7 @@ final class TestMetrics: MetricsFactory { public func makeCounter(label: String, dimensions: [(String, String)]) -> CounterHandler { self.counters.withLockedValue { counters in - return self.make(label: label, dimensions: dimensions, registry: &counters, maker: TestCounter.init) + self.make(label: label, dimensions: dimensions, registry: &counters, maker: TestCounter.init) } } @@ -45,7 +45,12 @@ final class TestMetrics: MetricsFactory { } } - private func make(label: String, dimensions: [(String, String)], registry: inout [String: Item], maker: (String, [(String, String)]) -> Item) -> Item { + private func make( + label: String, + dimensions: [(String, String)], + registry: inout [String: Item], + maker: (String, [(String, String)]) -> Item + ) -> Item { let item = maker(label, dimensions) registry[label] = item return item @@ -103,7 +108,7 @@ internal final class TestCounter: CounterHandler, Equatable { } public static func == (lhs: TestCounter, rhs: TestCounter) -> Bool { - return lhs.id == rhs.id + lhs.id == rhs.id } } @@ -134,7 +139,7 @@ internal final class TestRecorder: RecorderHandler, Equatable { } public static func == (lhs: TestRecorder, rhs: TestRecorder) -> Bool { - return lhs.id == rhs.id + lhs.id == rhs.id } } @@ -159,7 +164,7 @@ internal final class TestTimer: TimerHandler, Equatable { } func retriveValueInPreferredUnit(atIndex i: Int) -> Double { - return self.values.withLockedValue { values in + self.values.withLockedValue { values in let value = values[i].1 return self.displayUnit.withLockedValue { displayUnit in guard let displayUnit else { @@ -178,7 +183,7 @@ internal final class TestTimer: TimerHandler, Equatable { } public static func == (lhs: TestTimer, rhs: TestTimer) -> Bool { - return lhs.id == rhs.id + lhs.id == rhs.id } } @@ -193,7 +198,7 @@ final class MetricsTests: XCTestCase { let router = Router() router.middlewares.add(MetricsMiddleware()) router.get("/hello") { _, _ -> String in - return "Hello" + "Hello" } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -240,7 +245,7 @@ final class MetricsTests: XCTestCase { let router = Router() router.middlewares.add(MetricsMiddleware()) router.get("/hello") { _, _ -> String in - return "hello" + "hello" } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -294,9 +299,12 @@ final class MetricsTests: XCTestCase { let router = Router() router.middlewares.add(MetricsMiddleware()) router.get("/hello") { _, _ -> Response in - return Response(status: .ok, body: .init { _ in - try await Task.sleep(for: .milliseconds(5)) - }) + Response( + status: .ok, + body: .init { _ in + try await Task.sleep(for: .milliseconds(5)) + } + ) } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in diff --git a/Tests/HummingbirdTests/MiddlewareTests.swift b/Tests/HummingbirdTests/MiddlewareTests.swift index a9a03d02..72c34c71 100644 --- a/Tests/HummingbirdTests/MiddlewareTests.swift +++ b/Tests/HummingbirdTests/MiddlewareTests.swift @@ -12,12 +12,13 @@ // //===----------------------------------------------------------------------===// -@testable import Hummingbird import HummingbirdTesting import Logging import NIOConcurrencyHelpers import XCTest +@testable import Hummingbird + final class MiddlewareTests: XCTestCase { static func randomBuffer(size: Int) -> ByteBuffer { var data = [UInt8](repeating: 0, count: size) @@ -36,7 +37,7 @@ final class MiddlewareTests: XCTestCase { let router = Router() router.add(middleware: TestMiddleware()) router.get("/hello") { _, _ -> String in - return "Hello" + "Hello" } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -59,7 +60,7 @@ final class MiddlewareTests: XCTestCase { router.add(middleware: TestMiddleware(string: "first")) router.add(middleware: TestMiddleware(string: "second")) router.get("/hello") { _, _ -> String in - return "Hello" + "Hello" } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -83,7 +84,7 @@ final class MiddlewareTests: XCTestCase { let router = Router() router.add(middleware: TestMiddleware()) router.get("/hello") { _, _ -> String in - return "Hello" + "Hello" } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -134,7 +135,7 @@ final class MiddlewareTests: XCTestCase { router.group() .add(middleware: TestMiddleware()) .get("test") { _, _ in - return "test" + "test" } let app = Application(responder: router.buildResponder()) @@ -171,7 +172,7 @@ final class MiddlewareTests: XCTestCase { router.group() .add(middleware: TransformMiddleware()) .get("test") { request, _ in - return Response(status: .ok, body: .init(asyncSequence: request.body)) + Response(status: .ok, body: .init(asyncSequence: request.body)) } let app = Application(responder: router.buildResponder()) @@ -202,7 +203,7 @@ final class MiddlewareTests: XCTestCase { let response = try await next(request, context) var editedResponse = response editedResponse.body = editedResponse.body.map { - return ByteBuffer(bytes: $0.readableBytesView.map { $0 ^ 255 }) + ByteBuffer(bytes: $0.readableBytesView.map { $0 ^ 255 }) } return editedResponse } @@ -211,7 +212,7 @@ final class MiddlewareTests: XCTestCase { router.group() .add(middleware: TransformMiddleware()) .get("test") { request, _ in - return Response(status: .ok, body: .init(asyncSequence: request.body)) + Response(status: .ok, body: .init(asyncSequence: request.body)) } let app = Application(responder: router.buildResponder()) @@ -228,7 +229,7 @@ final class MiddlewareTests: XCTestCase { let router = Router() router.add(middleware: CORSMiddleware()) router.get("/hello") { _, _ -> String in - return "Hello" + "Hello" } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -243,7 +244,7 @@ final class MiddlewareTests: XCTestCase { let router = Router() router.add(middleware: CORSMiddleware(allowOrigin: .all)) router.get("/hello") { _, _ -> String in - return "Hello" + "Hello" } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -256,29 +257,31 @@ final class MiddlewareTests: XCTestCase { func testCORSOptions() async throws { let router = Router() - router.add(middleware: CORSMiddleware( - allowOrigin: .all, - allowHeaders: [.contentType, .authorization], - allowMethods: [.get, .put, .delete, .options], - allowCredentials: true, - exposedHeaders: ["content-length"], - maxAge: .seconds(3600) - )) + router.add( + middleware: CORSMiddleware( + allowOrigin: .all, + allowHeaders: [.contentType, .authorization], + allowMethods: [.get, .put, .delete, .options], + allowCredentials: true, + exposedHeaders: ["content-length"], + maxAge: .seconds(3600) + ) + ) router.get("/hello") { _, _ -> String in - return "Hello" + "Hello" } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in try await client.execute(uri: "/hello", method: .options, headers: [.origin: "foo.com"]) { response in // headers come back in opposite order as middleware is applied to responses in that order XCTAssertEqual(response.headers[.accessControlAllowOrigin], "*") - let headers = response.headers[.accessControlAllowHeaders] // .joined(separator: ", ") + let headers = response.headers[.accessControlAllowHeaders] // .joined(separator: ", ") XCTAssertEqual(headers, "content-type, authorization") - let methods = response.headers[.accessControlAllowMethods] // .joined(separator: ", ") + let methods = response.headers[.accessControlAllowMethods] // .joined(separator: ", ") XCTAssertEqual(methods, "GET, PUT, DELETE, OPTIONS") XCTAssertEqual(response.headers[.accessControlAllowCredentials], "true") XCTAssertEqual(response.headers[.accessControlMaxAge], "3600") - let exposedHeaders = response.headers[.accessControlExposeHeaders] // .joined(separator: ", ") + let exposedHeaders = response.headers[.accessControlExposeHeaders] // .joined(separator: ", ") XCTAssertEqual(exposedHeaders, "content-length") } } @@ -301,7 +304,7 @@ final class MiddlewareTests: XCTestCase { let router = Router() router.add(middleware: LogRequestsMiddleware(.info)) router.get("test") { _, _ in - return HTTPResponse.Status.ok + HTTPResponse.Status.ok } let app = Application( responder: router.buildResponder(), @@ -329,13 +332,13 @@ final class MiddlewareTests: XCTestCase { let router = Router() router.group() .add(middleware: LogRequestsMiddleware(.info, includeHeaders: .all(except: [.connection]))) - .get("all") { _, _ in return HTTPResponse.Status.ok } + .get("all") { _, _ in HTTPResponse.Status.ok } router.group() .add(middleware: LogRequestsMiddleware(.info, includeHeaders: .none)) - .get("none") { _, _ in return HTTPResponse.Status.ok } + .get("none") { _, _ in HTTPResponse.Status.ok } router.group() .add(middleware: LogRequestsMiddleware(.info, includeHeaders: [.contentType])) - .get("some") { _, _ in return HTTPResponse.Status.ok } + .get("some") { _, _ in HTTPResponse.Status.ok } let app = Application( responder: router.buildResponder(), logger: Logger(label: "TestLogging") { label in @@ -384,10 +387,10 @@ final class MiddlewareTests: XCTestCase { let router = Router() router.group() .add(middleware: LogRequestsMiddleware(.info, includeHeaders: .all(), redactHeaders: [.authorization])) - .get("all") { _, _ in return HTTPResponse.Status.ok } + .get("all") { _, _ in HTTPResponse.Status.ok } router.group() .add(middleware: LogRequestsMiddleware(.info, includeHeaders: [.authorization], redactHeaders: [.authorization])) - .get("some") { _, _ in return HTTPResponse.Status.ok } + .get("some") { _, _ in HTTPResponse.Status.ok } let app = Application( responder: router.buildResponder(), logger: Logger(label: "TestLogging") { label in @@ -426,7 +429,7 @@ final class MiddlewareTests: XCTestCase { let router = Router() router.add(middleware: LogRequestsMiddleware(.info, includeHeaders: [.test])) router.get("test") { _, _ in - return HTTPResponse.Status.ok + HTTPResponse.Status.ok } let app = Application( responder: router.buildResponder(), @@ -458,7 +461,7 @@ final class MiddlewareTests: XCTestCase { TestMiddleware(string: "second") } router.get("/hello") { _, _ -> String in - return "Hello" + "Hello" } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -576,9 +579,12 @@ final class MiddlewareTests: XCTestCase { let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in try await client.execute(uri: "/hello", method: .get) { response in - XCTAssertEqual(response.headers[values: .test], (0.. Response) async throws -> Response { + public func handle( + _ request: Request, + context: TestRouterContext2, + next: (Request, TestRouterContext2) async throws -> Response + ) async throws -> Response { var context = context context.string = self.output return try await next(request, context) @@ -255,12 +259,12 @@ final class RouterTests: XCTestCase { .group("/test") .add(middleware: TestGroupMiddleware(output: "route1")) .get { _, context in - return context.string + context.string } .group("/group") .add(middleware: TestGroupMiddleware(output: "route2")) .get { _, context in - return context.string + context.string } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -302,7 +306,7 @@ final class RouterTests: XCTestCase { .group("/group", context: TestRouterContext2.self) .add(middleware: TestTransformMiddleware()) .get { _, context in - return EditedResponse(headers: [.test: context.string], response: "hello") + EditedResponse(headers: [.test: context.string], response: "hello") } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -351,7 +355,7 @@ final class RouterTests: XCTestCase { .add(middleware: TestTransformMiddleware()) .group("/group", context: TestRouterContext2.self) .get { _, context in - return EditedResponse(headers: [.test: context.string], response: "hello") + EditedResponse(headers: [.test: context.string], response: "hello") } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -368,7 +372,7 @@ final class RouterTests: XCTestCase { let router = Router() router .delete("/user/:id") { _, context -> String? in - return context.parameters.get("id", as: String.self) + context.parameters.get("id", as: String.self) } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -404,7 +408,7 @@ final class RouterTests: XCTestCase { let router = Router() router .delete("/user/:id") { _, context -> String in - return try context.parameters.require("id", as: TestEnum.self).rawValue + try context.parameters.require("id", as: TestEnum.self).rawValue } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -453,7 +457,7 @@ final class RouterTests: XCTestCase { let router = Router() router .get("/files/file.*/*.jpg") { _, _ -> HTTPResponse.Status in - return .ok + .ok } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -511,7 +515,7 @@ final class RouterTests: XCTestCase { func testRequestId() async throws { let router = Router() router.get("id") { _, context in - return context.id.description + context.id.description } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -529,7 +533,7 @@ final class RouterTests: XCTestCase { func testRedirect() async throws { let router = Router() router.get("redirect") { _, _ in - return Response.redirect(to: "/other") + Response.redirect(to: "/other") } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -545,7 +549,7 @@ final class RouterTests: XCTestCase { let router = Router() let routes = RouteCollection() routes.get("that") { _, _ in - return HTTPResponse.Status.ok + HTTPResponse.Status.ok } router.addRoutes(routes, atPath: "/this") let app = Application(responder: router.buildResponder()) @@ -622,7 +626,7 @@ final class RouterTests: XCTestCase { routes.group("2") .add(middleware: TestMiddleware("Hello")) .get("3") { _, _ in - return HTTPResponse.Status.ok + HTTPResponse.Status.ok } router.addRoutes(routes, atPath: "1") let app = Application(responder: router.buildResponder()) @@ -638,13 +642,13 @@ final class RouterTests: XCTestCase { func testCaseInsensitive() async throws { let router = Router(options: .caseInsensitive) router.get("Uppercased") { _, _ in - return HTTPResponse.Status.ok + HTTPResponse.Status.ok } router.get("lowercased") { _, _ in - return HTTPResponse.Status.ok + HTTPResponse.Status.ok } router.group("group").get("Uppercased") { _, _ in - return HTTPResponse.Status.ok + HTTPResponse.Status.ok } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -663,10 +667,10 @@ final class RouterTests: XCTestCase { func testRecursiveWildcard() async throws { let router = Router() router.get("/api/v1/**/john") { _, context in - return "John \(context.parameters.getCatchAll().joined(separator: "/"))" + "John \(context.parameters.getCatchAll().joined(separator: "/"))" } router.get("/api/v1/**/jane/subpath") { _, context in - return "Jane \(context.parameters.getCatchAll().joined(separator: "/"))" + "Jane \(context.parameters.getCatchAll().joined(separator: "/"))" } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -683,16 +687,16 @@ final class RouterTests: XCTestCase { func testAutoGenerateHeadEndpoints() async throws { let router = Router(options: .autoGenerateHeadEndpoints) router.get("nohead") { _, _ in - return "TestString" + "TestString" } router.head("withhead") { _, _ in - return Response(status: .ok, headers: [.contentLength: "0", .contentLanguage: "en"], body: .init()) + Response(status: .ok, headers: [.contentLength: "0", .contentLanguage: "en"], body: .init()) } router.get("withhead") { _, _ in - return Response(status: .ok, headers: [.contentLength: "999"], body: .init()) + Response(status: .ok, headers: [.contentLength: "999"], body: .init()) } router.post("post") { _, _ in - return Response(status: .ok, headers: [.contentLength: "999"], body: .init()) + Response(status: .ok, headers: [.contentLength: "999"], body: .init()) } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -714,7 +718,7 @@ final class RouterTests: XCTestCase { let route = "/test" let router = Router() router.get("\(route)") { _, _ in - return "TestString" + "TestString" } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in diff --git a/Tests/HummingbirdTests/TestTracer.swift b/Tests/HummingbirdTests/TestTracer.swift index da859a0a..4b8e04e1 100644 --- a/Tests/HummingbirdTests/TestTracer.swift +++ b/Tests/HummingbirdTests/TestTracer.swift @@ -59,7 +59,7 @@ final class TestTracer: Tracer { public func forceFlush() {} func extract(_ carrier: Carrier, into context: inout ServiceContext, using extractor: Extract) - where + where Extract: Extractor, Carrier == Extract.Carrier { @@ -68,7 +68,7 @@ final class TestTracer: Tracer { } func inject(_ context: ServiceContext, into carrier: inout Carrier, using injector: Inject) - where + where Inject: Injector, Carrier == Inject.Carrier { @@ -178,5 +178,5 @@ final class TestSpan: Span { } } -extension TestTracer: @unchecked Sendable {} // only intended for single threaded testing -extension TestSpan: @unchecked Sendable {} // only intended for single threaded testing +extension TestTracer: @unchecked Sendable {} // only intended for single threaded testing +extension TestSpan: @unchecked Sendable {} // only intended for single threaded testing diff --git a/Tests/HummingbirdTests/TracingTests.swift b/Tests/HummingbirdTests/TracingTests.swift index f4075f21..255ef1ba 100644 --- a/Tests/HummingbirdTests/TracingTests.swift +++ b/Tests/HummingbirdTests/TracingTests.swift @@ -16,10 +16,11 @@ import HTTPTypes import Hummingbird import HummingbirdRouter import HummingbirdTesting -@testable import Instrumentation import Tracing import XCTest +@testable import Instrumentation + final class TracingTests: XCTestCase { func testTracingMiddleware() async throws { let expectation = expectation(description: "Expected span to be ended.") @@ -31,7 +32,7 @@ final class TracingTests: XCTestCase { let router = Router() router.middlewares.add(TracingMiddleware(attributes: ["net.host.name": "127.0.0.1", "net.host.port": 8080])) router.get("users/{id}") { _, _ -> String in - return "42" + "42" } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -50,14 +51,17 @@ final class TracingTests: XCTestCase { XCTAssertNil(span.status) XCTAssertTrue(span.recordedErrors.isEmpty) - XCTAssertSpanAttributesEqual(span.attributes, [ - "http.method": "GET", - "http.target": "/users/42", - "http.status_code": 200, - "http.response_content_length": 2, - "net.host.name": "127.0.0.1", - "net.host.port": 8080, - ]) + XCTAssertSpanAttributesEqual( + span.attributes, + [ + "http.method": "GET", + "http.target": "/users/42", + "http.status_code": 200, + "http.response_content_length": 2, + "net.host.name": "127.0.0.1", + "net.host.port": 8080, + ] + ) } func testTracingMiddlewareWithRouterBuilder() async throws { @@ -88,14 +92,17 @@ final class TracingTests: XCTestCase { XCTAssertNil(span.status) XCTAssertTrue(span.recordedErrors.isEmpty) - XCTAssertSpanAttributesEqual(span.attributes, [ - "http.method": "GET", - "http.target": "/users/42", - "http.status_code": 200, - "http.response_content_length": 2, - "net.host.name": "127.0.0.1", - "net.host.port": 8080, - ]) + XCTAssertSpanAttributesEqual( + span.attributes, + [ + "http.method": "GET", + "http.target": "/users/42", + "http.status_code": 200, + "http.response_content_length": 2, + "net.host.name": "127.0.0.1", + "net.host.port": 8080, + ] + ) } func testTracingMiddlewareWithFile() async throws { @@ -132,20 +139,23 @@ final class TracingTests: XCTestCase { XCTAssertNil(span.status) XCTAssertTrue(span.recordedErrors.isEmpty) - XCTAssertSpanAttributesEqual(span.attributes, [ - "http.method": "GET", - "http.target": "/\(filename)", - "http.status_code": 200, - "http.response_content_length": .int64(Int64(text.count)), - "net.host.name": "127.0.0.1", - "net.host.port": 8080, - ]) + XCTAssertSpanAttributesEqual( + span.attributes, + [ + "http.method": "GET", + "http.target": "/\(filename)", + "http.status_code": 200, + "http.response_content_length": .int64(Int64(text.count)), + "net.host.name": "127.0.0.1", + "net.host.port": 8080, + ] + ) } func testMiddlewareSkippingEndpoint() async throws { struct DeadendMiddleware: RouterMiddleware { func handle(_ input: Request, context: Context, next: (Request, Context) async throws -> Response) async throws -> Response { - return .init(status: .ok) + .init(status: .ok) } } let expectation = expectation(description: "Expected span to be ended.") @@ -177,12 +187,15 @@ final class TracingTests: XCTestCase { XCTAssertNil(span.status) XCTAssertTrue(span.recordedErrors.isEmpty) - XCTAssertSpanAttributesEqual(span.attributes, [ - "http.method": "GET", - "http.target": "/test/this", - "http.status_code": 200, - "http.response_content_length": 0, - ]) + XCTAssertSpanAttributesEqual( + span.attributes, + [ + "http.method": "GET", + "http.target": "/test/this", + "http.status_code": 200, + "http.response_content_length": 0, + ] + ) } func testTracingMiddlewareServerError() async throws { @@ -216,12 +229,15 @@ final class TracingTests: XCTestCase { let error = try XCTUnwrap(span.recordedErrors.first?.0 as? HTTPError, "Recorded unexpected errors: \(span.recordedErrors)") XCTAssertEqual(error.status, .internalServerError) - XCTAssertSpanAttributesEqual(span.attributes, [ - "http.method": "POST", - "http.target": "/users", - "http.status_code": 500, - "http.request_content_length": 2, - ]) + XCTAssertSpanAttributesEqual( + span.attributes, + [ + "http.method": "POST", + "http.target": "/users", + "http.status_code": 500, + "http.request_content_length": 2, + ] + ) } func testTracingMiddlewareIncludingHeaders() async throws { @@ -232,9 +248,11 @@ final class TracingTests: XCTestCase { InstrumentationSystem.bootstrapInternal(tracer) let router = Router() - router.middlewares.add(TracingMiddleware(recordingHeaders: [ - .accept, .contentType, .cacheControl, .test, - ])) + router.middlewares.add( + TracingMiddleware(recordingHeaders: [ + .accept, .contentType, .cacheControl, .test, + ]) + ) router.get("users/{id}") { _, _ -> Response in var headers = HTTPFields() headers[values: .cacheControl] = ["86400", "public"] @@ -265,16 +283,19 @@ final class TracingTests: XCTestCase { XCTAssertNil(span.status) XCTAssertTrue(span.recordedErrors.isEmpty) - XCTAssertSpanAttributesEqual(span.attributes, [ - "http.method": "GET", - "http.target": "/users/42", - "http.status_code": 200, - "http.response_content_length": 2, - "http.request.header.accept": .stringArray(["text/plain", "application/json"]), - "http.request.header.cache_control": "no-cache", - "http.response.header.content_type": "text/plain", - "http.response.header.cache_control": .stringArray(["86400", "public"]), - ]) + XCTAssertSpanAttributesEqual( + span.attributes, + [ + "http.method": "GET", + "http.target": "/users/42", + "http.status_code": 200, + "http.response_content_length": 2, + "http.request.header.accept": .stringArray(["text/plain", "application/json"]), + "http.request.header.cache_control": "no-cache", + "http.response.header.content_type": "text/plain", + "http.response.header.cache_control": .stringArray(["86400", "public"]), + ] + ) } func testTracingMiddlewareEmptyResponse() async throws { @@ -287,7 +308,7 @@ final class TracingTests: XCTestCase { let router = Router() router.middlewares.add(TracingMiddleware()) router.post("/users") { _, _ -> HTTPResponse.Status in - return .noContent + .noContent } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -305,12 +326,15 @@ final class TracingTests: XCTestCase { XCTAssertNil(span.status) XCTAssertTrue(span.recordedErrors.isEmpty) - XCTAssertSpanAttributesEqual(span.attributes, [ - "http.method": "POST", - "http.target": "/users", - "http.status_code": 204, - "http.response_content_length": 0, - ]) + XCTAssertSpanAttributesEqual( + span.attributes, + [ + "http.method": "POST", + "http.target": "/users", + "http.status_code": 204, + "http.response_content_length": 0, + ] + ) } func testTracingMiddlewareIndexRoute() async throws { @@ -323,7 +347,7 @@ final class TracingTests: XCTestCase { let router = Router() router.middlewares.add(TracingMiddleware()) router.get("/") { _, _ -> HTTPResponse.Status in - return .ok + .ok } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -341,12 +365,15 @@ final class TracingTests: XCTestCase { XCTAssertNil(span.status) XCTAssertTrue(span.recordedErrors.isEmpty) - XCTAssertSpanAttributesEqual(span.attributes, [ - "http.method": "GET", - "http.target": "/", - "http.status_code": 200, - "http.response_content_length": 0, - ]) + XCTAssertSpanAttributesEqual( + span.attributes, + [ + "http.method": "GET", + "http.target": "/", + "http.status_code": 200, + "http.response_content_length": 0, + ] + ) } func testTracingMiddlewareRouteNotFound() async throws { @@ -376,11 +403,14 @@ final class TracingTests: XCTestCase { let error = try XCTUnwrap(span.recordedErrors.first?.0 as? HTTPError, "Recorded unexpected errors: \(span.recordedErrors)") XCTAssertEqual(error.status, .notFound) - XCTAssertSpanAttributesEqual(span.attributes, [ - "http.method": "GET", - "http.target": "/", - "http.status_code": 404, - ]) + XCTAssertSpanAttributesEqual( + span.attributes, + [ + "http.method": "GET", + "http.target": "/", + "http.status_code": 404, + ] + ) } /// Test span is ended even if the response body with the span end is not run @@ -403,7 +433,7 @@ final class TracingTests: XCTestCase { router.middlewares.add(ErrorMiddleware()) router.middlewares.add(TracingMiddleware()) router.get("users/:id") { _, _ -> String in - return "42" + "42" } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -434,7 +464,7 @@ final class TracingTests: XCTestCase { let router = Router() router.middlewares.add(TracingMiddleware()) router.get("users/:id") { _, _ -> Response in - return Response( + Response( status: .ok, body: .init { _ in try await Task.sleep(for: .milliseconds(100)) } ) @@ -583,7 +613,7 @@ final class TracingTests: XCTestCase { router.get("/") { _, _ -> HTTPResponse.Status in try await Task.sleep(nanoseconds: 1000) return InstrumentationSystem.tracer.withAnySpan("testing", ofKind: .server) { _ in - return .ok + .ok } } let app = Application(responder: router.buildResponder()) diff --git a/Tests/HummingbirdTests/TrieRouterTests.swift b/Tests/HummingbirdTests/TrieRouterTests.swift index 329bdc21..93bf4f3b 100644 --- a/Tests/HummingbirdTests/TrieRouterTests.swift +++ b/Tests/HummingbirdTests/TrieRouterTests.swift @@ -12,9 +12,10 @@ // //===----------------------------------------------------------------------===// -@testable @_spi(Internal) import Hummingbird import XCTest +@testable @_spi(Internal) import Hummingbird + final class TrieRouterTests: XCTestCase { func testPathComponentsTrie() { let trieBuilder = RouterPathTrieBuilder() diff --git a/Tests/HummingbirdTests/URLEncodedForm/Application+URLEncodedFormTests.swift b/Tests/HummingbirdTests/URLEncodedForm/Application+URLEncodedFormTests.swift index 8d60f493..c3847ce2 100644 --- a/Tests/HummingbirdTests/URLEncodedForm/Application+URLEncodedFormTests.swift +++ b/Tests/HummingbirdTests/URLEncodedForm/Application+URLEncodedFormTests.swift @@ -60,7 +60,7 @@ final class HummingBirdURLEncodedTests: XCTestCase { func testEncode() async throws { let router = Router(context: URLEncodedCodingRequestContext.self) router.get("/user") { _, _ -> User in - return User(name: "John Smith", email: "john.smith@email.com", age: 25) + User(name: "John Smith", email: "john.smith@email.com", age: 25) } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in diff --git a/Tests/HummingbirdTests/URLEncodedForm/URLDecoderTests.swift b/Tests/HummingbirdTests/URLEncodedForm/URLDecoderTests.swift index 8da4f379..cd3f861d 100644 --- a/Tests/HummingbirdTests/URLEncodedForm/URLDecoderTests.swift +++ b/Tests/HummingbirdTests/URLEncodedForm/URLDecoderTests.swift @@ -12,9 +12,10 @@ // //===----------------------------------------------------------------------===// -@testable import Hummingbird import XCTest +@testable import Hummingbird + final class URLDecodedFormDecoderTests: XCTestCase { func testForm(_ value: Input, query: String, decoder: URLEncodedFormDecoder = .init()) { do { @@ -75,8 +76,25 @@ final class URLDecodedFormDecoderTests: XCTestCase { let f: [Float] let d: [Double] } - let test = Test(b: [true, false], i: [34], i8: [23], i16: [9], i32: [-6872], i64: [23], u: [0], u8: [255], u16: [7673], u32: [88222], u64: [234], f: [-1.1], d: [8]) - self.testForm(test, query: "b[]=true&b[]=false&i[]=34&i8[]=23&i16[]=9&i32[]=-6872&i64[]=23&u[]=0&u8[]=255&u16[]=7673&u32[]=88222&u64[]=234&f[]=-1.1&d[]=8") + let test = Test( + b: [true, false], + i: [34], + i8: [23], + i16: [9], + i32: [-6872], + i64: [23], + u: [0], + u8: [255], + u16: [7673], + u32: [88222], + u64: [234], + f: [-1.1], + d: [8] + ) + self.testForm( + test, + query: "b[]=true&b[]=false&i[]=34&i8[]=23&i16[]=9&i32[]=-6872&i64[]=23&u[]=0&u8[]=255&u16[]=7673&u32[]=88222&u64[]=234&f[]=-1.1&d[]=8" + ) } func testArraysWithIndices() { @@ -88,19 +106,19 @@ final class URLDecodedFormDecoderTests: XCTestCase { let test2 = Test(arr: [12, 45, 54, 55, -5, 5, 9, 33, 0, 9, 4, 33]) let query = """ - arr[0]=12\ - &arr[1]=45\ - &arr[2]=54\ - &arr[3]=55\ - &arr[4]=-5\ - &arr[5]=5\ - &arr[6]=9\ - &arr[7]=33\ - &arr[8]=0\ - &arr[9]=9\ - &arr[10]=4\ - &arr[11]=33 - """ + arr[0]=12\ + &arr[1]=45\ + &arr[2]=54\ + &arr[3]=55\ + &arr[4]=-5\ + &arr[5]=5\ + &arr[6]=9\ + &arr[7]=33\ + &arr[8]=0\ + &arr[9]=9\ + &arr[10]=4\ + &arr[11]=33 + """ self.testForm(test2, query: query) } diff --git a/Tests/HummingbirdTests/URLEncodedForm/URLEncodedNodeTests.swift b/Tests/HummingbirdTests/URLEncodedForm/URLEncodedNodeTests.swift index c9c51f92..160da9c7 100644 --- a/Tests/HummingbirdTests/URLEncodedForm/URLEncodedNodeTests.swift +++ b/Tests/HummingbirdTests/URLEncodedForm/URLEncodedNodeTests.swift @@ -12,9 +12,10 @@ // //===----------------------------------------------------------------------===// -@testable import Hummingbird import XCTest +@testable import Hummingbird + final class URLEncodedFormNodeTests: XCTestCase { static func XCTAssertEncodedEqual(_ lhs: String, _ rhs: String) { let lhs = lhs.split(separator: "&") diff --git a/Tests/HummingbirdTests/URLEncodedForm/URLEncoderTests.swift b/Tests/HummingbirdTests/URLEncodedForm/URLEncoderTests.swift index 4f638d2f..66220401 100644 --- a/Tests/HummingbirdTests/URLEncodedForm/URLEncoderTests.swift +++ b/Tests/HummingbirdTests/URLEncodedForm/URLEncoderTests.swift @@ -85,8 +85,25 @@ final class URLEncodedFormEncoderTests: XCTestCase { let f: [Float] let d: [Double] } - let test = Test(b: [true], i: [34], i8: [23], i16: [9], i32: [-6872], i64: [23], u: [0], u8: [255], u16: [7673], u32: [88222], u64: [234], f: [-1.1], d: [8]) - self.testForm(test, query: "b[]=true&i[]=34&i8[]=23&i16[]=9&i32[]=-6872&i64[]=23&u[]=0&u8[]=255&u16[]=7673&u32[]=88222&u64[]=234&f[]=-1.1&d[]=8.0") + let test = Test( + b: [true], + i: [34], + i8: [23], + i16: [9], + i32: [-6872], + i64: [23], + u: [0], + u8: [255], + u16: [7673], + u32: [88222], + u64: [234], + f: [-1.1], + d: [8] + ) + self.testForm( + test, + query: "b[]=true&i[]=34&i8[]=23&i16[]=9&i32[]=-6872&i64[]=23&u[]=0&u8[]=255&u16[]=7673&u32[]=88222&u64[]=234&f[]=-1.1&d[]=8.0" + ) } func testStringSpecialCharactersEncode() { diff --git a/Tests/HummingbirdTests/UUIDTests.swift b/Tests/HummingbirdTests/UUIDTests.swift index 845d0f71..f5de13f3 100644 --- a/Tests/HummingbirdTests/UUIDTests.swift +++ b/Tests/HummingbirdTests/UUIDTests.swift @@ -20,7 +20,7 @@ final class UUIDTests: XCTestCase { func testGetUUID() async throws { let router = Router() router.get(":id") { _, context -> UUID? in - return context.parameters.get("id", as: UUID.self) + context.parameters.get("id", as: UUID.self) } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in @@ -36,7 +36,7 @@ final class UUIDTests: XCTestCase { func testRequireUUID() async throws { let router = Router() router.get(":id") { _, context -> UUID in - return try context.parameters.require("id", as: UUID.self) + try context.parameters.require("id", as: UUID.self) } let app = Application(responder: router.buildResponder()) try await app.test(.router) { client in diff --git a/scripts/validate.sh b/scripts/validate.sh index bb67406e..f9499491 100755 --- a/scripts/validate.sh +++ b/scripts/validate.sh @@ -31,8 +31,6 @@ SWIFT_FORMAT_VERSION=0.53.10 set -eu here="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -which swiftformat > /dev/null 2>&1 || (echo "swiftformat not installed. You can install it using 'brew install swiftformat'" ; exit -1) - function replace_acceptable_years() { # this needs to replace all acceptable forms with 'YEARS' sed -e 's/20[12][0-9]-20[12][0-9]/YEARS/' -e 's/20[12][0-9]/YEARS/' -e '/^#!/ d' @@ -40,13 +38,9 @@ function replace_acceptable_years() { printf "=> Checking format... " FIRST_OUT="$(git status --porcelain)" -if [[ -n "${CI-""}" ]]; then - printf "(using v$(mint run NickLockwood/SwiftFormat@"$SWIFT_FORMAT_VERSION" --version)) " - mint run NickLockwood/SwiftFormat@"$SWIFT_FORMAT_VERSION" . > /dev/null 2>&1 -else - printf "(using v$(swiftformat --version)) " - swiftformat . > /dev/null 2>&1 -fi +git ls-files -z '*.swift' | xargs -0 swift format format --parallel --in-place +git diff --exit-code '*.swift' + SECOND_OUT="$(git status --porcelain)" if [[ "$FIRST_OUT" != "$SECOND_OUT" ]]; then printf "\033[0;31mformatting issues!\033[0m\n" @@ -55,10 +49,11 @@ if [[ "$FIRST_OUT" != "$SECOND_OUT" ]]; then else printf "\033[0;32mokay.\033[0m\n" fi -exit printf "=> Checking license headers... " tmp=$(mktemp /tmp/.soto-core-sanity_XXXXXX) +exit 0 + for language in swift-or-c; do declare -a matching_files declare -a exceptions @@ -66,18 +61,18 @@ for language in swift-or-c; do matching_files=( -name '*' ) case "$language" in swift-or-c) - exceptions=( -path '*Sources/INIParser/*' -o -path '*Sources/CSotoExpat/*' -o -path '*Benchmark/.build/*' -o -name Package.swift) + exceptions=( -path '*/Benchmarks/.build/*' -o -name Package.swift) matching_files=( -name '*.swift' -o -name '*.c' -o -name '*.h' ) cat > "$tmp" <<"EOF" //===----------------------------------------------------------------------===// // -// This source file is part of the Hummingbird open source project +// This source file is part of the Hummingbird server framework project // // Copyright (c) YEARS the Hummingbird authors // Licensed under Apache License v2.0 // // See LICENSE.txt for license information -// See CONTRIBUTORS.txt for the list of Hummingbird authors +// See hummingbird/CONTRIBUTORS.txt for the list of Hummingbird authors // // SPDX-License-Identifier: Apache-2.0 // @@ -89,13 +84,13 @@ EOF cat > "$tmp" <<"EOF" ##===----------------------------------------------------------------------===## ## -## This source file is part of the Hummingbird open source project +## This source file is part of the Hummingbird server framework project ## ## Copyright (c) YEARS the Hummingbird authors ## Licensed under Apache License v2.0 ## ## See LICENSE.txt for license information -## See CONTRIBUTORS.txt for the list of Hummingbird authors +## See hummingbird/CONTRIBUTORS.txt for the list of Hummingbird authors ## ## SPDX-License-Identifier: Apache-2.0 ##