From 2b15cbe58e0021a1d2724256f6dcefe094c531c2 Mon Sep 17 00:00:00 2001 From: Zhenchao Li Date: Wed, 23 Jul 2025 17:13:32 -0700 Subject: [PATCH] Add brotli as a dependency --- Package.swift | 9 ++++++++- Tests/Foundation/HTTPServer.swift | 24 ++++++++++++++++++++++++ Tests/Foundation/TestURLSession.swift | 23 +++++++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/Package.swift b/Package.swift index 4a9dc5dc71..7ba345e7c3 100644 --- a/Package.swift +++ b/Package.swift @@ -58,7 +58,9 @@ if let environmentPath = Context.environment["CURL_INCLUDE_PATH"] { var curlLinkFlags: [LinkerSetting] = [ .linkedLibrary("libcurl.lib", .when(platforms: [.windows])), - .linkedLibrary("zlibstatic.lib", .when(platforms: [.windows])) + .linkedLibrary("zlibstatic.lib", .when(platforms: [.windows])), + .linkedLibrary("brotlicommon.lib", .when(platforms: [.windows])), + .linkedLibrary("brotlidec.lib", .when(platforms: [.windows])) ] if let environmentPath = Context.environment["CURL_LIBRARY_PATH"] { curlLinkFlags.append(.unsafeFlags([ @@ -70,6 +72,11 @@ if let environmentPath = Context.environment["ZLIB_LIBRARY_PATH"] { "-L\(environmentPath)" ])) } +if let environmentPath = Context.environment["BROTLI_LIBRARY_PATH"] { + curlLinkFlags.append(.unsafeFlags([ + "-L\(environmentPath)" + ])) +} var libxmlLinkFlags: [LinkerSetting] = [ .linkedLibrary("libxml2s.lib", .when(platforms: [.windows])) diff --git a/Tests/Foundation/HTTPServer.swift b/Tests/Foundation/HTTPServer.swift index a6457f285f..7b42864d50 100644 --- a/Tests/Foundation/HTTPServer.swift +++ b/Tests/Foundation/HTTPServer.swift @@ -481,6 +481,18 @@ class _HTTPServer: CustomStringConvertible { "\r\n").data(using: .utf8)! try tcpSocket.writeRawData(responseData) } + + func respondWithAcceptEncoding(request: _HTTPRequest) throws { + var responseData: Data + if let acceptEncoding = request.getHeader(for: "Accept-Encoding") { + let content = acceptEncoding.data(using: .utf8)! + responseData = "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=ISO-8859-1\r\nContent-Length: \(content.count)\r\n\r\n".data(using: .utf8)! + responseData.append(content) + } else { + responseData = "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=ISO-8859-1\r\nContent-Length: 0\r\n\r\n".data(using: .utf8)! + } + try tcpSocket.writeRawData(responseData) + } } struct _HTTPRequest: CustomStringConvertible { @@ -690,6 +702,8 @@ public class TestURLSessionServer: CustomStringConvertible { try httpServer.respondWithUnauthorizedHeader() } else if req.uri.hasPrefix("/web-socket") { try handleWebSocketRequest(req) + } else if req.uri.hasPrefix("/accept-encoding") { + try httpServer.respondWithAcceptEncoding(request: req) } else { let response = try getResponse(request: req) try httpServer.respond(with: response) @@ -852,6 +866,16 @@ public class TestURLSessionServer: CustomStringConvertible { "Content-Encoding: gzip"].joined(separator: _HTTPUtils.CRLF), bodyData: helloWorld) } + + if uri == "/brotli-response" { + // This is "Hello World!" brotli encoded. + let helloWorld = Data([0x8B, 0x05, 0x80, 0x48, 0x65, 0x6C, 0x6C, 0x6F, + 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x03]) + return _HTTPResponse(response: .OK, + headers: ["Content-Length: \(helloWorld.count)", + "Content-Encoding: br"].joined(separator: _HTTPUtils.CRLF), + bodyData: helloWorld) + } if uri == "/echo-query" { let body = request.parameters.map { "\($0.key)=\($0.value)" }.joined(separator: "&") diff --git a/Tests/Foundation/TestURLSession.swift b/Tests/Foundation/TestURLSession.swift index df12d9a085..9bbfb922cd 100644 --- a/Tests/Foundation/TestURLSession.swift +++ b/Tests/Foundation/TestURLSession.swift @@ -31,6 +31,18 @@ final class TestURLSession: LoopbackServerTest, @unchecked Sendable { } } + func test_dataTaskWithAcceptEncoding() async { + let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/accept-encoding" + let url = URL(string: urlString)! + let d = DataTask(with: expectation(description: "GET \(urlString): with a delegate")) + d.run(with: url) + waitForExpectations(timeout: 12) + if !d.error { + let supportedEncodings = d.capital.split(separator: ",").map { $0.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines ) } + XCTAssert(supportedEncodings.contains("br"), "test_dataTaskWithURLRequest returned an unexpected result") + } + } + func test_dataTaskWithURLCompletionHandler() async { //shared session await dataTaskWithURLCompletionHandler(with: URLSession.shared) @@ -256,6 +268,17 @@ final class TestURLSession: LoopbackServerTest, @unchecked Sendable { } } + func test_brotliDataTask() async { + let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/brotli-response" + let url = URL(string: urlString)! + let d = DataTask(with: expectation(description: "GET \(urlString): brotli response")) + d.run(with: url) + waitForExpectations(timeout: 12) + if !d.error { + XCTAssertEqual(d.capital, "Hello World!") + } + } + func test_downloadTaskWithURL() async { let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/country.txt" let url = URL(string: urlString)!