diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index ef49792f..b528cb24 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,11 +5,13 @@ on: push jobs: build: runs-on: ubuntu-latest - container: ghcr.io/swiftwasm/swift:5.9 + container: swift:6.0 steps: - uses: actions/checkout@v4 - run: swift --version - - run: swift build -c debug --triple wasm32-unknown-wasi + - run: swift sdk install https://github.com/swiftwasm/swift/releases/download/swift-wasm-6.0.2-RELEASE/swift-wasm-6.0.2-RELEASE-wasm32-unknown-wasi.artifactbundle.zip --checksum 6ffedb055cb9956395d9f435d03d53ebe9f6a8d45106b979d1b7f53358e1dcb4 + + - run: swift build --swift-sdk wasm32-unknown-wasi diff --git a/.swift-version b/.swift-version new file mode 100644 index 00000000..090ea9da --- /dev/null +++ b/.swift-version @@ -0,0 +1 @@ +6.0.3 diff --git a/Justfile b/Justfile index 828f6f4c..bcb969cc 100644 --- a/Justfile +++ b/Justfile @@ -1,5 +1,8 @@ +format: + swift format --in-place --recursive . + build: - swift build -c debug --triple wasm32-unknown-wasi + swift build -c debug --swift-sdk wasm32-unknown-wasi demo: build fastly compute serve --skip-build --file ./.build/debug/ComputeDemo.wasm diff --git a/LICENSE b/LICENSE index a612ad98..30ad7b2e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,373 +1,20 @@ -Mozilla Public License Version 2.0 -================================== - -1. Definitions --------------- - -1.1. "Contributor" - means each individual or legal entity that creates, contributes to - the creation of, or owns Covered Software. - -1.2. "Contributor Version" - means the combination of the Contributions of others (if any) used - by a Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - means Source Code Form to which the initial Contributor has attached - the notice in Exhibit A, the Executable Form of such Source Code - Form, and Modifications of such Source Code Form, in each case - including portions thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - (a) that the initial Contributor has attached the notice described - in Exhibit B to the Covered Software; or - - (b) that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the - terms of a Secondary License. - -1.6. "Executable Form" - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - means a work that combines Covered Software with other material, in - a separate file or files, that is not Covered Software. - -1.8. "License" - means this document. - -1.9. "Licensable" - means having the right to grant, to the maximum extent possible, - whether at the time of the initial grant or subsequently, any and - all of the rights conveyed by this License. - -1.10. "Modifications" - means any of the following: - - (a) any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered - Software; or - - (b) any new file in Source Code Form that contains any Covered - Software. - -1.11. "Patent Claims" of a Contributor - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the - License, by the making, using, selling, offering for sale, having - made, import, or transfer of either its Contributions or its - Contributor Version. - -1.12. "Secondary License" - means either the GNU General Public License, Version 2.0, the GNU - Lesser General Public License, Version 2.1, the GNU Affero General - Public License, Version 3.0, or any later versions of those - licenses. - -1.13. "Source Code Form" - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that - controls, is controlled by, or is under common control with You. For - purposes of this definition, "control" means (a) the power, direct - or indirect, to cause the direction or management of such entity, - whether by contract or otherwise, or (b) ownership of more than - fifty percent (50%) of the outstanding shares or beneficial - ownership of such entity. - -2. License Grants and Conditions --------------------------------- - -2.1. Grants - -Each Contributor hereby grants You a world-wide, royalty-free, -non-exclusive license: - -(a) under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - -(b) under Patent Claims of such Contributor to make, use, sell, offer - for sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - -The licenses granted in Section 2.1 with respect to any Contribution -become effective for each Contribution on the date the Contributor first -distributes such Contribution. - -2.3. Limitations on Grant Scope - -The licenses granted in this Section 2 are the only rights granted under -this License. No additional rights or licenses will be implied from the -distribution or licensing of Covered Software under this License. -Notwithstanding Section 2.1(b) above, no patent license is granted by a -Contributor: - -(a) for any code that a Contributor has removed from Covered Software; - or - -(b) for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - -(c) under Patent Claims infringed by Covered Software in the absence of - its Contributions. - -This License does not grant any rights in the trademarks, service marks, -or logos of any Contributor (except as may be necessary to comply with -the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - -No Contributor makes additional grants as a result of Your choice to -distribute the Covered Software under a subsequent version of this -License (see Section 10.2) or under the terms of a Secondary License (if -permitted under the terms of Section 3.3). - -2.5. Representation - -Each Contributor represents that the Contributor believes its -Contributions are its original creation(s) or it has sufficient rights -to grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - -This License is not intended to limit any rights You have under -applicable copyright doctrines of fair use, fair dealing, or other -equivalents. - -2.7. Conditions - -Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted -in Section 2.1. - -3. Responsibilities -------------------- - -3.1. Distribution of Source Form - -All distribution of Covered Software in Source Code Form, including any -Modifications that You create or to which You contribute, must be under -the terms of this License. You must inform recipients that the Source -Code Form of the Covered Software is governed by the terms of this -License, and how they can obtain a copy of this License. You may not -attempt to alter or restrict the recipients' rights in the Source Code -Form. - -3.2. Distribution of Executable Form - -If You distribute Covered Software in Executable Form then: - -(a) such Covered Software must also be made available in Source Code - Form, as described in Section 3.1, and You must inform recipients of - the Executable Form how they can obtain a copy of such Source Code - Form by reasonable means in a timely manner, at a charge no more - than the cost of distribution to the recipient; and - -(b) You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter - the recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - -You may create and distribute a Larger Work under terms of Your choice, -provided that You also comply with the requirements of this License for -the Covered Software. If the Larger Work is a combination of Covered -Software with a work governed by one or more Secondary Licenses, and the -Covered Software is not Incompatible With Secondary Licenses, this -License permits You to additionally distribute such Covered Software -under the terms of such Secondary License(s), so that the recipient of -the Larger Work may, at their option, further distribute the Covered -Software under the terms of either this License or such Secondary -License(s). - -3.4. Notices - -You may not remove or alter the substance of any license notices -(including copyright notices, patent notices, disclaimers of warranty, -or limitations of liability) contained within the Source Code Form of -the Covered Software, except that You may alter any license notices to -the extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - -You may choose to offer, and to charge a fee for, warranty, support, -indemnity or liability obligations to one or more recipients of Covered -Software. However, You may do so only on Your own behalf, and not on -behalf of any Contributor. You must make it absolutely clear that any -such warranty, support, indemnity, or liability obligation is offered by -You alone, and You hereby agree to indemnify every Contributor for any -liability incurred by such Contributor as a result of warranty, support, -indemnity or liability terms You offer. You may include additional -disclaimers of warranty and limitations of liability specific to any -jurisdiction. - -4. Inability to Comply Due to Statute or Regulation ---------------------------------------------------- - -If it is impossible for You to comply with any of the terms of this -License with respect to some or all of the Covered Software due to -statute, judicial order, or regulation then You must: (a) comply with -the terms of this License to the maximum extent possible; and (b) -describe the limitations and the code they affect. Such description must -be placed in a text file included with all distributions of the Covered -Software under this License. Except to the extent prohibited by statute -or regulation, such description must be sufficiently detailed for a -recipient of ordinary skill to be able to understand it. - -5. Termination --------------- - -5.1. The rights granted under this License will terminate automatically -if You fail to comply with any of its terms. However, if You become -compliant, then the rights granted under this License from a particular -Contributor are reinstated (a) provisionally, unless and until such -Contributor explicitly and finally terminates Your grants, and (b) on an -ongoing basis, if such Contributor fails to notify You of the -non-compliance by some reasonable means prior to 60 days after You have -come back into compliance. Moreover, Your grants from a particular -Contributor are reinstated on an ongoing basis if such Contributor -notifies You of the non-compliance by some reasonable means, this is the -first time You have received notice of non-compliance with this License -from such Contributor, and You become compliant prior to 30 days after -Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent -infringement claim (excluding declaratory judgment actions, -counter-claims, and cross-claims) alleging that a Contributor Version -directly or indirectly infringes any patent, then the rights granted to -You by any and all Contributors for the Covered Software under Section -2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all -end user license agreements (excluding distributors and resellers) which -have been validly granted by You or Your distributors under this License -prior to termination shall survive termination. - -************************************************************************ -* * -* 6. Disclaimer of Warranty * -* ------------------------- * -* * -* Covered Software is provided under this License on an "as is" * -* basis, without warranty of any kind, either expressed, implied, or * -* statutory, including, without limitation, warranties that the * -* Covered Software is free of defects, merchantable, fit for a * -* particular purpose or non-infringing. The entire risk as to the * -* quality and performance of the Covered Software is with You. * -* Should any Covered Software prove defective in any respect, You * -* (not any Contributor) assume the cost of any necessary servicing, * -* repair, or correction. This disclaimer of warranty constitutes an * -* essential part of this License. No use of any Covered Software is * -* authorized under this License except under this disclaimer. * -* * -************************************************************************ - -************************************************************************ -* * -* 7. Limitation of Liability * -* -------------------------- * -* * -* Under no circumstances and under no legal theory, whether tort * -* (including negligence), contract, or otherwise, shall any * -* Contributor, or anyone who distributes Covered Software as * -* permitted above, be liable to You for any direct, indirect, * -* special, incidental, or consequential damages of any character * -* including, without limitation, damages for lost profits, loss of * -* goodwill, work stoppage, computer failure or malfunction, or any * -* and all other commercial damages or losses, even if such party * -* shall have been informed of the possibility of such damages. This * -* limitation of liability shall not apply to liability for death or * -* personal injury resulting from such party's negligence to the * -* extent applicable law prohibits such limitation. Some * -* jurisdictions do not allow the exclusion or limitation of * -* incidental or consequential damages, so this exclusion and * -* limitation may not apply to You. * -* * -************************************************************************ - -8. Litigation -------------- - -Any litigation relating to this License may be brought only in the -courts of a jurisdiction where the defendant maintains its principal -place of business and such litigation shall be governed by laws of that -jurisdiction, without reference to its conflict-of-law provisions. -Nothing in this Section shall prevent a party's ability to bring -cross-claims or counter-claims. - -9. Miscellaneous ----------------- - -This License represents the complete agreement concerning the subject -matter hereof. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent -necessary to make it enforceable. Any law or regulation which provides -that the language of a contract shall be construed against the drafter -shall not be used to construe this License against a Contributor. - -10. Versions of the License ---------------------------- - -10.1. New Versions - -Mozilla Foundation is the license steward. Except as provided in Section -10.3, no one other than the license steward has the right to modify or -publish new versions of this License. Each version will be given a -distinguishing version number. - -10.2. Effect of New Versions - -You may distribute the Covered Software under the terms of the version -of the License under which You originally received the Covered Software, -or under the terms of any subsequent version published by the license -steward. - -10.3. Modified Versions - -If you create software not governed by this License, and you want to -create a new license for such software, you may create and use a -modified version of this License if you rename the license and remove -any references to the name of the license steward (except to note that -such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary -Licenses - -If You choose to distribute Source Code Form that is Incompatible With -Secondary Licenses under the terms of this version of the License, the -notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice -------------------------------------------- - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular -file, then You may include the notice in a location (such as a LICENSE -file in a relevant directory) where a recipient would be likely to look -for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice ---------------------------------------------------------- - - This Source Code Form is "Incompatible With Secondary Licenses", as - defined by the Mozilla Public License, v. 2.0. +MIT License + +Copyright (c) 2024 Swift Cloud, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/Package.swift b/Package.swift index 18870eb2..8a9054bd 100644 --- a/Package.swift +++ b/Package.swift @@ -14,7 +14,7 @@ let package = Package( .library(name: "Compute", targets: ["Compute"]) ], dependencies: [ - .package(url: "https://github.com/apple/swift-crypto", from: "3.0.0") + .package(url: "https://github.com/apple/swift-crypto", "1.0.0"..<"4.0.0") ], targets: [ .target( @@ -35,5 +35,9 @@ let package = Package( name: "ComputeTests", dependencies: ["Compute"] ), + ], + swiftLanguageVersions: [ + .version("6"), + .v5, ] ) diff --git a/Sources/Compute/Cache.swift b/Sources/Compute/Cache.swift index ed627553..55832c47 100644 --- a/Sources/Compute/Cache.swift +++ b/Sources/Compute/Cache.swift @@ -1,13 +1,15 @@ // // Cache.swift -// +// // // Created by Andrew Barba on 9/13/23. // public struct Cache: Sendable { - public static func getOrSet(_ key: String, _ handler: () async throws -> (FetchResponse, CachePolicy)) async throws -> Entry { + public static func getOrSet( + _ key: String, _ handler: () async throws -> (FetchResponse, CachePolicy) + ) async throws -> Entry { let trx = try await Fastly.Cache.getOrSet(key) { let (res, cachePolicy) = try await handler() let length = res.headers[.contentLength].flatMap(Int.init) @@ -16,7 +18,9 @@ public struct Cache: Sendable { return try .init(trx) } - public static func getOrSet(_ key: String, _ handler: () async throws -> ([UInt8], CachePolicy)) async throws -> Entry { + public static func getOrSet(_ key: String, _ handler: () async throws -> ([UInt8], CachePolicy)) + async throws -> Entry + { let trx = try await Fastly.Cache.getOrSet(key) { let (bytes, cachePolicy) = try await handler() return (.bytes(bytes), cachePolicy) @@ -24,7 +28,9 @@ public struct Cache: Sendable { return try .init(trx) } - public static func getOrSet(_ key: String, _ handler: () async throws -> (String, CachePolicy)) async throws -> Entry { + public static func getOrSet(_ key: String, _ handler: () async throws -> (String, CachePolicy)) + async throws -> Entry + { let trx = try await Fastly.Cache.getOrSet(key) { let (text, cachePolicy) = try await handler() return (.bytes(.init(text.utf8)), cachePolicy) @@ -32,7 +38,9 @@ public struct Cache: Sendable { return try .init(trx) } - public static func getOrSet(_ key: String, _ handler: () async throws -> (Data, CachePolicy)) async throws -> Entry { + public static func getOrSet(_ key: String, _ handler: () async throws -> (Data, CachePolicy)) + async throws -> Entry + { let trx = try await Fastly.Cache.getOrSet(key) { let (data, cachePolicy) = try await handler() return (.bytes(data.bytes), cachePolicy) @@ -40,7 +48,9 @@ public struct Cache: Sendable { return try .init(trx) } - public static func getOrSet(_ key: String, _ handler: () async throws -> ([String: Sendable], CachePolicy)) async throws -> Entry { + public static func getOrSet( + _ key: String, _ handler: () async throws -> ([String: Sendable], CachePolicy) + ) async throws -> Entry { let trx = try await Fastly.Cache.getOrSet(key) { let (json, cachePolicy) = try await handler() let data = try JSONSerialization.data(withJSONObject: json) @@ -49,7 +59,9 @@ public struct Cache: Sendable { return try .init(trx) } - public static func getOrSet(_ key: String, _ handler: () async throws -> ([Sendable], CachePolicy)) async throws -> Entry { + public static func getOrSet( + _ key: String, _ handler: () async throws -> ([Sendable], CachePolicy) + ) async throws -> Entry { let trx = try await Fastly.Cache.getOrSet(key) { let (json, cachePolicy) = try await handler() let data = try JSONSerialization.data(withJSONObject: json) diff --git a/Sources/Compute/Concurrency.swift b/Sources/Compute/Concurrency.swift index 81142306..6cc08358 100644 --- a/Sources/Compute/Concurrency.swift +++ b/Sources/Compute/Concurrency.swift @@ -1,6 +1,6 @@ // // Concurrency.swift -// +// // // Created by Andrew Barba on 11/27/22. // @@ -10,7 +10,7 @@ extension Data: @unchecked Sendable {} extension URL: @unchecked Sendable {} #if !arch(wasm32) -extension HTTPURLResponse: @unchecked Sendable {} + extension HTTPURLResponse: @unchecked Sendable {} #endif extension Task where Success == Never, Failure == Never { diff --git a/Sources/Compute/ConfigStore.swift b/Sources/Compute/ConfigStore.swift index 9b027e5f..0cfd69af 100644 --- a/Sources/Compute/ConfigStore.swift +++ b/Sources/Compute/ConfigStore.swift @@ -1,6 +1,6 @@ // // ConfigStore.swift -// +// // // Created by Andrew Barba on 11/27/22. // diff --git a/Sources/Compute/Console.swift b/Sources/Compute/Console.swift index 4e505d8a..64869040 100644 --- a/Sources/Compute/Console.swift +++ b/Sources/Compute/Console.swift @@ -1,6 +1,6 @@ // // Console.swift -// +// // // Created by Andrew Barba on 3/23/22. // @@ -35,7 +35,7 @@ public struct Console: Sendable { } } -fileprivate struct StandardErrorOutputStream: TextOutputStream { +private struct StandardErrorOutputStream: TextOutputStream { private let stderr = FileHandle.standardError diff --git a/Sources/Compute/Crypto.swift b/Sources/Compute/Crypto.swift index 5f8db83a..4c339e2e 100644 --- a/Sources/Compute/Crypto.swift +++ b/Sources/Compute/Crypto.swift @@ -1,6 +1,6 @@ // // Crypto.swift -// +// // // Created by Andrew Barba on 2/8/23. // @@ -13,15 +13,18 @@ public enum Crypto {} extension Crypto { - public static func hash(_ input: String, using hash: T.Type) -> T.Digest where T: HashFunction { + public static func hash(_ input: String, using hash: T.Type) -> T.Digest + where T: HashFunction { return T.hash(data: Data(input.utf8)) } - public static func hash(_ input: [UInt8], using hash: T.Type) -> T.Digest where T: HashFunction { + public static func hash(_ input: [UInt8], using hash: T.Type) -> T.Digest + where T: HashFunction { return T.hash(data: Data(input)) } - public static func hash(_ input: Data, using hash: T.Type) -> T.Digest where T: HashFunction { + public static func hash(_ input: Data, using hash: T.Type) -> T.Digest + where T: HashFunction { return T.hash(data: input) } @@ -92,7 +95,9 @@ extension Crypto { } } - public static func verify(_ input: String, signature: Data, secret: String, using hash: Hash) -> Bool { + public static func verify( + _ input: String, signature: Data, secret: String, using hash: Hash + ) -> Bool { let computed = code(for: input, secret: secret, using: hash) return computed.toHexString() == signature.toHexString() } @@ -109,7 +114,9 @@ extension Crypto { case p521 } - public static func signature(for input: String, secret: String, using algorithm: Algorithm) throws -> Data { + public static func signature(for input: String, secret: String, using algorithm: Algorithm) + throws -> Data + { switch algorithm { case .p256: let pk = try P256.Signing.PrivateKey(pemRepresentation: secret) @@ -123,7 +130,9 @@ extension Crypto { } } - public static func verify(_ input: String, signature: Data, key: String, using algorithm: Algorithm) throws -> Bool { + public static func verify( + _ input: String, signature: Data, key: String, using algorithm: Algorithm + ) throws -> Bool { switch algorithm { case .p256: let publicKey = try P256.Signing.PublicKey(pemRepresentation: key) @@ -154,7 +163,7 @@ extension DataProtocol { } public func toHexString() -> String { - return reduce("") {$0 + String(format: "%02x", $1)} + return reduce("") { $0 + String(format: "%02x", $1) } } } @@ -168,7 +177,7 @@ extension Digest { } public func toHexString() -> String { - return reduce("") {$0 + String(format: "%02x", $1)} + return reduce("") { $0 + String(format: "%02x", $1) } } } @@ -182,7 +191,7 @@ extension HashedAuthenticationCode { } public func toHexString() -> String { - return reduce("") {$0 + String(format: "%02x", $1)} + return reduce("") { $0 + String(format: "%02x", $1) } } } @@ -192,6 +201,6 @@ extension Array where Element == UInt8 { } public func toHexString() -> String { - return reduce("") {$0 + String(format: "%02x", $1)} + return reduce("") { $0 + String(format: "%02x", $1) } } } diff --git a/Sources/Compute/Fanout/FanoutClient.swift b/Sources/Compute/Fanout/FanoutClient.swift index f7360eac..59179211 100644 --- a/Sources/Compute/Fanout/FanoutClient.swift +++ b/Sources/Compute/Fanout/FanoutClient.swift @@ -1,6 +1,6 @@ // // FanoutClient.swift -// +// // // Created by Andrew Barba on 2/1/23. // @@ -19,7 +19,10 @@ public struct FanoutClient: Sendable { "https://\(hostname)/service/\(service)/publish/" } - public init(service: String = Fastly.Environment.serviceId, token: String, hostname: String = "api.fastly.com") { + public init( + service: String = Fastly.Environment.serviceId, token: String, + hostname: String = "api.fastly.com" + ) { self.service = service self.token = token self.hostname = hostname @@ -27,11 +30,13 @@ public struct FanoutClient: Sendable { @discardableResult public func publish(_ message: PublishMessage) async throws -> FetchResponse { - return try await fetch(publishEndpoint, .options( - method: .post, - body: .json(message), - headers: ["Fastly-Key": token] - )) + return try await fetch( + publishEndpoint, + .options( + method: .post, + body: .json(message), + headers: ["Fastly-Key": token] + )) } @discardableResult @@ -43,7 +48,9 @@ public struct FanoutClient: Sendable { } @discardableResult - public func publish(_ value: T, encoder: JSONEncoder = .init(), to channel: String) async throws -> FetchResponse { + public func publish( + _ value: T, encoder: JSONEncoder = .init(), to channel: String + ) async throws -> FetchResponse { let content = try encoder.encode(value) return try await publish(content, to: channel) } @@ -56,7 +63,9 @@ public struct FanoutClient: Sendable { } @discardableResult - public func publish(_ jsonObject: [String: Any], to channel: String) async throws -> FetchResponse { + public func publish(_ jsonObject: [String: Any], to channel: String) async throws + -> FetchResponse + { let data = try JSONSerialization.data(withJSONObject: jsonObject) let content = String(data: data, encoding: .utf8) return try await publish(content, to: channel) diff --git a/Sources/Compute/Fanout/FanoutMessage.swift b/Sources/Compute/Fanout/FanoutMessage.swift index f751c2cf..fb749d3d 100644 --- a/Sources/Compute/Fanout/FanoutMessage.swift +++ b/Sources/Compute/Fanout/FanoutMessage.swift @@ -1,6 +1,6 @@ // // FanoutMessage.swift -// +// // // Created by Andrew Barba on 1/31/23. // diff --git a/Sources/Compute/Fanout/IncomingRequest+Fanout.swift b/Sources/Compute/Fanout/IncomingRequest+Fanout.swift index 6f03ae5d..02e4f64a 100644 --- a/Sources/Compute/Fanout/IncomingRequest+Fanout.swift +++ b/Sources/Compute/Fanout/IncomingRequest+Fanout.swift @@ -1,6 +1,6 @@ // // IncomingRequest+Fanout.swift -// +// // // Created by Andrew Barba on 2/1/23. // @@ -37,14 +37,16 @@ extension IncomingRequest { } public func verifyFanoutRequest() throws { - guard let token = headers[.gripSig] else { - throw FanoutRequestError.invalidSignature - } - let jwt = try JWT(token: token) - try jwt.verify(key: fanoutPublicKey) + guard let token = headers[.gripSig] else { + throw FanoutRequestError.invalidSignature + } + let jwt = try JWT(token: token) + try jwt.verify(key: fanoutPublicKey) } - public func upgradeWebsocket(to destination: UpgradeWebsocketDestination, hostname: String = "localhost") throws { + public func upgradeWebsocket( + to destination: UpgradeWebsocketDestination, hostname: String = "localhost" + ) throws { switch destination { case .proxy: try request.redirectToWebsocketProxy(backend: hostname) diff --git a/Sources/Compute/Fanout/OutgoingResponse+Fanout.swift b/Sources/Compute/Fanout/OutgoingResponse+Fanout.swift index bcaf76bd..a80d26a4 100644 --- a/Sources/Compute/Fanout/OutgoingResponse+Fanout.swift +++ b/Sources/Compute/Fanout/OutgoingResponse+Fanout.swift @@ -1,6 +1,6 @@ // // OutgoingResponse+Fanout.swift -// +// // // Created by Andrew Barba on 2/2/23. // diff --git a/Sources/Compute/Fastly/Fastly.swift b/Sources/Compute/Fastly/Fastly.swift index 2e8d315b..08bd80ac 100644 --- a/Sources/Compute/Fastly/Fastly.swift +++ b/Sources/Compute/Fastly/Fastly.swift @@ -1,6 +1,6 @@ // // Fastly.swift -// +// // // Created by Andrew Barba on 11/27/22. // diff --git a/Sources/Compute/Fastly/FastlyABI.swift b/Sources/Compute/Fastly/FastlyABI.swift index 9c6cf9f5..7c765be5 100644 --- a/Sources/Compute/Fastly/FastlyABI.swift +++ b/Sources/Compute/Fastly/FastlyABI.swift @@ -1,6 +1,6 @@ // // ABI.swift -// +// // // Created by Andrew Barba on 1/12/22. // diff --git a/Sources/Compute/Fastly/FastlyBody.swift b/Sources/Compute/Fastly/FastlyBody.swift index e6015007..042dc8bd 100644 --- a/Sources/Compute/Fastly/FastlyBody.swift +++ b/Sources/Compute/Fastly/FastlyBody.swift @@ -1,6 +1,6 @@ // // Body.swift -// +// // // Created by Andrew Barba on 1/13/22. // @@ -44,7 +44,9 @@ extension Fastly { while position < bytes.count { try bytes[position.. [UInt8] { defer { used = true } - return try Array(unsafeUninitializedCapacity: highWaterMark) { + return try [UInt8](unsafeUninitializedCapacity: highWaterMark) { var length = 0 try wasi(fastly_http_body__read(handle, $0.baseAddress, highWaterMark, &length)) $1 = length } } - public mutating func read(highWaterMark: Int = highWaterMark, onChunk: ([UInt8]) throws -> BodyScanContinuation) throws { + public mutating func read( + highWaterMark: Int = highWaterMark, onChunk: ([UInt8]) throws -> BodyScanContinuation + ) throws { while true { // Read chunk based on appropriate offset let chunk = try scan(highWaterMark: highWaterMark) diff --git a/Sources/Compute/Fastly/FastlyCache.swift b/Sources/Compute/Fastly/FastlyCache.swift index 13d08687..543e4d96 100644 --- a/Sources/Compute/Fastly/FastlyCache.swift +++ b/Sources/Compute/Fastly/FastlyCache.swift @@ -1,6 +1,6 @@ // // FastlyCache.swift -// +// // // Created by Andrew Barba on 9/13/23. // @@ -12,7 +12,9 @@ extension Fastly { public typealias InsertResult = (data: HandlerData, cachePolicy: CachePolicy) - public static func getOrSet(_ key: String, _ handler: () async throws -> InsertResult) async throws -> Transaction { + public static func getOrSet(_ key: String, _ handler: () async throws -> InsertResult) + async throws -> Transaction + { // Open the transaction let trx = try Transaction.lookup(key) @@ -29,7 +31,8 @@ extension Fastly { let (data, cachePolicy) = try await handler() // Get an instance to the insert handle - var writer = try trx.insertAndStreamBack(cachePolicy: cachePolicy, length: data.length) + var writer = try trx.insertAndStreamBack( + cachePolicy: cachePolicy, length: data.length) // Append bytes from handler to writeable body switch data { @@ -83,11 +86,15 @@ extension Fastly.Cache { var handle: WasiHandle = 0 let options = CacheLookupOptions.none var config = CacheLookupConfig() - try wasi(fastly_cache__cache_transaction_lookup(key, key.utf8.count, options.rawValue, &config, &handle)) + try wasi( + fastly_cache__cache_transaction_lookup( + key, key.utf8.count, options.rawValue, &config, &handle)) return Transaction(handle) } - public func insertAndStreamBack(cachePolicy: CachePolicy, length: Int?) throws -> (body: Fastly.Body, transaction: Transaction) { + public func insertAndStreamBack(cachePolicy: CachePolicy, length: Int?) throws -> ( + body: Fastly.Body, transaction: Transaction + ) { var bodyHandle: WasiHandle = 0 var cacheHandle: WasiHandle = 0 var options: CacheWriteOptions = [] @@ -101,7 +108,9 @@ extension Fastly.Cache { options.insert(.length) config.length = .init(length) } - try wasi(fastly_cache__cache_transaction_insert_and_stream_back(handle, options.rawValue, &config, &bodyHandle, &cacheHandle)) + try wasi( + fastly_cache__cache_transaction_insert_and_stream_back( + handle, options.rawValue, &config, &bodyHandle, &cacheHandle)) return (.init(bodyHandle), .init(cacheHandle)) } diff --git a/Sources/Compute/Fastly/FastlyConfigStore.swift b/Sources/Compute/Fastly/FastlyConfigStore.swift index 29442519..581a0bc0 100644 --- a/Sources/Compute/Fastly/FastlyConfigStore.swift +++ b/Sources/Compute/Fastly/FastlyConfigStore.swift @@ -1,6 +1,6 @@ // // Dictionary.swift -// +// // // Created by Andrew Barba on 1/12/22. // diff --git a/Sources/Compute/Fastly/FastlyEnvironment.swift b/Sources/Compute/Fastly/FastlyEnvironment.swift index eb5bbfeb..95db1be5 100644 --- a/Sources/Compute/Fastly/FastlyEnvironment.swift +++ b/Sources/Compute/Fastly/FastlyEnvironment.swift @@ -1,6 +1,6 @@ // // FastlyEnvironment.swift -// +// // // Created by Andrew Barba on 1/12/22. // diff --git a/Sources/Compute/Fastly/FastlyError.swift b/Sources/Compute/Fastly/FastlyError.swift index 56e7cea0..108cd98b 100644 --- a/Sources/Compute/Fastly/FastlyError.swift +++ b/Sources/Compute/Fastly/FastlyError.swift @@ -1,6 +1,6 @@ // // FastlyError.swift -// +// // // Created by Andrew Barba on 1/31/23. // @@ -15,7 +15,9 @@ extension Fastly { fileName.components(separatedBy: "/").last!.components(separatedBy: ".").first! } - internal init(status: WasiStatus, functionName: String = #function, fileName: String = #file) { + internal init( + status: WasiStatus, functionName: String = #function, fileName: String = #file + ) { self.status = status self.functionName = functionName self.fileName = fileName @@ -26,7 +28,8 @@ extension Fastly { extension Fastly.Error: LocalizedError { public var errorDescription: String? { - return "\(structName).\(functionName): \(status._errorDescription) - Fastly error code \(status.rawValue)" + return + "\(structName).\(functionName): \(status._errorDescription) - Fastly error code \(status.rawValue)" } } @@ -39,65 +42,77 @@ extension WasiStatus: LocalizedError { internal var _errorDescription: String { switch self { - case .ok: return - "OK" - - case .unexpected: return - "Generic error value. This means that some unexpected error " + - "occurred during a hostcall." - - case .invalidArgument: return - "Invalid argument." - - case .invalidHandle: return - "Invalid handle. Thrown when a request, response, dictionary, or " + - "body handle is not valid." - - case .bufferLength: return - "Buffer length error. Buffer is too long." - - case .unsupported: return - "Unsupported operation error. This error is thrown " + - "when some operation cannot be performed, because it is " + - "not supported." - - case .badAlignment: return - "Alignment error. This is thrown when a pointer does not point to " + - "a properly aligned slice of memory." - - case .httpInvalid: return - "HTTP parse error. This can be thrown when a method, URI, header, " + - "or status is not valid. This can also be thrown if a message head is " + - "too large." - - case .httpUser: return - "HTTP user error. This is thrown in cases where user code caused " + - "an HTTP error. For example, attempt to send a 1xx response code, or a " + - "request with a non-absolute URI. This can also be caused by an " + - "unexpected header: both `content-length` and `transfer-encoding`, for " + - "example." - - case .httpIncomplete: return - "HTTP incomplete message error. A stream ended unexpectedly." - - case .none: return - "A `None` error. This status code is used to " + - "indicate when an optional value did not exist, as " + - "opposed to an empty value." - - case .httpHeadTooLarge: return - "HTTP head too large error. This error will be thrown when the " + - "message head is too large." - - case .httpInvalidStatus: return - "HTTP invalid status error. This error will be " + - "thrown when the HTTP message contains an invalid " + - "status code." - - case .limitExceeded: return - "Limit exceeded error. This error will be thrown when an attempt " + - "to allocate a resource has exceeded the maximum number of resources " + - "permitted. For example, creating too many response handles." + case .ok: + return + "OK" + + case .unexpected: + return + "Generic error value. This means that some unexpected error " + + "occurred during a hostcall." + + case .invalidArgument: + return + "Invalid argument." + + case .invalidHandle: + return + "Invalid handle. Thrown when a request, response, dictionary, or " + + "body handle is not valid." + + case .bufferLength: + return + "Buffer length error. Buffer is too long." + + case .unsupported: + return + "Unsupported operation error. This error is thrown " + + "when some operation cannot be performed, because it is " + "not supported." + + case .badAlignment: + return + "Alignment error. This is thrown when a pointer does not point to " + + "a properly aligned slice of memory." + + case .httpInvalid: + return + "HTTP parse error. This can be thrown when a method, URI, header, " + + "or status is not valid. This can also be thrown if a message head is " + + "too large." + + case .httpUser: + return + "HTTP user error. This is thrown in cases where user code caused " + + "an HTTP error. For example, attempt to send a 1xx response code, or a " + + "request with a non-absolute URI. This can also be caused by an " + + "unexpected header: both `content-length` and `transfer-encoding`, for " + + "example." + + case .httpIncomplete: + return + "HTTP incomplete message error. A stream ended unexpectedly." + + case .none: + return + "A `None` error. This status code is used to " + + "indicate when an optional value did not exist, as " + + "opposed to an empty value." + + case .httpHeadTooLarge: + return + "HTTP head too large error. This error will be thrown when the " + + "message head is too large." + + case .httpInvalidStatus: + return + "HTTP invalid status error. This error will be " + + "thrown when the HTTP message contains an invalid " + "status code." + + case .limitExceeded: + return + "Limit exceeded error. This error will be thrown when an attempt " + + "to allocate a resource has exceeded the maximum number of resources " + + "permitted. For example, creating too many response handles." } } } diff --git a/Sources/Compute/Fastly/FastlyGeoLocation.swift b/Sources/Compute/Fastly/FastlyGeoLocation.swift index 5551bf95..fa48f3a3 100644 --- a/Sources/Compute/Fastly/FastlyGeoLocation.swift +++ b/Sources/Compute/Fastly/FastlyGeoLocation.swift @@ -1,6 +1,6 @@ // // Geo.swift -// +// // // Created by Andrew Barba on 1/12/22. // @@ -38,10 +38,11 @@ extension Fastly { let bytes = text.components(separatedBy: ".").compactMap { UInt8($0) } return try lookup(ip: bytes) case .v6(let text): - let bytes = text.components(separatedBy: ":").reduce(Array()) { res, octet in + let bytes = text.components(separatedBy: ":").reduce([UInt8]()) { res, octet in let first = octet.prefix(2) let second = octet.suffix(2) - return res + [UInt8(first, radix: 16), UInt8(second, radix: 16)].compactMap { $0 } + return res + + [UInt8(first, radix: 16), UInt8(second, radix: 16)].compactMap { $0 } } return try lookup(ip: bytes) } diff --git a/Sources/Compute/Fastly/FastlyKVStore.swift b/Sources/Compute/Fastly/FastlyKVStore.swift index 0f2f881e..62f26728 100644 --- a/Sources/Compute/Fastly/FastlyKVStore.swift +++ b/Sources/Compute/Fastly/FastlyKVStore.swift @@ -1,6 +1,6 @@ // // Store.swift -// +// // // Created by Andrew Barba on 3/30/22. // diff --git a/Sources/Compute/Fastly/FastlyLogger.swift b/Sources/Compute/Fastly/FastlyLogger.swift index a1c7c04f..3a0d5414 100644 --- a/Sources/Compute/Fastly/FastlyLogger.swift +++ b/Sources/Compute/Fastly/FastlyLogger.swift @@ -1,6 +1,6 @@ // // Logger.swift -// +// // // Created by Andrew Barba on 1/12/22. // diff --git a/Sources/Compute/Fastly/FastlyPendingRequest.swift b/Sources/Compute/Fastly/FastlyPendingRequest.swift index c92d93d3..9ac40be0 100644 --- a/Sources/Compute/Fastly/FastlyPendingRequest.swift +++ b/Sources/Compute/Fastly/FastlyPendingRequest.swift @@ -1,6 +1,6 @@ // // PendingRequest.swift -// +// // // Created by Andrew Barba on 1/14/22. // @@ -30,19 +30,24 @@ extension Fastly { var isDone: UInt32 = 0 var responseHandle: WasiHandle = 0 var bodyHandle: WasiHandle = 0 - try wasi(fastly_http_req__pending_req_poll(handle, &isDone, &responseHandle, &bodyHandle)) + try wasi( + fastly_http_req__pending_req_poll(handle, &isDone, &responseHandle, &bodyHandle)) guard isDone > 0 else { return nil } return (.init(responseHandle), .init(bodyHandle)) } - internal static func select(_ requests: [PendingRequest]) throws -> (index: Int, response: Response, body: Body) { + internal static func select(_ requests: [PendingRequest]) throws -> ( + index: Int, response: Response, body: Body + ) { var handles = requests.map(\.handle) var doneIndex: UInt32 = 0 var responseHandle: WasiHandle = 0 var bodyHandle: WasiHandle = 0 - try wasi(fastly_http_req__pending_req_select(&handles, handles.count, &doneIndex, &responseHandle, &bodyHandle)) + try wasi( + fastly_http_req__pending_req_select( + &handles, handles.count, &doneIndex, &responseHandle, &bodyHandle)) return (.init(doneIndex), .init(responseHandle), .init(bodyHandle)) } } diff --git a/Sources/Compute/Fastly/FastlyRequest.swift b/Sources/Compute/Fastly/FastlyRequest.swift index 04167edc..db71b76d 100644 --- a/Sources/Compute/Fastly/FastlyRequest.swift +++ b/Sources/Compute/Fastly/FastlyRequest.swift @@ -1,6 +1,6 @@ // // Request.swift -// +// // // Created by Andrew Barba on 1/13/22. // @@ -58,7 +58,9 @@ extension Fastly { try wasi(fastly_http_req__auto_decompress_response_set(handle, encodings.rawValue)) } - public mutating func setCachePolicy(_ policy: CachePolicy, surrogateKey: String? = nil) throws { + public mutating func setCachePolicy(_ policy: CachePolicy, surrogateKey: String? = nil) + throws + { var tag: CacheOverrideTag let ttl: UInt32 let swr: UInt32 @@ -72,12 +74,15 @@ extension Fastly { ttl = 0 swr = 0 case .ttl(let seconds, let staleWhileRevalidate, let pciCompliant): - tag = .ttl.union(staleWhileRevalidate > 0 ? .swr : .none).union(pciCompliant ? .pci : .none) + tag = .ttl.union(staleWhileRevalidate > 0 ? .swr : .none).union( + pciCompliant ? .pci : .none) ttl = .init(seconds) swr = .init(staleWhileRevalidate) } if let surrogateKey = surrogateKey { - try wasi(fastly_http_req__cache_override_v2_set(handle, tag.rawValue, ttl, swr, surrogateKey, surrogateKey.utf8.count)) + try wasi( + fastly_http_req__cache_override_v2_set( + handle, tag.rawValue, ttl, swr, surrogateKey, surrogateKey.utf8.count)) } else { try wasi(fastly_http_req__cache_override_set(handle, tag.rawValue, ttl, swr)) } @@ -88,8 +93,10 @@ extension Fastly { var nextCursor: Int64 = 0 var bytes: [UInt8] = [] while true { - let chunk = try Array(unsafeUninitializedCapacity: 1024) { - try wasi(fastly_http_req__header_names_get(handle, $0.baseAddress, 1024, cursor, &nextCursor, &$1)) + let chunk = try [UInt8](unsafeUninitializedCapacity: 1024) { + try wasi( + fastly_http_req__header_names_get( + handle, $0.baseAddress, 1024, cursor, &nextCursor, &$1)) } guard chunk.count > 0 else { break @@ -110,33 +117,47 @@ extension Fastly { } public mutating func insertHeader(_ name: String, _ value: String) throws { - try wasi(fastly_http_req__header_insert(handle, name, name.utf8.count, value, value.utf8.count)) + try wasi( + fastly_http_req__header_insert( + handle, name, name.utf8.count, value, value.utf8.count)) } public mutating func appendHeader(_ name: String, _ value: String) throws { - try wasi(fastly_http_req__header_append(handle, name, name.utf8.count, value, value.utf8.count)) + try wasi( + fastly_http_req__header_append( + handle, name, name.utf8.count, value, value.utf8.count)) } public mutating func removeHeader(_ name: String) throws { try wasi(fastly_http_req__header_remove(handle, name, name.utf8.count)) } - public mutating func send(_ body: Body, backend: String) throws -> (response: Response, body: Body) { + public mutating func send(_ body: Body, backend: String) throws -> ( + response: Response, body: Body + ) { var responseHandle: WasiHandle = 0 var bodyHandle: WasiHandle = 0 - try wasi(fastly_http_req__send(handle, body.handle, backend, backend.utf8.count, &responseHandle, &bodyHandle)) + try wasi( + fastly_http_req__send( + handle, body.handle, backend, backend.utf8.count, &responseHandle, &bodyHandle)) return (.init(responseHandle), .init(bodyHandle)) } public mutating func sendAsync(_ body: Body, backend: String) throws -> PendingRequest { var pendingRequestHandle: WasiHandle = 0 - try wasi(fastly_http_req__send_async(handle, body.handle, backend, backend.utf8.count, &pendingRequestHandle)) + try wasi( + fastly_http_req__send_async( + handle, body.handle, backend, backend.utf8.count, &pendingRequestHandle)) return .init(pendingRequestHandle, request: self) } - public mutating func sendAsyncStreaming(_ body: Body, backend: String) throws -> PendingRequest { + public mutating func sendAsyncStreaming(_ body: Body, backend: String) throws + -> PendingRequest + { var pendingRequestHandle: WasiHandle = 0 - try wasi(fastly_http_req__send_async_streaming(handle, body.handle, backend, backend.utf8.count, &pendingRequestHandle)) + try wasi( + fastly_http_req__send_async_streaming( + handle, body.handle, backend, backend.utf8.count, &pendingRequestHandle)) return .init(pendingRequestHandle, request: self) } @@ -185,7 +206,9 @@ extension Fastly.Request { } } - public func registerDynamicBackend(name: String, target: String, options: DynamicBackendOptions = .init()) throws { + public func registerDynamicBackend( + name: String, target: String, options: DynamicBackendOptions = .init() + ) throws { var mask: BackendConfigOptions = [] var config = DynamicBackendConfig() @@ -233,14 +256,15 @@ extension Fastly.Request { config.sni_hostname_len = target.utf8.count } - try wasi(fastly_http_req__register_dynamic_backend( - name, - name.utf8.count, - target, - target.utf8.count, - mask.rawValue, - &config - )) + try wasi( + fastly_http_req__register_dynamic_backend( + name, + name.utf8.count, + target, + target.utf8.count, + mask.rawValue, + &config + )) } } } @@ -267,8 +291,10 @@ extension Fastly.Request { var nextCursor: Int64 = 0 var bytes: [UInt8] = [] while true { - let chunk = try Array(unsafeUninitializedCapacity: 1024) { - try wasi(fastly_http_req__original_header_names_get($0.baseAddress, 1024, cursor, &nextCursor, &$1)) + let chunk = try [UInt8](unsafeUninitializedCapacity: 1024) { + try wasi( + fastly_http_req__original_header_names_get( + $0.baseAddress, 1024, cursor, &nextCursor, &$1)) } guard chunk.count > 0 else { break diff --git a/Sources/Compute/Fastly/FastlyResponse.swift b/Sources/Compute/Fastly/FastlyResponse.swift index cb552697..d885d50f 100644 --- a/Sources/Compute/Fastly/FastlyResponse.swift +++ b/Sources/Compute/Fastly/FastlyResponse.swift @@ -1,6 +1,6 @@ // // Response.swift -// +// // // Created by Andrew Barba on 1/13/22. // @@ -43,7 +43,8 @@ extension Fastly { } public mutating func send(_ body: Body, streaming: Bool = false) throws { - try wasi(fastly_http_resp__send_downstream(handle, body.handle, Int32(streaming ? 1 : 0))) + try wasi( + fastly_http_resp__send_downstream(handle, body.handle, Int32(streaming ? 1 : 0))) } public func getHeaderNames() throws -> [String] { @@ -51,8 +52,10 @@ extension Fastly { var nextCursor: Int64 = 0 var bytes: [UInt8] = [] while true { - let chunk = try Array(unsafeUninitializedCapacity: 1024) { - try wasi(fastly_http_resp__header_names_get(handle, $0.baseAddress, 1024, cursor, &nextCursor, &$1)) + let chunk = try [UInt8](unsafeUninitializedCapacity: 1024) { + try wasi( + fastly_http_resp__header_names_get( + handle, $0.baseAddress, 1024, cursor, &nextCursor, &$1)) } guard chunk.count > 0 else { break @@ -73,11 +76,15 @@ extension Fastly { } public mutating func insertHeader(_ name: String, _ value: String) throws { - try wasi(fastly_http_resp__header_insert(handle, name, name.utf8.count, value, value.utf8.count)) + try wasi( + fastly_http_resp__header_insert( + handle, name, name.utf8.count, value, value.utf8.count)) } public mutating func appendHeader(_ name: String, _ value: String) throws { - try wasi(fastly_http_resp__header_append(handle, name, name.utf8.count, value, value.utf8.count)) + try wasi( + fastly_http_resp__header_append( + handle, name, name.utf8.count, value, value.utf8.count)) } public mutating func removeHeader(_ name: String) throws { diff --git a/Sources/Compute/Fastly/FastlySecretStore.swift b/Sources/Compute/Fastly/FastlySecretStore.swift index b5b8749e..a279c3f8 100644 --- a/Sources/Compute/Fastly/FastlySecretStore.swift +++ b/Sources/Compute/Fastly/FastlySecretStore.swift @@ -1,6 +1,6 @@ // // FastlySecretStore.swift -// +// // // Created by Andrew Barba on 12/2/22. // diff --git a/Sources/Compute/Fastly/FastlyStubs.swift b/Sources/Compute/Fastly/FastlyStubs.swift index 7082fe26..85b72965 100644 --- a/Sources/Compute/Fastly/FastlyStubs.swift +++ b/Sources/Compute/Fastly/FastlyStubs.swift @@ -1,6 +1,6 @@ // // Stubs.swift -// +// // // Created by Andrew Barba on 2/2/22. // @@ -11,209 +11,357 @@ /// avoid link failure. /// When running with Compute runtime library, they are ignored completely. #if !arch(wasm32) -import ComputeRuntime - -/* FASTLY_ABI */ - -func fastly_abi__init(_ abi_version: UInt64) -> Int32 { fatalError() } - -/* FASTLY_DICTIONARY */ - -func fastly_dictionary__open(_ name: UnsafePointer!, _ name_len: Int, _ handle: UnsafeMutablePointer!) -> Int32 { fatalError() } - -func fastly_dictionary__get(_ handle: WasiHandle, _ key: UnsafePointer!, _ key_len: Int, _ value: UnsafeMutablePointer!, _ value_max_len: Int, _ nwritten: UnsafeMutablePointer!) -> Int32 { fatalError() } - -/* FASTLY_LOG */ - -func fastly_log__endpoint_get(_ name: UnsafePointer!, _ name_len: Int, _ handle: UnsafeMutablePointer!) -> Int32 { fatalError() } - -func fastly_log__write(_ handle: WasiHandle, _ msg: UnsafePointer!, _ msg_len: Int, _ nwritten: UnsafeMutablePointer!) -> Int32 { fatalError() } - -/* FASTLY_GEO */ - -func fastly_geo__lookup(_ ip: UnsafePointer!, _ ip_len: Int, _ value: UnsafeMutablePointer!, _ value_max_len: Int, _ nwritten: UnsafeMutablePointer!) -> Int32 { fatalError() } - -/* FASTLY_OBJECT_STORE */ - -func fastly_object_store__open(_ name: UnsafePointer!, _ name_len: Int, _ handle: UnsafeMutablePointer!) -> Int32 { fatalError() } - -func fastly_object_store__lookup(_ handle: WasiHandle, _ key: UnsafePointer!, _ key_len: Int, _ body_handle: UnsafeMutablePointer!) -> Int32 { fatalError() } - -func fastly_object_store__insert(_ handle: WasiHandle, _ key: UnsafePointer!, _ key_len: Int, _ body_handle: UInt32) -> Int32 { fatalError() } - -/* FASTLY_SECRET_STORE */ - -func fastly_secret_store__open(_ name: UnsafePointer!, _ name_len: Int, _ handle: UnsafeMutablePointer!) -> Int32 { fatalError() } - -func fastly_secret_store__lookup(_ handle: WasiHandle, _ key: UnsafePointer!, _ key_len: Int, _ secret_handle: UnsafeMutablePointer!) -> Int32 { fatalError() } - -func fastly_secret_store__plaintext(_ secret_handle: WasiHandle, _ value: UnsafeMutablePointer!, _ value_max_len: Int, _ nwritten: UnsafeMutablePointer!) -> Int32 { fatalError() } - -/* FASTLY_HTTP_BODY */ - -func fastly_http_body__new(_ handle: UnsafeMutablePointer!) -> Int32 { fatalError() } - -func fastly_http_body__append(_ dest: WasiHandle, _ src: WasiHandle) -> Int32 { fatalError() } - -func fastly_http_body__close(_ handle: WasiHandle) -> Int32 { fatalError() } - -func fastly_http_body__abandon(_ handle: WasiHandle) -> Int32 { fatalError() } - -func fastly_http_body__write(_ handle: WasiHandle, _ data: UnsafePointer!, _ data_len: Int, _ body_end: Int32, _ nwritten: UnsafeMutablePointer!) -> Int32 { fatalError() } - -func fastly_http_body__read(_ handle: WasiHandle, _ data: UnsafeMutablePointer!, _ data_max_len: Int, _ nwritten: UnsafeMutablePointer!) -> Int32 { fatalError() } - -/* FASTLY_HTTP_REQ */ - -func fastly_http_req__new(_ handle: UnsafeMutablePointer!) -> Int32 { fatalError() } - -func fastly_http_req__body_downstream_get(_ req: UnsafeMutablePointer!, _ body: UnsafeMutablePointer!) -> Int32 { fatalError() } - -func fastly_http_req__cache_override_set(_ req_handle: WasiHandle, _ tag: UInt32, _ ttl: UInt32, _ stale_while_revalidate: UInt32) -> Int32 { fatalError() } - -func fastly_http_req__cache_override_v2_set(_ req_handle: WasiHandle, _ tag: UInt32, _ ttl: UInt32, _ stale_while_revalidate: UInt32, _ surrogate_key: UnsafePointer!, _ surrogate_key_len: Int) -> Int32 { fatalError() } - -func fastly_http_req__close(_ handle: WasiHandle) -> Int32 { fatalError() } - -func fastly_http_req__method_get(_ handle: WasiHandle, _ value: UnsafeMutablePointer!, _ value_max_len: Int, _ nwritten: UnsafeMutablePointer!) -> Int32 { fatalError() } - -func fastly_http_req__uri_get(_ handle: WasiHandle, _ value: UnsafeMutablePointer!, _ value_max_len: Int, _ nwritten: UnsafeMutablePointer!) -> Int32 { fatalError() } - -func fastly_http_req__version_get(_ handle: WasiHandle, _ version: UnsafeMutablePointer!) -> Int32 { fatalError() } - -func fastly_http_req__method_set(_ handle: WasiHandle, _ method: UnsafePointer!, _ method_len: Int) -> Int32 { fatalError() } - -func fastly_http_req__uri_set(_ handle: WasiHandle, _ uri: UnsafePointer!, _ uri_len: Int) -> Int32 { fatalError() } - -func fastly_http_req__version_set(_ handle: WasiHandle, _ version: Int32) -> Int32 { fatalError() } - -func fastly_http_req__downstream_client_ip_addr(_ octets: UnsafeMutablePointer!, _ nwritten: UnsafeMutablePointer!) -> Int32 { fatalError() } - -func fastly_http_req__header_names_get(_ req_handle: WasiHandle, _ name: UnsafeMutablePointer!, _ name_len: Int, _ cursor: UInt32, _ ending_cursor: UnsafeMutablePointer!, _ nwritten: UnsafeMutablePointer!) -> Int32 { fatalError() } - -func fastly_http_req__original_header_names_get(_ buf: UnsafeMutablePointer!, _ buf_len: Int, _ cursor: UInt32, _ ending_cursor: UnsafeMutablePointer!, _ nwritten: UnsafeMutablePointer!) -> Int32 { fatalError() } - -func fastly_http_req__original_header_count(_ count: UnsafeMutablePointer!) -> Int32 { fatalError() } - -func fastly_http_req__header_value_get(_ resp_handle: WasiHandle, _ name: UnsafePointer!, _ name_len: Int, _ value: UnsafeMutablePointer!, _ value_max_len: Int, _ nwritten: UnsafeMutablePointer!) -> Int32 { fatalError() } - -func fastly_http_req__header_insert(_ resp_handle: WasiHandle, _ name: UnsafePointer!, _ name_len: Int, _ value: UnsafePointer!, _ value_len: Int) -> Int32 { fatalError() } - -func fastly_http_req__header_append(_ resp_handle: WasiHandle, _ name: UnsafePointer!, _ name_len: Int, _ value: UnsafePointer!, _ value_len: Int) -> Int32 { fatalError() } - -func fastly_http_req__header_remove(_ resp_handle: WasiHandle, _ name: UnsafePointer!, _ name_len: Int) -> Int32 { fatalError() } - -func fastly_http_req__send(_ req_handle: WasiHandle, _ body_handle: WasiHandle, _ backend: UnsafePointer!, _ backend_len: Int, _ resp_handle_out: UnsafeMutablePointer!, _ resp_body_handle_out: UnsafeMutablePointer!) -> Int32 { fatalError() } - -func fastly_http_req__send_async(_ req_handle: WasiHandle, _ body_handle: WasiHandle, _ backend: UnsafePointer!, _ backend_len: Int, _ pending_req_out: UnsafeMutablePointer!) -> Int32 { fatalError() } - -func fastly_http_req__send_async_streaming(_ req_handle: WasiHandle, _ body_handle: WasiHandle, _ backend: UnsafePointer!, _ backend_len: Int, _ pending_req_out: UnsafeMutablePointer!) -> Int32 { fatalError() } - -func fastly_http_req__pending_req_poll(_ req_handle: WasiHandle, _ is_done_out: UnsafeMutablePointer!, _ resp_handle_out: UnsafeMutablePointer!, _ resp_body_handle_out: UnsafeMutablePointer!) -> Int32 { fatalError() } - -func fastly_http_req__pending_req_wait(_ req_handle: WasiHandle, _ resp_handle_out: UnsafeMutablePointer!, _ resp_body_handle_out: UnsafeMutablePointer!) -> Int32 { fatalError() } + import ComputeRuntime -func fastly_http_req__pending_req_select(_ req_handles: UnsafeMutablePointer!, _ req_handles_len: Int, _ done_idx_out: UnsafeMutablePointer!, _ resp_handle_out: UnsafeMutablePointer!, _ resp_body_handle_out: UnsafeMutablePointer!) -> Int32 { fatalError() } + /* FASTLY_ABI */ -func fastly_http_req__auto_decompress_response_set(_ req_handle: WasiHandle, _ encodings: UInt32) -> Int32 { fatalError() } + func fastly_abi__init(_ abi_version: UInt64) -> Int32 { fatalError() } -func fastly_http_req__framing_headers_mode_set(_ req_handle: WasiHandle, _ mode: UInt32) -> Int32 { fatalError() } + /* FASTLY_DICTIONARY */ -func fastly_http_req__redirect_to_websocket_proxy(_ backend: UnsafePointer!, _ backend_len: Int) -> Int32 { fatalError() } + func fastly_dictionary__open( + _ name: UnsafePointer!, _ name_len: Int, _ handle: UnsafeMutablePointer! + ) -> Int32 { fatalError() } -func fastly_http_req__redirect_to_grip_proxy(_ backend: UnsafePointer!, _ backend_len: Int) -> Int32 { fatalError() } + func fastly_dictionary__get( + _ handle: WasiHandle, _ key: UnsafePointer!, _ key_len: Int, + _ value: UnsafeMutablePointer!, _ value_max_len: Int, + _ nwritten: UnsafeMutablePointer! + ) -> Int32 { fatalError() } -func fastly_http_req__register_dynamic_backend(_ name: UnsafePointer!, _ name_len: Int, _ target: UnsafePointer!, _ target_len: Int, _ backend_config_mask: UInt32, _ backend_configuration: UnsafeMutablePointer!) -> Int32 { fatalError() } + /* FASTLY_LOG */ -func fastly_http_req__downstream_tls_ja3_md5(_ value: UnsafeMutablePointer!, _ nwritten: UnsafeMutablePointer!) -> Int32 { fatalError() } + func fastly_log__endpoint_get( + _ name: UnsafePointer!, _ name_len: Int, _ handle: UnsafeMutablePointer! + ) -> Int32 { fatalError() } -func fastly_http_req__downstream_tls_ja4( - _ value: UnsafeMutablePointer!, - _ max_len: Int, - _ nwritten_out: UnsafeMutablePointer! -) -> Int32 { fatalError() } + func fastly_log__write( + _ handle: WasiHandle, _ msg: UnsafePointer!, _ msg_len: Int, + _ nwritten: UnsafeMutablePointer! + ) -> Int32 { fatalError() } -/* FASTLY_HTTP_RESP */ + /* FASTLY_GEO */ -func fastly_http_resp__new(_ handle: UnsafeMutablePointer!) -> Int32 { fatalError() } + func fastly_geo__lookup( + _ ip: UnsafePointer!, _ ip_len: Int, _ value: UnsafeMutablePointer!, + _ value_max_len: Int, _ nwritten: UnsafeMutablePointer! + ) -> Int32 { fatalError() } -func fastly_http_resp__close(_ handle: WasiHandle) -> Int32 { fatalError() } + /* FASTLY_OBJECT_STORE */ -func fastly_http_resp__send_downstream(_ resp_handle: WasiHandle, _ body_handle: WasiHandle, _ streaming: Int32) -> Int32 { fatalError() } + func fastly_object_store__open( + _ name: UnsafePointer!, _ name_len: Int, _ handle: UnsafeMutablePointer! + ) -> Int32 { fatalError() } -func fastly_http_resp__version_get(_ handle: WasiHandle, _ version: UnsafeMutablePointer!) -> Int32 { fatalError() } + func fastly_object_store__lookup( + _ handle: WasiHandle, _ key: UnsafePointer!, _ key_len: Int, + _ body_handle: UnsafeMutablePointer! + ) -> Int32 { fatalError() } -func fastly_http_resp__status_get(_ handle: WasiHandle, _ status: UnsafeMutablePointer!) -> Int32 { fatalError() } + func fastly_object_store__insert( + _ handle: WasiHandle, _ key: UnsafePointer!, _ key_len: Int, _ body_handle: UInt32 + ) -> Int32 { fatalError() } -func fastly_http_resp__version_set(_ handle: WasiHandle, _ version: Int32) -> Int32 { fatalError() } + /* FASTLY_SECRET_STORE */ -func fastly_http_resp__status_set(_ handle: WasiHandle, _ status: Int32) -> Int32 { fatalError() } + func fastly_secret_store__open( + _ name: UnsafePointer!, _ name_len: Int, _ handle: UnsafeMutablePointer! + ) -> Int32 { fatalError() } -func fastly_http_resp__header_names_get(_ resp_handle: WasiHandle, _ name: UnsafeMutablePointer!, _ name_len: Int, _ cursor: UInt32, _ ending_cursor: UnsafeMutablePointer!, _ nwritten: UnsafeMutablePointer!) -> Int32 { fatalError() } + func fastly_secret_store__lookup( + _ handle: WasiHandle, _ key: UnsafePointer!, _ key_len: Int, + _ secret_handle: UnsafeMutablePointer! + ) -> Int32 { fatalError() } -func fastly_http_resp__header_value_get(_ resp_handle: WasiHandle, _ name: UnsafePointer!, _ name_len: Int, _ value: UnsafeMutablePointer!, _ value_max_len: Int, _ nwritten: UnsafeMutablePointer!) -> Int32 { fatalError() } + func fastly_secret_store__plaintext( + _ secret_handle: WasiHandle, _ value: UnsafeMutablePointer!, _ value_max_len: Int, + _ nwritten: UnsafeMutablePointer! + ) -> Int32 { fatalError() } -func fastly_http_resp__header_insert(_ resp_handle: WasiHandle, _ name: UnsafePointer!, _ name_len: Int, _ value: UnsafePointer!, _ value_len: Int) -> Int32 { fatalError() } + /* FASTLY_HTTP_BODY */ -func fastly_http_resp__header_append(_ resp_handle: WasiHandle, _ name: UnsafePointer!, _ name_len: Int, _ value: UnsafePointer!, _ value_len: Int) -> Int32 { fatalError() } + func fastly_http_body__new(_ handle: UnsafeMutablePointer!) -> Int32 { + fatalError() + } -func fastly_http_resp__header_remove(_ resp_handle: WasiHandle, _ name: UnsafePointer!, _ name_len: Int) -> Int32 { fatalError() } + func fastly_http_body__append(_ dest: WasiHandle, _ src: WasiHandle) -> Int32 { fatalError() } -func fastly_http_resp__framing_headers_mode_set(_ resp_handle: WasiHandle, _ mode: UInt32) -> Int32 { fatalError() } + func fastly_http_body__close(_ handle: WasiHandle) -> Int32 { fatalError() } -func fastly_http_resp__http_keepalive_mode_set(_ resp_handle: WasiHandle, _ mode: UInt32) -> Int32 { fatalError() } + func fastly_http_body__abandon(_ handle: WasiHandle) -> Int32 { fatalError() } -func fastly_cache__cache_transaction_lookup( - _ cache_key: UnsafePointer!, - _ cache_key_len: Int, - _ options_mask: UInt32, - _ config: UnsafeMutablePointer!, - _ ret: UnsafeMutablePointer! -) -> Int32 { fatalError() } + func fastly_http_body__write( + _ handle: WasiHandle, _ data: UnsafePointer!, _ data_len: Int, _ body_end: Int32, + _ nwritten: UnsafeMutablePointer! + ) -> Int32 { fatalError() } -func fastly_cache__cache_transaction_insert_and_stream_back( - _ handle: WasiHandle, - _ options_mask: UInt32, - _ config: UnsafeMutablePointer!, - _ ret_body: UnsafeMutablePointer!, - _ ret_cache: UnsafeMutablePointer! -) -> Int32 { fatalError() } + func fastly_http_body__read( + _ handle: WasiHandle, _ data: UnsafeMutablePointer!, _ data_max_len: Int, + _ nwritten: UnsafeMutablePointer! + ) -> Int32 { fatalError() } -func fastly_cache__cache_get_state( - _ handle: WasiHandle, - _ ret: UnsafeMutablePointer! -) -> Int32 { fatalError() } + /* FASTLY_HTTP_REQ */ -func fastly_cache__cache_get_age_ns( - _ handle: WasiHandle, - _ ret: UnsafeMutablePointer! -) -> Int32 { fatalError() } + func fastly_http_req__new(_ handle: UnsafeMutablePointer!) -> Int32 { fatalError() } -func fastly_cache__cache_get_length( - _ handle: WasiHandle, - _ ret: UnsafeMutablePointer! -) -> Int32 { fatalError() } + func fastly_http_req__body_downstream_get( + _ req: UnsafeMutablePointer!, _ body: UnsafeMutablePointer! + ) -> Int32 { fatalError() } -func fastly_cache__cache_get_hits( - _ handle: WasiHandle, - _ ret: UnsafeMutablePointer! -) -> Int32{ fatalError() } + func fastly_http_req__cache_override_set( + _ req_handle: WasiHandle, _ tag: UInt32, _ ttl: UInt32, _ stale_while_revalidate: UInt32 + ) -> Int32 { fatalError() } -func fastly_cache__cache_get_body( - _ handle: WasiHandle, - _ options_mask: UInt32, - _ config: UnsafeMutablePointer!, - _ ret: UnsafeMutablePointer! -) -> Int32 { fatalError() } + func fastly_http_req__cache_override_v2_set( + _ req_handle: WasiHandle, _ tag: UInt32, _ ttl: UInt32, _ stale_while_revalidate: UInt32, + _ surrogate_key: UnsafePointer!, _ surrogate_key_len: Int + ) -> Int32 { fatalError() } -func fastly_cache__cache_transaction_cancel(_ handle: WasiHandle) -> Int32 { fatalError() } + func fastly_http_req__close(_ handle: WasiHandle) -> Int32 { fatalError() } + + func fastly_http_req__method_get( + _ handle: WasiHandle, _ value: UnsafeMutablePointer!, _ value_max_len: Int, + _ nwritten: UnsafeMutablePointer! + ) -> Int32 { fatalError() } + + func fastly_http_req__uri_get( + _ handle: WasiHandle, _ value: UnsafeMutablePointer!, _ value_max_len: Int, + _ nwritten: UnsafeMutablePointer! + ) -> Int32 { fatalError() } -func fastly_device__device_detection_lookup( - _ user_agent: UnsafePointer!, - _ user_agent_len: Int, - _ buf: UnsafeMutablePointer!, - _ buf_len: Int, - _ nwritten: UnsafeMutablePointer! -) -> Int32 { fatalError() } + func fastly_http_req__version_get(_ handle: WasiHandle, _ version: UnsafeMutablePointer!) + -> Int32 + { fatalError() } + + func fastly_http_req__method_set( + _ handle: WasiHandle, _ method: UnsafePointer!, _ method_len: Int + ) -> Int32 { fatalError() } + + func fastly_http_req__uri_set( + _ handle: WasiHandle, _ uri: UnsafePointer!, _ uri_len: Int + ) -> Int32 { fatalError() } + + func fastly_http_req__version_set(_ handle: WasiHandle, _ version: Int32) -> Int32 { + fatalError() + } + + func fastly_http_req__downstream_client_ip_addr( + _ octets: UnsafeMutablePointer!, _ nwritten: UnsafeMutablePointer! + ) -> Int32 { fatalError() } + + func fastly_http_req__header_names_get( + _ req_handle: WasiHandle, _ name: UnsafeMutablePointer!, _ name_len: Int, + _ cursor: UInt32, _ ending_cursor: UnsafeMutablePointer!, + _ nwritten: UnsafeMutablePointer! + ) -> Int32 { fatalError() } + + func fastly_http_req__original_header_names_get( + _ buf: UnsafeMutablePointer!, _ buf_len: Int, _ cursor: UInt32, + _ ending_cursor: UnsafeMutablePointer!, _ nwritten: UnsafeMutablePointer! + ) -> Int32 { fatalError() } + + func fastly_http_req__original_header_count(_ count: UnsafeMutablePointer!) -> Int32 + { fatalError() } + + func fastly_http_req__header_value_get( + _ resp_handle: WasiHandle, _ name: UnsafePointer!, _ name_len: Int, + _ value: UnsafeMutablePointer!, _ value_max_len: Int, + _ nwritten: UnsafeMutablePointer! + ) -> Int32 { fatalError() } + + func fastly_http_req__header_insert( + _ resp_handle: WasiHandle, _ name: UnsafePointer!, _ name_len: Int, + _ value: UnsafePointer!, _ value_len: Int + ) -> Int32 { fatalError() } + + func fastly_http_req__header_append( + _ resp_handle: WasiHandle, _ name: UnsafePointer!, _ name_len: Int, + _ value: UnsafePointer!, _ value_len: Int + ) -> Int32 { fatalError() } + + func fastly_http_req__header_remove( + _ resp_handle: WasiHandle, _ name: UnsafePointer!, _ name_len: Int + ) -> Int32 { fatalError() } + + func fastly_http_req__send( + _ req_handle: WasiHandle, _ body_handle: WasiHandle, _ backend: UnsafePointer!, + _ backend_len: Int, _ resp_handle_out: UnsafeMutablePointer!, + _ resp_body_handle_out: UnsafeMutablePointer! + ) -> Int32 { fatalError() } + + func fastly_http_req__send_async( + _ req_handle: WasiHandle, _ body_handle: WasiHandle, _ backend: UnsafePointer!, + _ backend_len: Int, _ pending_req_out: UnsafeMutablePointer! + ) -> Int32 { fatalError() } + + func fastly_http_req__send_async_streaming( + _ req_handle: WasiHandle, _ body_handle: WasiHandle, _ backend: UnsafePointer!, + _ backend_len: Int, _ pending_req_out: UnsafeMutablePointer! + ) -> Int32 { fatalError() } + + func fastly_http_req__pending_req_poll( + _ req_handle: WasiHandle, _ is_done_out: UnsafeMutablePointer!, + _ resp_handle_out: UnsafeMutablePointer!, + _ resp_body_handle_out: UnsafeMutablePointer! + ) -> Int32 { fatalError() } + + func fastly_http_req__pending_req_wait( + _ req_handle: WasiHandle, _ resp_handle_out: UnsafeMutablePointer!, + _ resp_body_handle_out: UnsafeMutablePointer! + ) -> Int32 { fatalError() } + + func fastly_http_req__pending_req_select( + _ req_handles: UnsafeMutablePointer!, _ req_handles_len: Int, + _ done_idx_out: UnsafeMutablePointer!, + _ resp_handle_out: UnsafeMutablePointer!, + _ resp_body_handle_out: UnsafeMutablePointer! + ) -> Int32 { fatalError() } + + func fastly_http_req__auto_decompress_response_set( + _ req_handle: WasiHandle, _ encodings: UInt32 + ) -> Int32 { fatalError() } + + func fastly_http_req__framing_headers_mode_set(_ req_handle: WasiHandle, _ mode: UInt32) + -> Int32 + { fatalError() } + + func fastly_http_req__redirect_to_websocket_proxy( + _ backend: UnsafePointer!, _ backend_len: Int + ) -> Int32 { fatalError() } + + func fastly_http_req__redirect_to_grip_proxy( + _ backend: UnsafePointer!, _ backend_len: Int + ) -> Int32 { fatalError() } + + func fastly_http_req__register_dynamic_backend( + _ name: UnsafePointer!, _ name_len: Int, _ target: UnsafePointer!, + _ target_len: Int, _ backend_config_mask: UInt32, + _ backend_configuration: UnsafeMutablePointer! + ) -> Int32 { fatalError() } + + func fastly_http_req__downstream_tls_ja3_md5( + _ value: UnsafeMutablePointer!, _ nwritten: UnsafeMutablePointer! + ) -> Int32 { fatalError() } + + func fastly_http_req__downstream_tls_ja4( + _ value: UnsafeMutablePointer!, + _ max_len: Int, + _ nwritten_out: UnsafeMutablePointer! + ) -> Int32 { fatalError() } + + /* FASTLY_HTTP_RESP */ + + func fastly_http_resp__new(_ handle: UnsafeMutablePointer!) -> Int32 { + fatalError() + } + + func fastly_http_resp__close(_ handle: WasiHandle) -> Int32 { fatalError() } + + func fastly_http_resp__send_downstream( + _ resp_handle: WasiHandle, _ body_handle: WasiHandle, _ streaming: Int32 + ) -> Int32 { fatalError() } + + func fastly_http_resp__version_get( + _ handle: WasiHandle, _ version: UnsafeMutablePointer! + ) -> Int32 { fatalError() } + + func fastly_http_resp__status_get(_ handle: WasiHandle, _ status: UnsafeMutablePointer!) + -> Int32 + { fatalError() } + + func fastly_http_resp__version_set(_ handle: WasiHandle, _ version: Int32) -> Int32 { + fatalError() + } + + func fastly_http_resp__status_set(_ handle: WasiHandle, _ status: Int32) -> Int32 { + fatalError() + } + + func fastly_http_resp__header_names_get( + _ resp_handle: WasiHandle, _ name: UnsafeMutablePointer!, _ name_len: Int, + _ cursor: UInt32, _ ending_cursor: UnsafeMutablePointer!, + _ nwritten: UnsafeMutablePointer! + ) -> Int32 { fatalError() } + + func fastly_http_resp__header_value_get( + _ resp_handle: WasiHandle, _ name: UnsafePointer!, _ name_len: Int, + _ value: UnsafeMutablePointer!, _ value_max_len: Int, + _ nwritten: UnsafeMutablePointer! + ) -> Int32 { fatalError() } + + func fastly_http_resp__header_insert( + _ resp_handle: WasiHandle, _ name: UnsafePointer!, _ name_len: Int, + _ value: UnsafePointer!, _ value_len: Int + ) -> Int32 { fatalError() } + + func fastly_http_resp__header_append( + _ resp_handle: WasiHandle, _ name: UnsafePointer!, _ name_len: Int, + _ value: UnsafePointer!, _ value_len: Int + ) -> Int32 { fatalError() } + + func fastly_http_resp__header_remove( + _ resp_handle: WasiHandle, _ name: UnsafePointer!, _ name_len: Int + ) -> Int32 { fatalError() } + + func fastly_http_resp__framing_headers_mode_set(_ resp_handle: WasiHandle, _ mode: UInt32) + -> Int32 + { fatalError() } + + func fastly_http_resp__http_keepalive_mode_set(_ resp_handle: WasiHandle, _ mode: UInt32) + -> Int32 + { fatalError() } + + func fastly_cache__cache_transaction_lookup( + _ cache_key: UnsafePointer!, + _ cache_key_len: Int, + _ options_mask: UInt32, + _ config: UnsafeMutablePointer!, + _ ret: UnsafeMutablePointer! + ) -> Int32 { fatalError() } + + func fastly_cache__cache_transaction_insert_and_stream_back( + _ handle: WasiHandle, + _ options_mask: UInt32, + _ config: UnsafeMutablePointer!, + _ ret_body: UnsafeMutablePointer!, + _ ret_cache: UnsafeMutablePointer! + ) -> Int32 { fatalError() } + + func fastly_cache__cache_get_state( + _ handle: WasiHandle, + _ ret: UnsafeMutablePointer! + ) -> Int32 { fatalError() } + + func fastly_cache__cache_get_age_ns( + _ handle: WasiHandle, + _ ret: UnsafeMutablePointer! + ) -> Int32 { fatalError() } + + func fastly_cache__cache_get_length( + _ handle: WasiHandle, + _ ret: UnsafeMutablePointer! + ) -> Int32 { fatalError() } + + func fastly_cache__cache_get_hits( + _ handle: WasiHandle, + _ ret: UnsafeMutablePointer! + ) -> Int32 { fatalError() } + + func fastly_cache__cache_get_body( + _ handle: WasiHandle, + _ options_mask: UInt32, + _ config: UnsafeMutablePointer!, + _ ret: UnsafeMutablePointer! + ) -> Int32 { fatalError() } + + func fastly_cache__cache_transaction_cancel(_ handle: WasiHandle) -> Int32 { fatalError() } + + func fastly_device__device_detection_lookup( + _ user_agent: UnsafePointer!, + _ user_agent_len: Int, + _ buf: UnsafeMutablePointer!, + _ buf_len: Int, + _ nwritten: UnsafeMutablePointer! + ) -> Int32 { fatalError() } #endif diff --git a/Sources/Compute/Fastly/FastlyTypes.swift b/Sources/Compute/Fastly/FastlyTypes.swift index 24c9bd0d..63676c09 100644 --- a/Sources/Compute/Fastly/FastlyTypes.swift +++ b/Sources/Compute/Fastly/FastlyTypes.swift @@ -1,6 +1,6 @@ // // Types.swift -// +// // // Created by Andrew Barba on 1/12/22. // @@ -86,7 +86,7 @@ public enum HTTPVersion: Int32, Codable, Sendable { return "0.9" case .http1_0: return "1.0" - case.http1_1: + case .http1_1: return "1.1" case .h2: return "2" diff --git a/Sources/Compute/Fastly/FastlyUtils.swift b/Sources/Compute/Fastly/FastlyUtils.swift index be528c48..49056699 100644 --- a/Sources/Compute/Fastly/FastlyUtils.swift +++ b/Sources/Compute/Fastly/FastlyUtils.swift @@ -1,13 +1,15 @@ // // Utils.swift -// +// // // Created by Andrew Barba on 1/12/22. // -import CoreFoundation +import Foundation -internal typealias WasiBufferReader = (_ buffer: UnsafeMutablePointer?, _ maxLength: Int, _ length: inout Int) -> Int32 +internal typealias WasiBufferReader = ( + _ buffer: UnsafeMutablePointer?, _ maxLength: Int, _ length: inout Int +) -> Int32 internal func wasi( _ handler: @autoclosure () -> Int32, @@ -30,7 +32,9 @@ internal func wasiString( fileName: String = #file ) throws -> String? { do { - let bytes = try wasiBytes(maxBufferLength: maxBufferLength, handler: handler, functionName: functionName, fileName: fileName) + let bytes = try wasiBytes( + maxBufferLength: maxBufferLength, handler: handler, functionName: functionName, + fileName: fileName) return String(bytes: bytes, encoding: .utf8) } catch WasiStatus.none, WasiStatus.invalidArgument { return nil @@ -46,7 +50,9 @@ internal func wasiDecode( functionName: String = #function, fileName: String = #file ) throws -> T where T: Decodable { - let bytes = try wasiBytes(maxBufferLength: maxBufferLength, handler: handler, functionName: functionName, fileName: fileName) + let bytes = try wasiBytes( + maxBufferLength: maxBufferLength, handler: handler, functionName: functionName, + fileName: fileName) return try decoder.decode(T.self, from: Data(bytes)) } @@ -56,15 +62,17 @@ internal func wasiBytes( functionName: String = #function, fileName: String = #file ) throws -> [UInt8] { - return try Array(unsafeUninitializedCapacity: maxBufferLength) { + return try [UInt8](unsafeUninitializedCapacity: maxBufferLength) { var length = 0 - try wasi(handler($0.baseAddress, maxBufferLength, &length), functionName: functionName, fileName: fileName) + try wasi( + handler($0.baseAddress, maxBufferLength, &length), functionName: functionName, + fileName: fileName) $1 = length } } internal struct Utils { - + internal static let jsonDecoder: JSONDecoder = { let decoder = JSONDecoder() decoder.keyDecodingStrategy = .convertFromSnakeCase @@ -76,7 +84,7 @@ extension Array { internal func chunked(into size: Int) -> [[Element]] { return stride(from: 0, to: count, by: size).map { - Array(self[$0 ..< Swift.min($0 + size, count)]) + Array(self[$0.. FetchResponse { - // Build url components from request url - guard var urlComponents = URLComponents(string: request.url.absoluteString) else { - throw FetchRequestError.invalidURL + enum URLSessionFetchError: Error, Sendable { + case invalidResponse } - // Set default scheme - urlComponents.scheme = urlComponents.scheme ?? "http" + static func fetch(_ request: FetchRequest) async throws -> FetchResponse { + // Build url components from request url + guard var urlComponents = URLComponents(string: request.url.absoluteString) else { + throw FetchRequestError.invalidURL + } - // Set default host - urlComponents.host = urlComponents.host ?? "localhost" + // Set default scheme + urlComponents.scheme = urlComponents.scheme ?? "http" - // Build search params - for (key, value) in request.searchParams { - var queryItems = urlComponents.queryItems ?? [] - queryItems.append(.init(name: key, value: value)) - urlComponents.queryItems = queryItems - } + // Set default host + urlComponents.host = urlComponents.host ?? "localhost" - // Parse final url - guard let url = urlComponents.url else { - throw FetchRequestError.invalidURL - } + // Build search params + for (key, value) in request.searchParams { + var queryItems = urlComponents.queryItems ?? [] + queryItems.append(.init(name: key, value: value)) + urlComponents.queryItems = queryItems + } - // Set request resources - var httpRequest = URLRequest(url: url) + // Parse final url + guard let url = urlComponents.url else { + throw FetchRequestError.invalidURL + } - // Set request method - httpRequest.httpMethod = request.method.rawValue + // Set request resources + var httpRequest = URLRequest(url: url) - // Set the timeout interval - if let timeoutInterval = request.timeoutInterval { - httpRequest.timeoutInterval = timeoutInterval - } + // Set request method + httpRequest.httpMethod = request.method.rawValue - // Set content encodings - if let encoding = request.acceptEncoding { - httpRequest.setValue(encoding.stringValue, forHTTPHeaderField: HTTPHeader.acceptEncoding.rawValue) - } + // Set the timeout interval + if let timeoutInterval = request.timeoutInterval { + httpRequest.timeoutInterval = timeoutInterval + } - // Set default content type based on body - if let contentType = request.body?.defaultContentType { - let name = HTTPHeader.contentType.rawValue - httpRequest.setValue(request.headers[name] ?? contentType, forHTTPHeaderField: name) - } + // Set content encodings + if let encoding = request.acceptEncoding { + httpRequest.setValue( + encoding.stringValue, forHTTPHeaderField: HTTPHeader.acceptEncoding.rawValue) + } - // Set headers - for (key, value) in request.headers { - httpRequest.setValue(value, forHTTPHeaderField: key) - } + // Set default content type based on body + if let contentType = request.body?.defaultContentType { + let name = HTTPHeader.contentType.rawValue + httpRequest.setValue(request.headers[name] ?? contentType, forHTTPHeaderField: name) + } - // Write bytes to body - switch request.body { - case .bytes(let bytes): - httpRequest.httpBody = Data(bytes) - case .data(let data): - httpRequest.httpBody = data - case .text(let text): - httpRequest.httpBody = Data(text.utf8) - case .json(let json): - httpRequest.httpBody = json - case .stream(let body): - let data = try await body.data() - httpRequest.httpBodyStream = .init(data: data) - case .none: - break - } + // Set headers + for (key, value) in request.headers { + httpRequest.setValue(value, forHTTPHeaderField: key) + } - let (data, response): (Data, HTTPURLResponse) = try await withCheckedThrowingContinuation { continuation in - let task = URLSession.shared.dataTask(with: httpRequest) { data, response, error in - if let data, let response = response as? HTTPURLResponse { - continuation.resume(returning: (data, response)) - } else { - continuation.resume(throwing: error ?? URLSessionFetchError.invalidResponse) - } + // Write bytes to body + switch request.body { + case .bytes(let bytes): + httpRequest.httpBody = Data(bytes) + case .data(let data): + httpRequest.httpBody = data + case .text(let text): + httpRequest.httpBody = Data(text.utf8) + case .json(let json): + httpRequest.httpBody = json + case .stream(let body): + let data = try await body.data() + httpRequest.httpBodyStream = .init(data: data) + case .none: + break } - task.resume() - } - return FetchResponse( - body: ReadableDataBody(data), - headers: Headers(response.allHeaderFields as! HTTPHeaders), - status: response.statusCode, - url: url - ) + let (data, response): (Data, HTTPURLResponse) = + try await withCheckedThrowingContinuation { continuation in + let task = URLSession.shared.dataTask(with: httpRequest) { + data, response, error in + if let data, let response = response as? HTTPURLResponse { + continuation.resume(returning: (data, response)) + } else { + continuation.resume( + throwing: error ?? URLSessionFetchError.invalidResponse) + } + } + task.resume() + } + + return FetchResponse( + body: ReadableDataBody(data), + headers: Headers(response.allHeaderFields as! HTTPHeaders), + status: response.statusCode, + url: url + ) + } } -} #endif diff --git a/Sources/Compute/Fetch/Fetch+Wasi.swift b/Sources/Compute/Fetch/Fetch+Wasi.swift index e10e64df..3a4efa2c 100644 --- a/Sources/Compute/Fetch/Fetch+Wasi.swift +++ b/Sources/Compute/Fetch/Fetch+Wasi.swift @@ -1,6 +1,6 @@ // // Fetch.swift -// +// // // Created by Andrew Barba on 1/15/22. // @@ -84,16 +84,19 @@ internal struct WasiFetcher: Sendable { // Register the backend if Fastly.Environment.viceroy, request.backend != "localhost" { - try await dynamicBackends.register(request.backend, for: httpRequest, ssl: urlComponents.scheme == "https") + try await dynamicBackends.register( + request.backend, for: httpRequest, ssl: urlComponents.scheme == "https") } // Issue async request let pendingRequest: Fastly.PendingRequest if let streamingBody = streamingBody { - pendingRequest = try await httpRequest.sendAsyncStreaming(writableBody.body, backend: request.backend) + pendingRequest = try await httpRequest.sendAsyncStreaming( + writableBody.body, backend: request.backend) try await streamingBody.pipeTo(writableBody) } else { - pendingRequest = try await httpRequest.sendAsync(writableBody.body, backend: request.backend) + pendingRequest = try await httpRequest.sendAsync( + writableBody.body, backend: request.backend) } // Store the time we started sending request @@ -114,7 +117,9 @@ internal struct WasiFetcher: Sendable { } // Check for a timeout - if let timeoutInterval = request.timeoutInterval, Date().timeIntervalSince1970 - startTime > timeoutInterval { + if let timeoutInterval = request.timeoutInterval, + Date().timeIntervalSince1970 - startTime > timeoutInterval + { throw FetchRequestError.timeout } } @@ -137,7 +142,8 @@ extension WasiFetcher { // Attempt to register the backend do { - try request.registerDynamicBackend(name: backend, target: backend, options: .init(ssl: ssl)) + try request.registerDynamicBackend( + name: backend, target: backend, options: .init(ssl: ssl)) } catch WasiStatus.unexpected { // ignore } catch { diff --git a/Sources/Compute/Fetch/Fetch.swift b/Sources/Compute/Fetch/Fetch.swift index 07ab64c7..843fcc44 100644 --- a/Sources/Compute/Fetch/Fetch.swift +++ b/Sources/Compute/Fetch/Fetch.swift @@ -1,24 +1,28 @@ // // Fetch.swift -// +// // // Created by Andrew Barba on 12/5/22. // public func fetch(_ request: FetchRequest) async throws -> FetchResponse { #if !arch(wasm32) - return try await URLSessionFetcher.fetch(request) + return try await URLSessionFetcher.fetch(request) #else - return try await WasiFetcher.fetch(request) + return try await WasiFetcher.fetch(request) #endif } -public func fetch(_ url: URL, _ options: FetchRequest.Options = .options()) async throws -> FetchResponse { +public func fetch(_ url: URL, _ options: FetchRequest.Options = .options()) async throws + -> FetchResponse +{ let request = FetchRequest(url, options) return try await fetch(request) } -public func fetch(_ urlPath: String, _ options: FetchRequest.Options = .options()) async throws -> FetchResponse { +public func fetch(_ urlPath: String, _ options: FetchRequest.Options = .options()) async throws + -> FetchResponse +{ guard let url = URL(string: urlPath) else { throw FetchRequestError.invalidURL } @@ -26,7 +30,7 @@ public func fetch(_ urlPath: String, _ options: FetchRequest.Options = .options( return try await fetch(request) } -public func fetch ( +public func fetch( _ request: IncomingRequest, origin: String, streaming: Bool = true, @@ -81,14 +85,16 @@ public func fetch ( headers[HTTPHeader.xForwardedFor.rawValue] = request.clientIpAddress().stringValue } - return try await fetch(url, .options( - method: options.method ?? request.method, - body: body, - headers: headers, - searchParams: options.searchParams ?? request.searchParams, - timeoutInterval: options.timeoutInterval, - cachePolicy: options.cachePolicy, - surrogateKey: options.surrogateKey, - backend: options.backend - )) + return try await fetch( + url, + .options( + method: options.method ?? request.method, + body: body, + headers: headers, + searchParams: options.searchParams ?? request.searchParams, + timeoutInterval: options.timeoutInterval, + cachePolicy: options.cachePolicy, + surrogateKey: options.surrogateKey, + backend: options.backend + )) } diff --git a/Sources/Compute/Fetch/FetchRequest.swift b/Sources/Compute/Fetch/FetchRequest.swift index 8049d1c0..422460b2 100644 --- a/Sources/Compute/Fetch/FetchRequest.swift +++ b/Sources/Compute/Fetch/FetchRequest.swift @@ -1,6 +1,6 @@ // // FetchRequest.swift -// +// // // Created by Andrew Barba on 1/14/22. // @@ -110,7 +110,8 @@ extension FetchRequest { case json(_ json: Data) case stream(_ body: ReadableBody) - public static func json(_ value: T, encoder: JSONEncoder = .init()) throws -> Body where T: Encodable { + public static func json(_ value: T, encoder: JSONEncoder = .init()) throws -> Body + where T: Encodable { let data = try encoder.encode(value) return Body.json(data) } diff --git a/Sources/Compute/Fetch/FetchResponse.swift b/Sources/Compute/Fetch/FetchResponse.swift index c44c72c0..3b79bf34 100644 --- a/Sources/Compute/Fetch/FetchResponse.swift +++ b/Sources/Compute/Fetch/FetchResponse.swift @@ -1,6 +1,6 @@ // // FetchResponse.swift -// +// // // Created by Andrew Barba on 12/5/22. // @@ -31,11 +31,13 @@ extension FetchResponse { extension FetchResponse { - public func decode(decoder: JSONDecoder = .init()) async throws -> T where T: Decodable & Sendable { + public func decode(decoder: JSONDecoder = .init()) async throws -> T + where T: Decodable & Sendable { return try await body.decode(decoder: decoder) } - public func decode(_ type: T.Type, decoder: JSONDecoder = .init()) async throws -> T where T: Decodable & Sendable { + public func decode(_ type: T.Type, decoder: JSONDecoder = .init()) async throws -> T + where T: Decodable & Sendable { return try await body.decode(type, decoder: decoder) } diff --git a/Sources/Compute/Headers.swift b/Sources/Compute/Headers.swift index 4c607d12..54b976a6 100644 --- a/Sources/Compute/Headers.swift +++ b/Sources/Compute/Headers.swift @@ -1,6 +1,6 @@ // // Headers.swift -// +// // // Created by Andrew Barba on 1/16/22. // diff --git a/Sources/Compute/IncomingRequest.swift b/Sources/Compute/IncomingRequest.swift index 3f160ff0..500f1804 100644 --- a/Sources/Compute/IncomingRequest.swift +++ b/Sources/Compute/IncomingRequest.swift @@ -1,6 +1,6 @@ // // IncomingRequest.swift -// +// // // Created by Andrew Barba on 1/13/22. // @@ -39,7 +39,8 @@ public struct IncomingRequest: Sendable { self.url = url self.method = try request.getMethod() ?? .get self.httpVersion = try request.getHTTPVersion() ?? .http1_1 - self.searchParams = URLComponents(string: url.absoluteString)? + self.searchParams = + URLComponents(string: url.absoluteString)? .queryItems? .reduce(into: [:]) { $0[$1.name] = $1.value } ?? [:] } diff --git a/Sources/Compute/JWT/JWT.swift b/Sources/Compute/JWT/JWT.swift index 9045aff3..c11ab4ad 100644 --- a/Sources/Compute/JWT/JWT.swift +++ b/Sources/Compute/JWT/JWT.swift @@ -1,6 +1,6 @@ // // JWT.swift -// +// // // Created by Andrew Barba on 11/27/22. // @@ -65,7 +65,7 @@ public struct JWT: Sendable { ) throws { let header: [String: Sendable] = [ "alg": algorithm.rawValue, - "typ": "JWT" + "typ": "JWT", ] var properties: [String: Sendable] = [ @@ -160,7 +160,8 @@ extension JWT { let input = token.components(separatedBy: ".").prefix(2).joined(separator: ".") // Ensure the signatures match - try verifySignature(input, signature: signature, key: key, using: algorithm ?? self.algorithm) + try verifySignature( + input, signature: signature, key: key, using: algorithm ?? self.algorithm) // Ensure the jwt is not expired if expiration, self.expired == true { @@ -205,7 +206,9 @@ private func encodeJWTPart(_ value: [String: Any]) throws -> String { return try base64UrlEncode(data) } -private func hmacSignature(_ input: String, secret: String, using algorithm: JWT.Algorithm) throws -> Data { +private func hmacSignature(_ input: String, secret: String, using algorithm: JWT.Algorithm) throws + -> Data +{ switch algorithm { case .hs256: return Crypto.Auth.code(for: input, secret: secret, using: .sha256) @@ -222,7 +225,9 @@ private func hmacSignature(_ input: String, secret: String, using algorithm: JWT } } -private func verifySignature(_ input: String, signature: Data, key: String, using algorithm: JWT.Algorithm) throws { +private func verifySignature( + _ input: String, signature: Data, key: String, using algorithm: JWT.Algorithm +) throws { let verified: Bool switch algorithm { case .es256: @@ -244,7 +249,8 @@ private func verifySignature(_ input: String, signature: Data, key: String, usin } private func base64UrlDecode(_ value: String) throws -> Data { - var base64 = value + var base64 = + value .replacingOccurrences(of: "-", with: "+") .replacingOccurrences(of: "_", with: "/") let length = Double(base64.lengthOfBytes(using: String.Encoding.utf8)) @@ -261,7 +267,8 @@ private func base64UrlDecode(_ value: String) throws -> Data { } private func base64UrlEncode(_ value: Data) throws -> String { - return value + return + value .base64EncodedString() .trimmingCharacters(in: ["="]) .replacingOccurrences(of: "+", with: "-") diff --git a/Sources/Compute/JWT/JWTClaim.swift b/Sources/Compute/JWT/JWTClaim.swift index 24506af6..02b31afd 100644 --- a/Sources/Compute/JWT/JWTClaim.swift +++ b/Sources/Compute/JWT/JWTClaim.swift @@ -1,6 +1,6 @@ // // JWTClaim.swift -// +// // // Created by Andrew Barba on 2/6/23. // diff --git a/Sources/Compute/JWT/JWTError.swift b/Sources/Compute/JWT/JWTError.swift index 18da95a8..13620dc6 100644 --- a/Sources/Compute/JWT/JWTError.swift +++ b/Sources/Compute/JWT/JWTError.swift @@ -1,6 +1,6 @@ // // JWTError.swift -// +// // // Created by Andrew Barba on 2/6/23. // diff --git a/Sources/Compute/KVStore.swift b/Sources/Compute/KVStore.swift index 382dc7ba..95116797 100644 --- a/Sources/Compute/KVStore.swift +++ b/Sources/Compute/KVStore.swift @@ -1,6 +1,6 @@ // // KVStore.swift -// +// // // Created by Andrew Barba on 3/31/22. // @@ -80,9 +80,9 @@ extension KVStore { try await put(key, data: data) } - public func put(_ key: String, value: T, encoder: JSONEncoder = .init()) async throws where T: Encodable { + public func put(_ key: String, value: T, encoder: JSONEncoder = .init()) async throws + where T: Encodable { let data = try encoder.encode(value) try await put(key, data: data) } } - diff --git a/Sources/Compute/Range.swift b/Sources/Compute/Range.swift index 0b51f5b9..75ca3956 100644 --- a/Sources/Compute/Range.swift +++ b/Sources/Compute/Range.swift @@ -1,6 +1,6 @@ // // Range.swift -// +// // // Created by Andrew Barba on 1/18/22. // @@ -37,7 +37,9 @@ public struct Range: Sendable { public init?(from value: String) { // Split on equals to get [, -] - let valueParts = value.components(separatedBy: "=").map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } + let valueParts = value.components(separatedBy: "=").map { + $0.trimmingCharacters(in: .whitespacesAndNewlines) + } // Ensure only two parts guard valueParts.count == 2 else { @@ -48,13 +50,17 @@ public struct Range: Sendable { let unit = valueParts[0] // Parse intervals parts to get [-, ...] - let intervalsParts = valueParts[1].components(separatedBy: ",").map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } + let intervalsParts = valueParts[1].components(separatedBy: ",").map { + $0.trimmingCharacters(in: .whitespacesAndNewlines) + } // Map over intervals parts to create intervals let intervals = intervalsParts.compactMap { part -> RangeInterval? in // Split part on - to get [, ] - let intervalParts = part.components(separatedBy: "-").map { $0.trimmingCharacters(in: .whitespacesAndNewlines) } + let intervalParts = part.components(separatedBy: "-").map { + $0.trimmingCharacters(in: .whitespacesAndNewlines) + } // Ensure exactly two parts guard intervalParts.count == 2 else { diff --git a/Sources/Compute/ReadableBody/ReadableBody+Data.swift b/Sources/Compute/ReadableBody/ReadableBody+Data.swift index 430c23fc..bcf6d12d 100644 --- a/Sources/Compute/ReadableBody/ReadableBody+Data.swift +++ b/Sources/Compute/ReadableBody/ReadableBody+Data.swift @@ -1,73 +1,74 @@ // // ReadableBody+Data.swift -// +// // // Created by Andrew Barba on 12/5/22. // #if !arch(wasm32) -internal actor ReadableDataBody: ReadableBody { + internal actor ReadableDataBody: ReadableBody { - var used: Bool { - return true - } + var used: Bool { + return true + } - var data: Data + var data: Data - var body: Fastly.Body + var body: Fastly.Body - init(_ data: Data) { - self.data = data - self.body = .init(InvalidWasiHandle) - } + init(_ data: Data) { + self.data = data + self.body = .init(InvalidWasiHandle) + } - func close() async throws {} -} + func close() async throws {} + } -extension ReadableDataBody { + extension ReadableDataBody { - func pipeTo(_ dest: WritableBody, preventClose: Bool) async throws { - try await dest.write(data) + func pipeTo(_ dest: WritableBody, preventClose: Bool) async throws { + try await dest.write(data) + } } -} -extension ReadableDataBody { + extension ReadableDataBody { - func decode(_ type: T.Type, decoder: JSONDecoder = .init()) async throws -> T where T: Decodable & Sendable { - return try decoder.decode(type, from: data) - } + func decode(_ type: T.Type, decoder: JSONDecoder = .init()) async throws -> T + where T: Decodable & Sendable { + return try decoder.decode(type, from: data) + } - func json() async throws -> T { - return try JSONSerialization.jsonObject(with: data) as! T - } + func json() async throws -> T { + return try JSONSerialization.jsonObject(with: data) as! T + } - func jsonObject() async throws -> [String : Sendable] { - return try await json() - } + func jsonObject() async throws -> [String: Sendable] { + return try await json() + } - func jsonArray() async throws -> [Sendable] { - return try await json() - } + func jsonArray() async throws -> [Sendable] { + return try await json() + } - func formValues() async throws -> HTTPSearchParams { - let query = try await text() - let components = URLComponents(string: "?\(query)") - let queryItems = components?.queryItems ?? [] - return queryItems.reduce(into: [:]) { values, item in - values[item.name] = item.value + func formValues() async throws -> HTTPSearchParams { + let query = try await text() + let components = URLComponents(string: "?\(query)") + let queryItems = components?.queryItems ?? [] + return queryItems.reduce(into: [:]) { values, item in + values[item.name] = item.value + } } - } - func text() async throws -> String { - return String(data: data, encoding: .utf8)! - } + func text() async throws -> String { + return String(data: data, encoding: .utf8)! + } - func data() async throws -> Data { - return data - } + func data() async throws -> Data { + return data + } - func bytes() async throws -> [UInt8] { - return data.bytes + func bytes() async throws -> [UInt8] { + return data.bytes + } } -} #endif diff --git a/Sources/Compute/ReadableBody/ReadableBody+Wasi.swift b/Sources/Compute/ReadableBody/ReadableBody+Wasi.swift index 9fcd437f..023a4172 100644 --- a/Sources/Compute/ReadableBody/ReadableBody+Wasi.swift +++ b/Sources/Compute/ReadableBody/ReadableBody+Wasi.swift @@ -44,7 +44,8 @@ extension ReadableWasiBody { extension ReadableWasiBody { - func decode(_ type: T.Type, decoder: JSONDecoder = .init()) async throws -> T where T: Decodable { + func decode(_ type: T.Type, decoder: JSONDecoder = .init()) async throws -> T + where T: Decodable { let data = try await data() return try decoder.decode(type, from: data) } diff --git a/Sources/Compute/ReadableBody/ReadableBody.swift b/Sources/Compute/ReadableBody/ReadableBody.swift index d53b880a..911baaa1 100644 --- a/Sources/Compute/ReadableBody/ReadableBody.swift +++ b/Sources/Compute/ReadableBody/ReadableBody.swift @@ -1,6 +1,6 @@ // // ReadableBody.swift -// +// // // Created by Andrew Barba on 12/5/22. // diff --git a/Sources/Compute/Router/Parameters.swift b/Sources/Compute/Router/Parameters.swift index cfd82bd1..219cefeb 100644 --- a/Sources/Compute/Router/Parameters.swift +++ b/Sources/Compute/Router/Parameters.swift @@ -60,7 +60,7 @@ public struct Parameters: Sendable { public func get(_ name: String) -> String? { self.values[name] } - + /// Grabs the named parameter from the parameter bag, casting it to /// a `LosslessStringConvertible` type. /// @@ -71,11 +71,10 @@ public struct Parameters: Sendable { /// let commentID = parameters.get("comment_id", as: Int.self) /// public func get(_ name: String, as type: T.Type = T.self) -> T? - where T: LosslessStringConvertible - { + where T: LosslessStringConvertible { self.get(name).flatMap(T.init) } - + /// Adds a new parameter value to the bag. /// /// - note: The value will be percent-decoded. @@ -86,7 +85,7 @@ public struct Parameters: Sendable { public mutating func set(_ name: String, to value: String?) { self.values[name] = value?.removingPercentEncoding } - + /// Fetches the components matched by `catchall` (`**`). /// /// If the route doen't hit `catchall`, it'll return `[]`. @@ -108,7 +107,7 @@ public struct Parameters: Sendable { } return self.catchall.values } - + /// Stores the components matched by `catchall` (`**`). /// /// - parameters: @@ -116,7 +115,7 @@ public struct Parameters: Sendable { public mutating func setCatchall(matched: [String]) { self.catchall = Catchall(values: matched) } - + /// Holds path components that were matched by `catchall` (`**`). /// /// Used internally. diff --git a/Sources/Compute/Router/PathComponent.swift b/Sources/Compute/Router/PathComponent.swift index 29c07d1e..832c8a2e 100644 --- a/Sources/Compute/Router/PathComponent.swift +++ b/Sources/Compute/Router/PathComponent.swift @@ -18,12 +18,12 @@ public enum PathComponent: ExpressibleByStringInterpolation, CustomStringConvert /// /// Represented as `:` followed by the identifier. case parameter(String) - + /// A dynamic parameter component with discarded value. /// /// Represented as `*` case anything - + /// A fallback component that will match one *or more* dynamic /// parameter components with discarded values. /// @@ -47,7 +47,7 @@ public enum PathComponent: ExpressibleByStringInterpolation, CustomStringConvert self = .constant(value) } } - + /// `CustomStringConvertible` conformance. public var description: String { switch self { diff --git a/Sources/Compute/Router/Routable.swift b/Sources/Compute/Router/Routable.swift index 4893ec8f..8d32d4a3 100644 --- a/Sources/Compute/Router/Routable.swift +++ b/Sources/Compute/Router/Routable.swift @@ -11,7 +11,7 @@ protocol Routable { /// Type of value stored in routes. This will be returned by the router. associatedtype Output - + /// Registers a new `Output` to the `Router` at a given path. /// /// - parameters: @@ -19,7 +19,7 @@ protocol Routable { /// - path: Path to register output at. /// mutating func register(_ output: Output, at path: [PathComponent]) - + /// Fetches output for a specific route. /// /// `PathComponent.parameter` values will be stored in the supplied `Parameters` diff --git a/Sources/Compute/Router/TrieRouter.swift b/Sources/Compute/Router/TrieRouter.swift index 778e89cf..29c03816 100644 --- a/Sources/Compute/Router/TrieRouter.swift +++ b/Sources/Compute/Router/TrieRouter.swift @@ -18,7 +18,7 @@ final class TrieRouter: Routable, CustomStringConvertible { /// - note: Case-insensitive routing may be less performant than case-sensitive routing. case caseInsensitive } - + /// Configured options such as case-sensitivity. var options: Set @@ -51,7 +51,9 @@ final class TrieRouter: Routable, CustomStringConvertible { for (index, component) in path.enumerated() { switch component { case .catchall: - precondition(index == path.count - 1, "Catchall ('\(component)') must be the last component in a path.") + precondition( + index == path.count - 1, + "Catchall ('\(component)') must be the last component in a path.") fallthrough default: current = current.buildOrFetchChild(for: component, options: self.options) @@ -62,7 +64,7 @@ final class TrieRouter: Routable, CustomStringConvertible { if current.output != nil { print("[Routing] Warning: Overriding route output at: \(path.string)") } - + // after iterating over all path components, we can set the output // on the current node current.output = output @@ -80,7 +82,7 @@ final class TrieRouter: Routable, CustomStringConvertible { func route(path: [String], parameters: inout Parameters) -> Output? { // always start at the root node var currentNode: Node = self.root - + let isCaseInsensitive = self.options.contains(.caseInsensitive) var currentCatchall: (Node, [String])? @@ -93,7 +95,8 @@ final class TrieRouter: Routable, CustomStringConvertible { } // check the constants first - if let constant = currentNode.constants[isCaseInsensitive ? slice.lowercased() : slice] { + if let constant = currentNode.constants[isCaseInsensitive ? slice.lowercased() : slice] + { currentNode = constant continue search } @@ -131,7 +134,7 @@ final class TrieRouter: Routable, CustomStringConvertible { return nil } } - + var description: String { return self.root.description } @@ -180,36 +183,38 @@ extension TrieRouter { /// Wildcard child node that may be a named parameter or an anything var wildcard: Wildcard? - + /// Catchall node, if one exists. /// This node should not have any child nodes. var catchall: Node? - + /// This node's output var output: Output? - + /// Creates a new `RouterNode`. init(output: Output? = nil) { self.output = output self.constants = [String: Node]() } - + /// Fetches the child `RouterNode` for the supplied path component, or builds /// a new segment onto the tree if necessary. - func buildOrFetchChild(for component: PathComponent, options: Set) -> Node { + func buildOrFetchChild(for component: PathComponent, options: Set) + -> Node + { let isCaseInsensitive = options.contains(.caseInsensitive) - + switch component { case .constant(let string): // We're going to be comparing this path against an incoming losercased path later // so it's more efficient to lowercase it up front let string = isCaseInsensitive ? string.lowercased() : string - + // search for existing constant if let node = self.constants[string] { return node } - + // none found, add a new node let node = Node() self.constants[string] = node @@ -219,7 +224,10 @@ extension TrieRouter { if let wildcard = self.wildcard { if let existingName = self.wildcard?.parameter { - precondition(existingName == name, "It is not possible to have two routes with the same prefix but different parameter names, even if the trailing path components differ (tried to add route with \(name) that collides with \(existingName)).") + precondition( + existingName == name, + "It is not possible to have two routes with the same prefix but different parameter names, even if the trailing path components differ (tried to add route with \(name) that collides with \(existingName))." + ) } else { wildcard.setParameterName(name) } @@ -250,11 +258,11 @@ extension TrieRouter { return node } } - + var description: String { self.subpathDescriptions.joined(separator: "\n") } - + var subpathDescriptions: [String] { var desc: [String] = [] for (name, constant) in self.constants { @@ -274,7 +282,7 @@ extension TrieRouter { } } - if let _ = self.catchall { + if self.catchall != nil { desc.append("→ **") } return desc @@ -282,8 +290,8 @@ extension TrieRouter { } } -private extension Array where Element == String { - func indented() -> [String] { +extension Array where Element == String { + fileprivate func indented() -> [String] { return self.map { " " + $0 } } } diff --git a/Sources/Compute/SecretStore.swift b/Sources/Compute/SecretStore.swift index 1074a374..d9c100bc 100644 --- a/Sources/Compute/SecretStore.swift +++ b/Sources/Compute/SecretStore.swift @@ -1,6 +1,6 @@ // // SecretStore.swift -// +// // // Created by Andrew Barba on 12/2/22. // diff --git a/Tests/ComputeTests/FetchTests.swift b/Tests/ComputeTests/FetchTests.swift index da2ec017..b3c8fdbc 100644 --- a/Tests/ComputeTests/FetchTests.swift +++ b/Tests/ComputeTests/FetchTests.swift @@ -1,11 +1,12 @@ // // FetchTests.swift -// +// // // Created by Andrew Barba on 11/27/22. // import XCTest + @testable import Compute final class FetchTests: XCTestCase { diff --git a/Tests/ComputeTests/JWTTests.swift b/Tests/ComputeTests/JWTTests.swift index 786c1c44..ad066fd9 100644 --- a/Tests/ComputeTests/JWTTests.swift +++ b/Tests/ComputeTests/JWTTests.swift @@ -1,11 +1,12 @@ // // JWTTests.swift -// +// // // Created by Andrew Barba on 11/27/22. // import XCTest + @testable import Compute private let token = @@ -56,7 +57,7 @@ final class JWTTests: XCTestCase { let jwt = try JWT( claims: ["name": "John Doe"], secret: "your-256-bit-secret", - issuedAt: Date(timeIntervalSince1970: 1669591611), + issuedAt: Date(timeIntervalSince1970: 1_669_591_611), subject: "1234567890" ) XCTAssertEqual(jwt.token, token) diff --git a/fastly.toml b/fastly.toml deleted file mode 100644 index 7f077f94..00000000 --- a/fastly.toml +++ /dev/null @@ -1,2 +0,0 @@ -language = "swift" -manifest_version = 2