Skip to content

Commit 90f5df9

Browse files
committed
Add explicit percent encoding for URL parameters
1 parent d37eb48 commit 90f5df9

File tree

3 files changed

+35
-27
lines changed

3 files changed

+35
-27
lines changed

Sources/AlgoliaSearchClient/Transport/URLSession/URLRequest+Convenience.swift

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@ import Foundation
99

1010
extension URLRequest: Builder {}
1111

12+
extension CharacterSet {
13+
14+
static var uriAllowed = CharacterSet.alphanumerics.union(.init(charactersIn: "-_.!~*'()"))
15+
16+
}
17+
1218
extension URLRequest {
1319

1420
subscript(header key: HTTPHeaderKey) -> String? {
@@ -28,41 +34,43 @@ extension URLRequest {
2834
var urlComponents = URLComponents()
2935
urlComponents.scheme = "https"
3036
urlComponents.path = path.fullPath
37+
38+
if let urlParameters = requestOptions?.urlParameters {
39+
urlComponents.queryItems = urlParameters
40+
.map { (key, value) in
41+
guard let encodedName = key.rawValue.addingPercentEncoding(withAllowedCharacters: .uriAllowed) else {
42+
return nil
43+
}
44+
let encodedValue = value?.addingPercentEncoding(withAllowedCharacters: .uriAllowed)
45+
return URLQueryItem(name: encodedName, value: encodedValue)
46+
}
47+
.compactMap { $0 }
48+
}
3149

3250
var request = URLRequest(url: urlComponents.url!)
3351

3452
request.httpMethod = method.rawValue
3553
request.httpBody = body
36-
54+
3755
if let requestOptions = requestOptions {
38-
request.setRequestOptions(requestOptions)
56+
57+
requestOptions.headers.forEach { header in
58+
let (value, field) = (header.value, header.key.rawValue)
59+
request.setValue(value, forHTTPHeaderField: field)
60+
}
61+
62+
// If body is set in query parameters, it will override the body passed as parameter to this function
63+
if let body = requestOptions.body, !body.isEmpty {
64+
let jsonEncodedBody = try? JSONSerialization.data(withJSONObject: body, options: [])
65+
request.httpBody = jsonEncodedBody
66+
}
67+
3968
}
40-
69+
70+
request.httpBody = body
4171
self = request
4272
}
4373

44-
mutating func setRequestOptions(_ requestOptions: RequestOptions) {
45-
46-
// Append headers
47-
requestOptions.headers.forEach { setValue($0.value, forHTTPHeaderField: $0.key.rawValue) }
48-
49-
// Append query items
50-
if let url = url, var currentComponents = URLComponents(string: url.absoluteString) {
51-
let requestOptionsItems = requestOptions.urlParameters.map { URLQueryItem(name: $0.key.rawValue, value: $0.value) }
52-
var existingItems = currentComponents.queryItems ?? []
53-
existingItems.append(contentsOf: requestOptionsItems)
54-
currentComponents.queryItems = existingItems
55-
self.url = currentComponents.url
56-
}
57-
58-
// Set body
59-
if
60-
let body = requestOptions.body,
61-
let jsonData = try? JSONSerialization.data(withJSONObject: body, options: []) {
62-
httpBody = jsonData
63-
}
64-
}
65-
6674
}
6775

6876
extension URLRequest {

Tests/AlgoliaSearchClientTests/Unit/Command/SearchCommandTests.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class SearchCommandTests: XCTestCase, AlgoliaCommandTest {
3939
callType: .read,
4040
method: .get,
4141
urlPath: "/1/indexes/testIndex/browse",
42-
queryItems: [.init(name: "testParameter", value: "testParameterValue"), .init(name: "cursor", value: "testCursor")],
42+
queryItems: [.init(name: "testParameter", value: "testParameterValue"), .init(name: "cursor", value: "AgA%2BBgg4MTUyNTQ0Mg%3D%3D")],
4343
body: nil,
4444
requestOptions: test.requestOptions)
4545
}

Tests/AlgoliaSearchClientTests/Unit/TestValues.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ struct TestValues {
2828
}()
2929
let taskID: TaskID = "testTaskID"
3030
let requestOptions = RequestOptions(headers: ["testHeader": "testHeaderValue"], urlParameters: ["testParameter": "testParameterValue"])
31-
let cursor: Cursor = "testCursor"
31+
let cursor: Cursor = "AgA+Bgg4MTUyNTQ0Mg=="
3232
let userID: UserID = "testUserID"
3333
let clusterName: ClusterName = "testClusterName"
3434

0 commit comments

Comments
 (0)