Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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