Skip to content

Commit bcf2cca

Browse files
authored
Merge pull request #5251 from zhenchaoli/zcli/brotli
Add brotli support to FoundationNetworking
2 parents ec67520 + f837322 commit bcf2cca

File tree

4 files changed

+84
-3
lines changed

4 files changed

+84
-3
lines changed

Package.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,9 @@ if let environmentPath = Context.environment["CURL_INCLUDE_PATH"] {
5858

5959
var curlLinkFlags: [LinkerSetting] = [
6060
.linkedLibrary("libcurl.lib", .when(platforms: [.windows])),
61-
.linkedLibrary("zlibstatic.lib", .when(platforms: [.windows]))
61+
.linkedLibrary("zlibstatic.lib", .when(platforms: [.windows])),
62+
.linkedLibrary("brotlicommon.lib", .when(platforms: [.windows])),
63+
.linkedLibrary("brotlidec.lib", .when(platforms: [.windows]))
6264
]
6365
if let environmentPath = Context.environment["CURL_LIBRARY_PATH"] {
6466
curlLinkFlags.append(.unsafeFlags([
@@ -70,6 +72,11 @@ if let environmentPath = Context.environment["ZLIB_LIBRARY_PATH"] {
7072
"-L\(environmentPath)"
7173
]))
7274
}
75+
if let environmentPath = Context.environment["BROTLI_LIBRARY_PATH"] {
76+
curlLinkFlags.append(.unsafeFlags([
77+
"-L\(environmentPath)"
78+
]))
79+
}
7380

7481
var libxmlLinkFlags: [LinkerSetting] = [
7582
.linkedLibrary("libxml2s.lib", .when(platforms: [.windows]))

Tests/Foundation/HTTPServer.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,18 @@ class _HTTPServer: CustomStringConvertible {
481481
"\r\n").data(using: .utf8)!
482482
try tcpSocket.writeRawData(responseData)
483483
}
484+
485+
func respondWithAcceptEncoding(request: _HTTPRequest) throws {
486+
var responseData: Data
487+
if let acceptEncoding = request.getHeader(for: "Accept-Encoding") {
488+
let content = acceptEncoding.data(using: .utf8)!
489+
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)!
490+
responseData.append(content)
491+
} else {
492+
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)!
493+
}
494+
try tcpSocket.writeRawData(responseData)
495+
}
484496
}
485497

486498
struct _HTTPRequest: CustomStringConvertible {
@@ -690,6 +702,8 @@ public class TestURLSessionServer: CustomStringConvertible {
690702
try httpServer.respondWithUnauthorizedHeader()
691703
} else if req.uri.hasPrefix("/web-socket") {
692704
try handleWebSocketRequest(req)
705+
} else if req.uri.hasPrefix("/accept-encoding") {
706+
try httpServer.respondWithAcceptEncoding(request: req)
693707
} else {
694708
let response = try getResponse(request: req)
695709
try httpServer.respond(with: response)
@@ -852,6 +866,16 @@ public class TestURLSessionServer: CustomStringConvertible {
852866
"Content-Encoding: gzip"].joined(separator: _HTTPUtils.CRLF),
853867
bodyData: helloWorld)
854868
}
869+
870+
if uri == "/brotli-response" {
871+
// This is "Hello World!" brotli encoded.
872+
let helloWorld = Data([0x8B, 0x05, 0x80, 0x48, 0x65, 0x6C, 0x6C, 0x6F,
873+
0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x21, 0x03])
874+
return _HTTPResponse(response: .OK,
875+
headers: ["Content-Length: \(helloWorld.count)",
876+
"Content-Encoding: br"].joined(separator: _HTTPUtils.CRLF),
877+
bodyData: helloWorld)
878+
}
855879

856880
if uri == "/echo-query" {
857881
let body = request.parameters.map { "\($0.key)=\($0.value)" }.joined(separator: "&")

Tests/Foundation/TestURLSession.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,18 @@ final class TestURLSession: LoopbackServerTest, @unchecked Sendable {
3131
}
3232
}
3333

34+
func test_dataTaskWithAcceptEncoding() async {
35+
let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/accept-encoding"
36+
let url = URL(string: urlString)!
37+
let d = DataTask(with: expectation(description: "GET \(urlString): with a delegate"))
38+
d.run(with: url)
39+
waitForExpectations(timeout: 12)
40+
if !d.error {
41+
let supportedEncodings = d.capital.split(separator: ",").map { $0.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines ) }
42+
XCTAssert(supportedEncodings.contains("br"), "test_dataTaskWithURLRequest returned an unexpected result")
43+
}
44+
}
45+
3446
func test_dataTaskWithURLCompletionHandler() async {
3547
//shared session
3648
await dataTaskWithURLCompletionHandler(with: URLSession.shared)
@@ -256,6 +268,17 @@ final class TestURLSession: LoopbackServerTest, @unchecked Sendable {
256268
}
257269
}
258270

271+
func test_brotliDataTask() async {
272+
let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/brotli-response"
273+
let url = URL(string: urlString)!
274+
let d = DataTask(with: expectation(description: "GET \(urlString): brotli response"))
275+
d.run(with: url)
276+
waitForExpectations(timeout: 12)
277+
if !d.error {
278+
XCTAssertEqual(d.capital, "Hello World!")
279+
}
280+
}
281+
259282
func test_downloadTaskWithURL() async {
260283
let urlString = "http://127.0.0.1:\(TestURLSession.serverPort)/country.txt"
261284
let url = URL(string: urlString)!

cmake/modules/WindowsSwiftPMDependencies.cmake

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,18 @@ function(_foundation_setup_windows_swiftpm_dependencies_target)
3737
EXCLUDE_FROM_ALL YES
3838
)
3939

40+
ExternalProject_Add(brotli
41+
GIT_REPOSITORY https://github.com/google/brotli
42+
GIT_TAG v1.1.0
43+
CMAKE_ARGS
44+
-DCMAKE_INSTALL_PREFIX=${DEST_DIR}/brotli
45+
-DCMAKE_C_COMPILER=cl
46+
-DBUILD_SHARED_LIBS=NO
47+
-DCMAKE_POSITION_INDEPENDENT_CODE=YES
48+
-DCMAKE_BUILD_TYPE=Release
49+
EXCLUDE_FROM_ALL YES
50+
)
51+
4052
ExternalProject_Add(libxml
4153
GIT_REPOSITORY https://github.com/gnome/libxml2.git
4254
GIT_TAG v2.11.5
@@ -63,6 +75,15 @@ function(_foundation_setup_windows_swiftpm_dependencies_target)
6375
# Add a custom target for zlib's install step that curl can depend on
6476
ExternalProject_Add_StepTargets(zlib install)
6577

78+
set(BROTLI_ROOT "${DEST_DIR}/brotli")
79+
set(BROTLI_LIBRARY_DIR "${BROTLI_ROOT}/lib")
80+
set(BROTLI_INCLUDE_DIR "${BROTLI_ROOT}/include")
81+
set(BROTLICOMMON_LIBRARY_PATH "${BROTLI_LIBRARY_DIR}/brotlicommon.lib")
82+
set(BROTLIDEC_LIBRARY_PATH "${BROTLI_LIBRARY_DIR}/brotlidec.lib")
83+
84+
# Add a custom target for brotli's install step that curl can depend on
85+
ExternalProject_Add_StepTargets(brotli install)
86+
6687
ExternalProject_Add(curl
6788
GIT_REPOSITORY https://github.com/curl/curl.git
6889
GIT_TAG curl-8_9_1
@@ -75,7 +96,7 @@ function(_foundation_setup_windows_swiftpm_dependencies_target)
7596
-DCURL_CA_BUNDLE=none
7697
-DCURL_CA_FALLBACK=NO
7798
-DCURL_CA_PATH=none
78-
-DCURL_BROTLI=NO
99+
-DCURL_BROTLI=YES
79100
-DCURL_DISABLE_ALTSVC=NO
80101
-DCURL_DISABLE_AWS=YES
81102
-DCURL_DISABLE_BASIC_AUTH=NO
@@ -150,7 +171,10 @@ function(_foundation_setup_windows_swiftpm_dependencies_target)
150171
-DZLIB_ROOT=${ZLIB_ROOT}
151172
-DZLIB_LIBRARY=${ZLIB_LIBRARY_PATH}
152173
-DZLIB_INCLUDE_DIR=${ZLIB_INCLUDE_DIR}
153-
DEPENDS zlib-install
174+
-DBROTLIDEC_LIBRARY=${BROTLIDEC_LIBRARY_PATH}
175+
-DBROTLICOMMON_LIBRARY=${BROTLICOMMON_LIBRARY_PATH}
176+
-DBROTLI_INCLUDE_DIR=${BROTLI_INCLUDE_DIR}
177+
DEPENDS zlib-install brotli-install
154178
EXCLUDE_FROM_ALL YES
155179
)
156180

@@ -166,6 +190,7 @@ function(_foundation_setup_windows_swiftpm_dependencies_target)
166190
message(STATUS "CURL_INCLUDE_PATH=${CURL_INCLUDE_DIR}")
167191
message(STATUS "CURL_LIBRARY_PATH=${CURL_LIBRARY_DIR}")
168192
message(STATUS "ZLIB_LIBRARY_PATH=${ZLIB_LIBRARY_DIR}")
193+
message(STATUS "BROTLI_LIBRARY_PATH=${BROTLI_LIBRARY_DIR}")
169194

170195
ExternalProject_Add_StepTargets(libxml install)
171196
ExternalProject_Add_StepTargets(curl install)
@@ -186,5 +211,7 @@ function(_foundation_setup_windows_swiftpm_dependencies_target)
186211
COMMAND echo CURL_LIBRARY_PATH=${CURL_LIBRARY_DIR})
187212
add_custom_command(TARGET WindowsSwiftPMDependencies POST_BUILD
188213
COMMAND echo ZLIB_LIBRARY_PATH=${ZLIB_LIBRARY_DIR})
214+
add_custom_command(TARGET WindowsSwiftPMDependencies POST_BUILD
215+
COMMAND echo BROTLI_LIBRARY_PATH=${BROTLI_LIBRARY_DIR})
189216

190217
endfunction()

0 commit comments

Comments
 (0)