Skip to content

Commit 4840b25

Browse files
committed
chore: use HTTPClient
1 parent b11f9d5 commit 4840b25

File tree

2 files changed

+51
-25
lines changed

2 files changed

+51
-25
lines changed

Sources/Functions/FunctionsClient.swift

Lines changed: 50 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,26 +18,28 @@ public actor FunctionsClient {
1818
let url: URL
1919
/// Headers to be included in the requests.
2020
var headers: [String: String]
21-
/// The fetch handler used to make requests.
22-
let fetch: FetchHandler
21+
22+
private let http: HTTPClient
2323

2424
/// Initializes a new instance of `FunctionsClient`.
2525
///
2626
/// - Parameters:
2727
/// - url: The base URL for the functions.
2828
/// - headers: Headers to be included in the requests. (Default: empty dictionary)
29+
/// - logger: SupabaseLogger instance to use.
2930
/// - fetch: The fetch handler used to make requests. (Default: URLSession.shared.data(for:))
3031
public init(
3132
url: URL,
3233
headers: [String: String] = [:],
34+
logger: (any SupabaseLogger)? = nil,
3335
fetch: @escaping FetchHandler = { try await URLSession.shared.data(for: $0) }
3436
) {
3537
self.url = url
3638
self.headers = headers
3739
if headers["X-Client-Info"] == nil {
3840
self.headers["X-Client-Info"] = "functions-swift/\(version)"
3941
}
40-
self.fetch = fetch
42+
http = HTTPClient(logger: logger, fetchHandler: fetch)
4143
}
4244

4345
/// Updates the authorization header.
@@ -64,10 +66,10 @@ public actor FunctionsClient {
6466
options: FunctionInvokeOptions = .init(),
6567
decode: (Data, HTTPURLResponse) throws -> Response
6668
) async throws -> Response {
67-
let (data, response) = try await rawInvoke(
69+
let response = try await rawInvoke(
6870
functionName: functionName, invokeOptions: options
6971
)
70-
return try decode(data, response)
72+
return try decode(response.data, response.response)
7173
}
7274

7375
/// Invokes a function and decodes the response as a specific type.
@@ -102,34 +104,40 @@ public actor FunctionsClient {
102104
private func rawInvoke(
103105
functionName: String,
104106
invokeOptions: FunctionInvokeOptions
105-
) async throws -> (Data, HTTPURLResponse) {
106-
let url = url.appendingPathComponent(functionName)
107-
var urlRequest = URLRequest(url: url)
108-
urlRequest.allHTTPHeaderFields = invokeOptions.headers.merging(headers) { invoke, _ in invoke }
109-
urlRequest.httpMethod = (invokeOptions.method ?? .post).rawValue
110-
urlRequest.httpBody = invokeOptions.body
111-
112-
let (data, response) = try await fetch(urlRequest)
113-
114-
guard let httpResponse = response as? HTTPURLResponse else {
115-
throw URLError(.badServerResponse)
116-
}
107+
) async throws -> Response {
108+
let request = Request(
109+
path: functionName,
110+
method: .post,
111+
headers: invokeOptions.headers.merging(headers) { invoke, _ in invoke },
112+
body: invokeOptions.body
113+
)
114+
let response = try await http.fetch(request, baseURL: url)
117115

118-
guard 200 ..< 300 ~= httpResponse.statusCode else {
119-
throw FunctionsError.httpError(code: httpResponse.statusCode, data: data)
116+
guard 200 ..< 300 ~= response.statusCode else {
117+
throw FunctionsError.httpError(code: response.statusCode, data: response.data)
120118
}
121119

122-
let isRelayError = httpResponse.value(forHTTPHeaderField: "x-relay-error") == "true"
120+
let isRelayError = response.response.value(forHTTPHeaderField: "x-relay-error") == "true"
123121
if isRelayError {
124122
throw FunctionsError.relayError
125123
}
126124

127-
return (data, httpResponse)
125+
return response
128126
}
129-
130-
public func _invokeWithStream(
127+
128+
/// Invokes a function with streamed response.
129+
///
130+
/// Function MUST return a `text/event-stream` content type for this method to work.
131+
///
132+
/// - Parameters:
133+
/// - functionName: The name of the function to invoke.
134+
/// - invokeOptions: Options for invoking the function.
135+
/// - Returns: A stream of Data.
136+
///
137+
/// - Warning: Experimental method.
138+
public func _invoke(
131139
_ functionName: String,
132-
options invokeOptions: FunctionInvokeOptions
140+
options invokeOptions: FunctionInvokeOptions = .init()
133141
) -> AsyncThrowingStream<Data, any Error> {
134142
let (stream, continuation) = AsyncThrowingStream<Data, any Error>.makeStream()
135143
let delegate = StreamResponseDelegate(continuation: continuation)
@@ -142,7 +150,24 @@ public actor FunctionsClient {
142150
urlRequest.httpMethod = (invokeOptions.method ?? .post).rawValue
143151
urlRequest.httpBody = invokeOptions.body
144152

145-
let task = session.dataTask(with: urlRequest)
153+
let task = session.dataTask(with: urlRequest) { data, response, _ in
154+
guard let httpResponse = response as? HTTPURLResponse else {
155+
continuation.finish(throwing: URLError(.badServerResponse))
156+
return
157+
}
158+
159+
guard 200 ..< 300 ~= httpResponse.statusCode else {
160+
let error = FunctionsError.httpError(code: httpResponse.statusCode, data: data ?? Data())
161+
continuation.finish(throwing: error)
162+
return
163+
}
164+
165+
let isRelayError = httpResponse.value(forHTTPHeaderField: "x-relay-error") == "true"
166+
if isRelayError {
167+
continuation.finish(throwing: FunctionsError.relayError)
168+
}
169+
}
170+
146171
task.resume()
147172

148173
continuation.onTermination = { _ in

Sources/Supabase/SupabaseClient.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ public final class SupabaseClient: @unchecked Sendable {
7070
public private(set) lazy var functions = FunctionsClient(
7171
url: functionsURL,
7272
headers: defaultHeaders,
73+
logger: options.global.logger,
7374
fetch: fetchWithAuth
7475
)
7576

0 commit comments

Comments
 (0)