diff --git a/FlyingFox/Sources/HTTPClient.swift b/FlyingFox/Sources/HTTPClient.swift new file mode 100644 index 0000000..b7687df --- /dev/null +++ b/FlyingFox/Sources/HTTPClient.swift @@ -0,0 +1,63 @@ +// +// HTTPClient.swift +// FlyingFox +// +// Created by Simon Whitty on 8/06/2024. +// Copyright © 2024 Simon Whitty. All rights reserved. +// +// Distributed under the permissive MIT license +// Get the latest version from here: +// +// https://github.com/swhitty/FlyingFox +// +// 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. +// + +import FlyingSocks + +@_spi(Private) +public struct _HTTPClient { + + public func sendHTTPRequest(_ request: HTTPRequest, to address: some SocketAddress) async throws -> HTTPResponse { + let socket = try await AsyncSocket.connected(to: address) + try await socket.writeRequest(request) + let response = try await socket.readResponse() + try? socket.close() + return response + } +} + +@_spi(Private) +public extension AsyncSocket { + func writeRequest(_ request: HTTPRequest) async throws { + try await write(HTTPEncoder.encodeRequest(request)) + } + + func readResponse() async throws -> HTTPResponse { + try await HTTPDecoder.decodeResponse(from: bytes) + } + + func writeFrame(_ frame: WSFrame) async throws { + try await write(WSFrameEncoder.encodeFrame(frame)) + } + + func readFrame() async throws -> WSFrame { + try await WSFrameEncoder.decodeFrame(from: bytes) + } +} diff --git a/FlyingFox/Tests/AsyncSocketTests.swift b/FlyingFox/Tests/AsyncSocketTests.swift index 4ceca6f..1bfa0c2 100644 --- a/FlyingFox/Tests/AsyncSocketTests.swift +++ b/FlyingFox/Tests/AsyncSocketTests.swift @@ -63,22 +63,6 @@ extension AsyncSocket { try await write(string.data(using: .utf8)!) } - func writeRequest(_ request: HTTPRequest) async throws { - try await write(HTTPEncoder.encodeRequest(request)) - } - - func writeFrame(_ frame: WSFrame) async throws { - try await write(WSFrameEncoder.encodeFrame(frame)) - } - - func readResponse() async throws -> HTTPResponse { - try await HTTPDecoder.decodeResponse(from: bytes) - } - - func readFrame() async throws -> WSFrame { - try await WSFrameEncoder.decodeFrame(from: bytes) - } - func readString(length: Int) async throws -> String { let bytes = try await read(bytes: length) guard let string = String(data: Data(bytes), encoding: .utf8) else { diff --git a/FlyingFox/Tests/HTTPClientTests.swift b/FlyingFox/Tests/HTTPClientTests.swift new file mode 100644 index 0000000..cdc9b4c --- /dev/null +++ b/FlyingFox/Tests/HTTPClientTests.swift @@ -0,0 +1,55 @@ +// +// HTTPClientTests.swift +// FlyingFox +// +// Created by Simon Whitty on 8/06/2024. +// Copyright © 2024 Simon Whitty. All rights reserved. +// +// Distributed under the permissive MIT license +// Get the latest version from here: +// +// https://github.com/swhitty/FlyingFox +// +// 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. +// + +@_spi(Private) import struct FlyingFox._HTTPClient +@testable import FlyingFox +@testable import FlyingSocks +import XCTest +import Foundation + +final class HTTPClientTests: XCTestCase { + + func testClient() async throws { + // given + let server = HTTPServer(port: 0) + let task = Task { try await server.start() } + defer { task.cancel() } + let client = _HTTPClient() + + // when + let port = try await server.waitForListeningPort() + let response = try await client.sendHTTPRequest(HTTPRequest.make(), to: .loopback(port: port)) + + // then + XCTAssertEqual(response.statusCode, .notFound) + } + +} diff --git a/FlyingFox/Tests/HTTPServerTests.swift b/FlyingFox/Tests/HTTPServerTests.swift index d83e042..2215c74 100644 --- a/FlyingFox/Tests/HTTPServerTests.swift +++ b/FlyingFox/Tests/HTTPServerTests.swift @@ -29,7 +29,7 @@ // SOFTWARE. // -@testable import FlyingFox +@_spi(Private) @testable import FlyingFox @testable import FlyingSocks import XCTest import Foundation diff --git a/FlyingFox/Tests/WebSocket/WSFrameEncoderTests.swift b/FlyingFox/Tests/WebSocket/WSFrameEncoderTests.swift index eb03720..2783658 100644 --- a/FlyingFox/Tests/WebSocket/WSFrameEncoderTests.swift +++ b/FlyingFox/Tests/WebSocket/WSFrameEncoderTests.swift @@ -29,7 +29,7 @@ // SOFTWARE. // -@testable import FlyingFox +@_spi(Private) @testable import FlyingFox @testable import FlyingSocks import Foundation import XCTest