Skip to content

Commit

Permalink
feat: specify region when initializing client
Browse files Browse the repository at this point in the history
  • Loading branch information
grdsdev committed Apr 18, 2024
1 parent d9fd14f commit c776b23
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 1 deletion.
33 changes: 33 additions & 0 deletions Sources/Functions/FunctionsClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public actor FunctionsClient {
let url: URL
/// Headers to be included in the requests.
var headers: [String: String]
/// The Region to invoke the functions in.
let region: String
/// The fetch handler used to make requests.
let fetch: FetchHandler

Expand All @@ -26,17 +28,43 @@ public actor FunctionsClient {
/// - Parameters:
/// - url: The base URL for the functions.
/// - headers: Headers to be included in the requests. (Default: empty dictionary)
/// - region: The Region to invoke the functions in.
/// - fetch: The fetch handler used to make requests. (Default: URLSession.shared.data(for:))
@_disfavoredOverload
public init(
url: URL,
headers: [String: String] = [:],
region: String = FunctionRegion.any.rawValue,
fetch: @escaping FetchHandler = { try await URLSession.shared.data(for: $0) }
) {
self.url = url
self.headers = headers
if headers["X-Client-Info"] == nil {
self.headers["X-Client-Info"] = "functions-swift/\(version)"
}
self.region = region
self.fetch = fetch
}

/// Initializes a new instance of `FunctionsClient`.
///
/// - Parameters:
/// - url: The base URL for the functions.
/// - headers: Headers to be included in the requests. (Default: empty dictionary)
/// - region: The Region to invoke the functions in.
/// - fetch: The fetch handler used to make requests. (Default: URLSession.shared.data(for:))
public init(
url: URL,
headers: [String: String] = [:],
region: FunctionRegion = .any,
fetch: @escaping FetchHandler = { try await URLSession.shared.data(for: $0) }
) {
self.url = url
self.headers = headers
if headers["X-Client-Info"] == nil {
self.headers["X-Client-Info"] = "functions-swift/\(version)"
}
self.region = region.rawValue
self.fetch = fetch
}

Expand Down Expand Up @@ -109,6 +137,11 @@ public actor FunctionsClient {
urlRequest.httpMethod = (invokeOptions.method ?? .post).rawValue
urlRequest.httpBody = invokeOptions.body

let region = invokeOptions.region ?? region
if region != FunctionRegion.any.rawValue {
urlRequest.setValue(region, forHTTPHeaderField: "x-region")
}

let (data, response) = try await fetch(urlRequest)

guard let httpResponse = response as? HTTPURLResponse else {
Expand Down
2 changes: 1 addition & 1 deletion Sources/Functions/Types.swift
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public enum FunctionRegion: String {
case apSouth1 = "ap-south-1"
case apSoutheast1 = "ap-southeast-1"
case apSoutheast2 = "ap-southeast-2"
case aaCentral1 = "ca-central-1"
case caCentral1 = "ca-central-1"
case euCentral1 = "eu-central-1"
case euWest1 = "eu-west-1"
case euWest2 = "eu-west-2"
Expand Down
58 changes: 58 additions & 0 deletions Tests/FunctionsTests/FunctionsClientTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,20 @@ final class FunctionsClientTests: XCTestCase {

lazy var sut = FunctionsClient(url: url, headers: ["Apikey": apiKey])

func testInit() async {
let client = FunctionsClient(
url: url,
headers: ["Apikey": apiKey],
region: .saEast1
)
let region = await client.region
XCTAssertEqual(region, "sa-east-1")

let headers = await client.headers
XCTAssertEqual(headers["Apikey"], apiKey)
XCTAssertNotNil(headers["X-Client-Info"])
}

func testInvoke() async throws {
let url = URL(string: "http://localhost:5432/functions/v1/hello_world")!
let _request = ActorIsolated(URLRequest?.none)
Expand Down Expand Up @@ -43,6 +57,50 @@ final class FunctionsClientTests: XCTestCase {
)
}

func testInvokeWithRegionDefinedInClient() async {
let sut = FunctionsClient(url: url, region: .caCentral1) {
let region = $0.value(forHTTPHeaderField: "x-region")
XCTAssertEqual(region, "ca-central-1")

throw CancellationError()
}

let _ = try? await sut.invoke("hello-world")
}

func testInvokeWithRegion() async {
let sut = FunctionsClient(url: url) {
let region = $0.value(forHTTPHeaderField: "x-region")
XCTAssertEqual(region, "ca-central-1")

throw CancellationError()
}

let _ = try? await sut.invoke("hello-world", options: .init(region: .caCentral1))
}

func testInvokeWithoutRegion() async {
let sut = FunctionsClient(url: url) {
let region = $0.value(forHTTPHeaderField: "x-region")
XCTAssertNil(region)

throw CancellationError()
}

let _ = try? await sut.invoke("hello-world")
}

func testInvokeWithAnyRegion() async {
let sut = FunctionsClient(url: url) {
let region = $0.value(forHTTPHeaderField: "x-region")
XCTAssertNil(region)

throw CancellationError()
}

let _ = try? await sut.invoke("hello-world", options: .init(region: .any))
}

func testInvoke_shouldThrow_URLError_badServerResponse() async {
let sut = FunctionsClient(url: url, headers: ["Apikey": apiKey]) { _ in
throw URLError(.badServerResponse)
Expand Down

0 comments on commit c776b23

Please # to comment.