Skip to content

Commit c3be915

Browse files
authored
Merge pull request #37 from phiHero/master
fix: encode URL user input Id
2 parents 58e996a + 6202234 commit c3be915

16 files changed

+96
-66
lines changed

Sources/Typesense/Alias.swift

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,46 +12,47 @@ public struct Alias {
1212
}
1313

1414
public func upsert(name: String, collection: CollectionAliasSchema) async throws -> (CollectionAlias?, URLResponse?) {
15-
let schemaData: Data?
16-
17-
schemaData = try encoder.encode(collection)
18-
19-
if let validSchema = schemaData {
20-
let (data, response) = try await apiCall.put(endPoint: "\(RESOURCEPATH)/\(name)", body: validSchema)
21-
if let result = data {
22-
let alias = try decoder.decode(CollectionAlias.self, from: result)
23-
return (alias, response)
24-
}
15+
let schemaData = try encoder.encode(collection)
16+
let (data, response) = try await apiCall.put(endPoint: endpointPath(name), body: schemaData)
17+
if let result = data {
18+
let alias = try decoder.decode(CollectionAlias.self, from: result)
19+
return (alias, response)
2520
}
26-
return (nil, nil)
21+
return (nil, response)
2722
}
2823

2924
public func retrieve(name: String) async throws -> (CollectionAlias?, URLResponse?) {
30-
let (data, response) = try await apiCall.get(endPoint: "\(RESOURCEPATH)/\(name)")
25+
let (data, response) = try await apiCall.get(endPoint: endpointPath(name))
3126
if let result = data {
3227
let alias = try decoder.decode(CollectionAlias.self, from: result)
3328
return (alias, response)
3429
}
35-
return (nil, nil)
30+
return (nil, response)
3631
}
3732

3833
public func retrieve() async throws -> (CollectionAliasesResponse?, URLResponse?) {
39-
let (data, response) = try await apiCall.get(endPoint: "\(RESOURCEPATH)")
34+
let (data, response) = try await apiCall.get(endPoint: endpointPath())
4035
if let result = data {
4136
let aliases = try decoder.decode(CollectionAliasesResponse.self, from: result)
4237
return (aliases, response)
4338
}
44-
return (nil, nil)
39+
return (nil, response)
4540
}
4641

4742
public func delete(name: String) async throws -> (CollectionAlias?, URLResponse?) {
48-
let (data, response) = try await apiCall.delete(endPoint: "\(RESOURCEPATH)/\(name)")
43+
let (data, response) = try await apiCall.delete(endPoint: endpointPath(name))
4944
if let result = data {
5045
let alias = try decoder.decode(CollectionAlias.self, from: result)
5146
return (alias, response)
5247
}
53-
return (nil, nil)
48+
return (nil, response)
5449
}
5550

56-
51+
private func endpointPath(_ operation: String? = nil) throws -> String {
52+
if let operation: String = operation {
53+
return try "\(RESOURCEPATH)/\(operation.encodeURL())"
54+
} else {
55+
return RESOURCEPATH
56+
}
57+
}
5758
}

Sources/Typesense/AnalyticsRule.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ public struct AnalyticsRule {
2929
return (nil, response)
3030
}
3131

32-
private func endpointPath() -> String {
33-
return "\(AnalyticsRules.resourcePath)/\(name)"
32+
private func endpointPath() throws -> String {
33+
return try "\(AnalyticsRules.resourcePath)/\(name.encodeURL())"
3434
}
3535
}

Sources/Typesense/AnalyticsRules.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ public struct AnalyticsRules {
3333
return (nil, response)
3434
}
3535

36-
private func endpointPath(_ operation: String? = nil) -> String {
36+
private func endpointPath(_ operation: String? = nil) throws -> String {
3737
if let operation = operation {
38-
return "\(AnalyticsRules.resourcePath)/\(operation)"
38+
return try "\(AnalyticsRules.resourcePath)/\(operation.encodeURL())"
3939
} else {
4040
return AnalyticsRules.resourcePath
4141
}

Sources/Typesense/Collection.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ import Foundation
66

77
public struct Collection {
88
var apiCall: ApiCall
9-
let RESOURCEPATH = "collections"
10-
119
var collectionName: String
1210

1311
init(apiCall: ApiCall, collectionName: String) {
@@ -24,7 +22,7 @@ public struct Collection {
2422
}
2523

2624
public func delete() async throws -> (CollectionResponse?, URLResponse?) {
27-
let (data, response) = try await apiCall.delete(endPoint: "\(RESOURCEPATH)/\(collectionName)")
25+
let (data, response) = try await apiCall.delete(endPoint: endpointPath())
2826
if let result = data {
2927
let fetchedCollection = try decoder.decode(CollectionResponse.self, from: result)
3028
return (fetchedCollection, response)
@@ -33,7 +31,7 @@ public struct Collection {
3331
}
3432

3533
public func retrieve() async throws -> (CollectionResponse?, URLResponse?) {
36-
let (data, response) = try await apiCall.get(endPoint: "\(RESOURCEPATH)/\(collectionName)")
34+
let (data, response) = try await apiCall.get(endPoint: endpointPath())
3735
if let result = data {
3836
let fetchedCollection = try decoder.decode(CollectionResponse.self, from: result)
3937
return (fetchedCollection, response)
@@ -52,4 +50,8 @@ public struct Collection {
5250
public func override(_ overrideId: String) -> Override{
5351
return Override(apiCall: self.apiCall, collectionName: self.collectionName, overrideId: overrideId)
5452
}
53+
54+
private func endpointPath() throws -> String {
55+
return "\(Collections.RESOURCEPATH)/\(try collectionName.encodeURL())"
56+
}
5557
}

Sources/Typesense/Document.swift

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,30 @@ public struct Document {
88
var apiCall: ApiCall
99
var collectionName: String
1010
var id: String
11-
let RESOURCEPATH: String
1211

1312
init(apiCall: ApiCall, collectionName: String, id: String) {
1413
self.apiCall = apiCall
1514
self.collectionName = collectionName
1615
self.id = id
17-
self.RESOURCEPATH = "collections/\(collectionName)/documents"
1816
}
1917

2018
public func delete() async throws -> (Data?, URLResponse?) {
21-
let (data, response) = try await apiCall.delete(endPoint: "\(RESOURCEPATH)/\(self.id)")
19+
let (data, response) = try await apiCall.delete(endPoint: endpointPath())
2220
return (data, response)
2321
}
2422

2523
public func retrieve() async throws -> (Data?, URLResponse?) {
26-
let (data, response) = try await apiCall.get(endPoint: "\(RESOURCEPATH)/\(self.id)")
24+
let (data, response) = try await apiCall.get(endPoint: endpointPath())
2725
return (data, response)
2826
}
2927

3028
public func update(newDocument: Data, options: DocumentIndexParameters? = nil) async throws -> (Data?, URLResponse?) {
3129
let queryParams = try createURLQuery(forSchema: options)
32-
let (data, response) = try await apiCall.patch(endPoint: "\(RESOURCEPATH)/\(self.id)", body: newDocument, queryParameters: queryParams)
30+
let (data, response) = try await apiCall.patch(endPoint: endpointPath(), body: newDocument, queryParameters: queryParams)
3331
return (data, response)
3432
}
3533

34+
private func endpointPath() throws -> String {
35+
return try "\(Collections.RESOURCEPATH)/\(collectionName.encodeURL())/documents/\(id.encodeURL())"
36+
}
3637
}

Sources/Typesense/Documents.swift

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,30 @@ import Foundation
77
public struct Documents {
88
var apiCall: ApiCall
99
var collectionName: String
10-
let RESOURCEPATH: String
1110

1211
init(apiCall: ApiCall, collectionName: String) {
1312
self.apiCall = apiCall
1413
self.collectionName = collectionName
15-
self.RESOURCEPATH = "collections/\(collectionName)/documents"
1614
}
1715

1816
public func create(document: Data, options: DocumentIndexParameters? = nil) async throws -> (Data?, URLResponse?) {
1917
let queryParams = try createURLQuery(forSchema: options)
20-
let (data, response) = try await apiCall.post(endPoint: RESOURCEPATH, body: document, queryParameters: queryParams)
18+
let (data, response) = try await apiCall.post(endPoint: endpointPath(), body: document, queryParameters: queryParams)
2119
return (data, response)
2220
}
2321

2422
public func upsert(document: Data, options: DocumentIndexParameters? = nil) async throws -> (Data?, URLResponse?) {
2523
var queryParams = try createURLQuery(forSchema: options)
2624
queryParams.append(URLQueryItem(name: "action", value: "upsert"))
27-
let (data, response) = try await apiCall.post(endPoint: RESOURCEPATH, body: document, queryParameters: queryParams)
25+
let (data, response) = try await apiCall.post(endPoint: endpointPath(), body: document, queryParameters: queryParams)
2826
return (data, response)
2927
}
3028

3129
public func update<T: Codable>(document: T, options: DocumentIndexParameters? = nil) async throws -> (T?, URLResponse?) {
3230
var queryParams = try createURLQuery(forSchema: options)
3331
queryParams.append(URLQueryItem(name: "action", value: "update"))
3432
let jsonData = try encoder.encode(document)
35-
let (data, response) = try await apiCall.post(endPoint: RESOURCEPATH, body: jsonData, queryParameters: queryParams)
33+
let (data, response) = try await apiCall.post(endPoint: endpointPath(), body: jsonData, queryParameters: queryParams)
3634
if let validData = data {
3735
let decodedData = try decoder.decode(T.self, from: validData)
3836
return (decodedData, response)
@@ -43,7 +41,7 @@ public struct Documents {
4341
public func update<T: Encodable>(document: T, options: UpdateDocumentsByFilterParameters) async throws -> (UpdateByFilterResponse?, URLResponse?) {
4442
let queryParams = try createURLQuery(forSchema: options)
4543
let jsonData = try encoder.encode(document)
46-
let (data, response) = try await apiCall.patch(endPoint: RESOURCEPATH, body: jsonData, queryParameters: queryParams)
44+
let (data, response) = try await apiCall.patch(endPoint: endpointPath(), body: jsonData, queryParameters: queryParams)
4745
if let validData = data {
4846
let decodedData = try decoder.decode(UpdateByFilterResponse.self, from: validData)
4947
return (decodedData, response)
@@ -53,7 +51,7 @@ public struct Documents {
5351

5452
public func delete(options: DeleteDocumentsParameters) async throws -> (DeleteDocumentsResponse?, URLResponse?) {
5553
let queryParams = try createURLQuery(forSchema: options)
56-
let (data, response) = try await apiCall.delete(endPoint: "\(RESOURCEPATH)", queryParameters: queryParams)
54+
let (data, response) = try await apiCall.delete(endPoint: endpointPath(), queryParameters: queryParams)
5755
if let validData = data {
5856
let decodedData = try decoder.decode(DeleteDocumentsResponse.self, from: validData)
5957
return (decodedData, response)
@@ -70,14 +68,14 @@ public struct Documents {
7068
if let givenBatchSize = batchSize {
7169
deleteQueryParams.append(URLQueryItem(name: "batch_size", value: String(givenBatchSize)))
7270
}
73-
let (data, response) = try await apiCall.delete(endPoint: "\(RESOURCEPATH)", queryParameters: deleteQueryParams)
71+
let (data, response) = try await apiCall.delete(endPoint: endpointPath(), queryParameters: deleteQueryParams)
7472
return (data, response)
7573

7674
}
7775

7876
public func search(_ searchParameters: SearchParameters) async throws -> (Data?, URLResponse?) {
7977
let queryParams = try createURLQuery(forSchema: searchParameters)
80-
return try await apiCall.get(endPoint: "\(RESOURCEPATH)/search", queryParameters: queryParams)
78+
return try await apiCall.get(endPoint: endpointPath("search"), queryParameters: queryParams)
8179
}
8280

8381
public func search<T>(_ searchParameters: SearchParameters, for: T.Type) async throws -> (SearchResult<T>?, URLResponse?) {
@@ -307,7 +305,7 @@ public struct Documents {
307305
searchQueryParams.append(URLQueryItem(name: "facet_strategy", value: facetReturnParent))
308306
}
309307

310-
let (data, response) = try await apiCall.get(endPoint: "\(RESOURCEPATH)/search", queryParameters: searchQueryParams)
308+
let (data, response) = try await apiCall.get(endPoint: endpointPath("search"), queryParameters: searchQueryParams)
311309

312310
if let validData = data {
313311
let searchRes = try decoder.decode(SearchResult<T>.self, from: validData)
@@ -319,7 +317,7 @@ public struct Documents {
319317

320318
public func importBatch(_ documents: Data, options: ImportDocumentsParameters) async throws -> (Data?, URLResponse?) {
321319
let queryParams = try createURLQuery(forSchema: options)
322-
let (data, response) = try await apiCall.post(endPoint: "\(RESOURCEPATH)/import", body: documents, queryParameters: queryParams)
320+
let (data, response) = try await apiCall.post(endPoint: endpointPath("import"), body: documents, queryParameters: queryParams)
323321
return (data, response)
324322
}
325323

@@ -329,13 +327,22 @@ public struct Documents {
329327
if let specifiedAction = action {
330328
importAction.value = specifiedAction.rawValue
331329
}
332-
let (data, response) = try await apiCall.post(endPoint: "\(RESOURCEPATH)/import", body: documents, queryParameters: [importAction])
330+
let (data, response) = try await apiCall.post(endPoint: endpointPath("import"), body: documents, queryParameters: [importAction])
333331
return (data, response)
334332
}
335333

336334
public func export(options: ExportDocumentsParameters? = nil) async throws -> (Data?, URLResponse?) {
337335
let searchQueryParams = try createURLQuery(forSchema: options)
338-
let (data, response) = try await apiCall.get(endPoint: "\(RESOURCEPATH)/export", queryParameters: searchQueryParams)
336+
let (data, response) = try await apiCall.get(endPoint: endpointPath("export"), queryParameters: searchQueryParams)
339337
return (data, response)
340338
}
339+
340+
private func endpointPath(_ operation: String? = nil) throws -> String {
341+
let baseEndpoint = try "collections/\(collectionName.encodeURL())/documents"
342+
if let operation: String = operation {
343+
return "\(baseEndpoint)/\(operation)"
344+
} else {
345+
return baseEndpoint
346+
}
347+
}
341348
}

Sources/Typesense/Errors.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ extension HTTPError: LocalizedError {
2121

2222
public enum URLError: Error {
2323
case invalidURL
24+
case encodingError(message: String)
2425
}
2526

2627
public enum DataError: Error {

Sources/Typesense/Override.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ public struct Override {
3434
return (nil, response)
3535
}
3636

37-
private func endpointPath() -> String {
38-
return "\(Collections.RESOURCEPATH)/\(collectionName)/\(Overrides.RESOURCEPATH)/\(overrideId)"
37+
private func endpointPath() throws -> String {
38+
return try "\(Collections.RESOURCEPATH)/\(collectionName.encodeURL())/\(Overrides.RESOURCEPATH)/\(overrideId.encodeURL())"
3939
}
4040

4141

Sources/Typesense/Overrides.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@ public struct Overrides {
3535
return (nil, nil)
3636
}
3737

38-
private func endpointPath(_ operation: String? = nil) -> String {
39-
let baseEndpoint = "\(Collections.RESOURCEPATH)/\(collectionName)/\(Overrides.RESOURCEPATH)"
38+
private func endpointPath(_ operation: String? = nil) throws -> String {
39+
let baseEndpoint = try "\(Collections.RESOURCEPATH)/\(collectionName.encodeURL())/\(Overrides.RESOURCEPATH)"
4040
if let operation = operation {
41-
return "\(baseEndpoint)/\(operation)"
41+
return try "\(baseEndpoint)/\(operation.encodeURL())"
4242
} else {
4343
return baseEndpoint
4444
}

Sources/Typesense/Preset.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ public struct Preset {
3131
return (nil, response)
3232
}
3333

34-
private func endpointPath() -> String {
35-
return "\(Presets.RESOURCEPATH)/\(presetName)"
34+
private func endpointPath() throws -> String {
35+
return try "\(Presets.RESOURCEPATH)/\(presetName.encodeURL())"
3636
}
3737

3838

0 commit comments

Comments
 (0)