Skip to content

Commit

Permalink
feat(functions): invoke function with custom query params (#376)
Browse files Browse the repository at this point in the history
  • Loading branch information
grdsdev committed May 9, 2024
1 parent 69d05ef commit b4b9276
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 23 deletions.
34 changes: 18 additions & 16 deletions Sources/Functions/FunctionsClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -161,17 +161,7 @@ public final class FunctionsClient: Sendable {
functionName: String,
invokeOptions: FunctionInvokeOptions
) async throws -> HTTPResponse {
var request = HTTPRequest(
url: url.appendingPathComponent(functionName),
method: invokeOptions.httpMethod ?? .post,
headers: mutableState.headers.merged(with: invokeOptions.headers),
body: invokeOptions.body
)

if let region = invokeOptions.region ?? region {
request.headers["x-region"] = region
}

let request = buildRequest(functionName: functionName, options: invokeOptions)
let response = try await http.send(request)

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

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

let url = url.appendingPathComponent(functionName)
var urlRequest = URLRequest(url: url)
urlRequest.allHTTPHeaderFields = mutableState.headers.merged(with: invokeOptions.headers).dictionary
urlRequest.httpMethod = (invokeOptions.method ?? .post).rawValue
urlRequest.httpBody = invokeOptions.body
let urlRequest = buildRequest(functionName: functionName, options: invokeOptions).urlRequest

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

return stream
}

private func buildRequest(functionName: String, options: FunctionInvokeOptions) -> HTTPRequest {
var request = HTTPRequest(
url: url.appendingPathComponent(functionName),
method: options.httpMethod ?? .post,
query: options.query,
headers: mutableState.headers.merged(with: options.headers),
body: options.body
)

if let region = options.region ?? region {
request.headers["x-region"] = region
}

return request
}
}

final class StreamResponseDelegate: NSObject, URLSessionDataDelegate, Sendable {
Expand Down
8 changes: 8 additions & 0 deletions Sources/Functions/Types.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,21 @@ public struct FunctionInvokeOptions: Sendable {
let body: Data?
/// The Region to invoke the function in.
let region: String?
/// The query to be included in the function invocation.
let query: [URLQueryItem]

/// Initializes the `FunctionInvokeOptions` structure.
///
/// - Parameters:
/// - method: Method to use in the function invocation.
/// - query: The query to be included in the function invocation.
/// - headers: Headers to be included in the function invocation. (Default: empty dictionary)
/// - region: The Region to invoke the function in.
/// - body: The body data to be sent with the function invocation. (Default: nil)
@_disfavoredOverload
public init(
method: Method? = nil,
query: [URLQueryItem] = [],
headers: [String: String] = [:],
region: String? = nil,
body: some Encodable
Expand All @@ -62,23 +66,27 @@ public struct FunctionInvokeOptions: Sendable {
self.method = method
self.headers = defaultHeaders.merged(with: HTTPHeaders(headers))
self.region = region
self.query = query
}

/// Initializes the `FunctionInvokeOptions` structure.
///
/// - Parameters:
/// - method: Method to use in the function invocation.
/// - query: The query to be included in the function invocation.
/// - headers: Headers to be included in the function invocation. (Default: empty dictionary)
/// - region: The Region to invoke the function in.
@_disfavoredOverload
public init(
method: Method? = nil,
query: [URLQueryItem] = [],
headers: [String: String] = [:],
region: String? = nil
) {
self.method = method
self.headers = HTTPHeaders(headers)
self.region = region
self.query = query
body = nil
}

Expand Down
4 changes: 2 additions & 2 deletions Sources/Storage/StorageFileApi.swift
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ public class StorageFileApi: StorageApi {
"bucketId": bucketId,
"sourceKey": source,
"destinationKey": destination,
"destinationBucket": options?.destinationBucket
"destinationBucket": options?.destinationBucket,
]
)
)
Expand Down Expand Up @@ -156,7 +156,7 @@ public class StorageFileApi: StorageApi {
"bucketId": bucketId,
"sourceKey": source,
"destinationKey": destination,
"destinationBucket": options?.destinationBucket
"destinationBucket": options?.destinationBucket,
]
)
)
Expand Down
10 changes: 5 additions & 5 deletions Sources/_Helpers/SharedModels/HTTPError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@ public struct HTTPError: Error, Sendable {

extension HTTPError: LocalizedError {
public var errorDescription: String? {
var message = "Status Code: \(self.response.statusCode)"
if let body = String(data: data, encoding: .utf8) {
message += " Body: \(body)"
}
return message
var message = "Status Code: \(response.statusCode)"
if let body = String(data: data, encoding: .utf8) {
message += " Body: \(body)"
}
return message
}
}
21 changes: 21 additions & 0 deletions Tests/FunctionsTests/FunctionsClientTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,27 @@ final class FunctionsClientTests: XCTestCase {
XCTAssertEqual(request?.method, .delete)
}

func testInvokeWithQuery() async throws {
let http = HTTPClientMock().any { _ in try .stub(body: Empty()) }

let sut = FunctionsClient(
url: url,
headers: ["Apikey": apiKey],
region: nil,
http: http
)

try await sut.invoke(
"hello-world",
options: .init(
query: [URLQueryItem(name: "key", value: "value")]
)
)

let request = http.receivedRequests.last
XCTAssertEqual(request?.urlRequest.url?.query, "key=value")
}

func testInvokeWithRegionDefinedInClient() async throws {
let http = HTTPClientMock()
.any { _ in try .stub(body: Empty()) }
Expand Down

0 comments on commit b4b9276

Please sign in to comment.