Skip to content

Commit b4b9276

Browse files
authored
feat(functions): invoke function with custom query params (#376)
1 parent 69d05ef commit b4b9276

File tree

5 files changed

+54
-23
lines changed

5 files changed

+54
-23
lines changed

Sources/Functions/FunctionsClient.swift

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -161,17 +161,7 @@ public final class FunctionsClient: Sendable {
161161
functionName: String,
162162
invokeOptions: FunctionInvokeOptions
163163
) async throws -> HTTPResponse {
164-
var request = HTTPRequest(
165-
url: url.appendingPathComponent(functionName),
166-
method: invokeOptions.httpMethod ?? .post,
167-
headers: mutableState.headers.merged(with: invokeOptions.headers),
168-
body: invokeOptions.body
169-
)
170-
171-
if let region = invokeOptions.region ?? region {
172-
request.headers["x-region"] = region
173-
}
174-
164+
let request = buildRequest(functionName: functionName, options: invokeOptions)
175165
let response = try await http.send(request)
176166

177167
guard 200 ..< 300 ~= response.statusCode else {
@@ -206,11 +196,7 @@ public final class FunctionsClient: Sendable {
206196

207197
let session = URLSession(configuration: .default, delegate: delegate, delegateQueue: nil)
208198

209-
let url = url.appendingPathComponent(functionName)
210-
var urlRequest = URLRequest(url: url)
211-
urlRequest.allHTTPHeaderFields = mutableState.headers.merged(with: invokeOptions.headers).dictionary
212-
urlRequest.httpMethod = (invokeOptions.method ?? .post).rawValue
213-
urlRequest.httpBody = invokeOptions.body
199+
let urlRequest = buildRequest(functionName: functionName, options: invokeOptions).urlRequest
214200

215201
let task = session.dataTask(with: urlRequest) { data, response, _ in
216202
guard let httpResponse = response as? HTTPURLResponse else {
@@ -241,6 +227,22 @@ public final class FunctionsClient: Sendable {
241227

242228
return stream
243229
}
230+
231+
private func buildRequest(functionName: String, options: FunctionInvokeOptions) -> HTTPRequest {
232+
var request = HTTPRequest(
233+
url: url.appendingPathComponent(functionName),
234+
method: options.httpMethod ?? .post,
235+
query: options.query,
236+
headers: mutableState.headers.merged(with: options.headers),
237+
body: options.body
238+
)
239+
240+
if let region = options.region ?? region {
241+
request.headers["x-region"] = region
242+
}
243+
244+
return request
245+
}
244246
}
245247

246248
final class StreamResponseDelegate: NSObject, URLSessionDataDelegate, Sendable {

Sources/Functions/Types.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,21 @@ public struct FunctionInvokeOptions: Sendable {
2929
let body: Data?
3030
/// The Region to invoke the function in.
3131
let region: String?
32+
/// The query to be included in the function invocation.
33+
let query: [URLQueryItem]
3234

3335
/// Initializes the `FunctionInvokeOptions` structure.
3436
///
3537
/// - Parameters:
3638
/// - method: Method to use in the function invocation.
39+
/// - query: The query to be included in the function invocation.
3740
/// - headers: Headers to be included in the function invocation. (Default: empty dictionary)
3841
/// - region: The Region to invoke the function in.
3942
/// - body: The body data to be sent with the function invocation. (Default: nil)
4043
@_disfavoredOverload
4144
public init(
4245
method: Method? = nil,
46+
query: [URLQueryItem] = [],
4347
headers: [String: String] = [:],
4448
region: String? = nil,
4549
body: some Encodable
@@ -62,23 +66,27 @@ public struct FunctionInvokeOptions: Sendable {
6266
self.method = method
6367
self.headers = defaultHeaders.merged(with: HTTPHeaders(headers))
6468
self.region = region
69+
self.query = query
6570
}
6671

6772
/// Initializes the `FunctionInvokeOptions` structure.
6873
///
6974
/// - Parameters:
7075
/// - method: Method to use in the function invocation.
76+
/// - query: The query to be included in the function invocation.
7177
/// - headers: Headers to be included in the function invocation. (Default: empty dictionary)
7278
/// - region: The Region to invoke the function in.
7379
@_disfavoredOverload
7480
public init(
7581
method: Method? = nil,
82+
query: [URLQueryItem] = [],
7683
headers: [String: String] = [:],
7784
region: String? = nil
7885
) {
7986
self.method = method
8087
self.headers = HTTPHeaders(headers)
8188
self.region = region
89+
self.query = query
8290
body = nil
8391
}
8492

Sources/Storage/StorageFileApi.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ public class StorageFileApi: StorageApi {
125125
"bucketId": bucketId,
126126
"sourceKey": source,
127127
"destinationKey": destination,
128-
"destinationBucket": options?.destinationBucket
128+
"destinationBucket": options?.destinationBucket,
129129
]
130130
)
131131
)
@@ -156,7 +156,7 @@ public class StorageFileApi: StorageApi {
156156
"bucketId": bucketId,
157157
"sourceKey": source,
158158
"destinationKey": destination,
159-
"destinationBucket": options?.destinationBucket
159+
"destinationBucket": options?.destinationBucket,
160160
]
161161
)
162162
)

Sources/_Helpers/SharedModels/HTTPError.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ public struct HTTPError: Error, Sendable {
2626

2727
extension HTTPError: LocalizedError {
2828
public var errorDescription: String? {
29-
var message = "Status Code: \(self.response.statusCode)"
30-
if let body = String(data: data, encoding: .utf8) {
31-
message += " Body: \(body)"
32-
}
33-
return message
29+
var message = "Status Code: \(response.statusCode)"
30+
if let body = String(data: data, encoding: .utf8) {
31+
message += " Body: \(body)"
32+
}
33+
return message
3434
}
3535
}

Tests/FunctionsTests/FunctionsClientTests.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,27 @@ final class FunctionsClientTests: XCTestCase {
7474
XCTAssertEqual(request?.method, .delete)
7575
}
7676

77+
func testInvokeWithQuery() async throws {
78+
let http = HTTPClientMock().any { _ in try .stub(body: Empty()) }
79+
80+
let sut = FunctionsClient(
81+
url: url,
82+
headers: ["Apikey": apiKey],
83+
region: nil,
84+
http: http
85+
)
86+
87+
try await sut.invoke(
88+
"hello-world",
89+
options: .init(
90+
query: [URLQueryItem(name: "key", value: "value")]
91+
)
92+
)
93+
94+
let request = http.receivedRequests.last
95+
XCTAssertEqual(request?.urlRequest.url?.query, "key=value")
96+
}
97+
7798
func testInvokeWithRegionDefinedInClient() async throws {
7899
let http = HTTPClientMock()
79100
.any { _ in try .stub(body: Empty()) }

0 commit comments

Comments
 (0)