-
Notifications
You must be signed in to change notification settings - Fork 29
Expand file tree
/
Copy pathClient+Request.swift
More file actions
87 lines (77 loc) · 3.19 KB
/
Client+Request.swift
File metadata and controls
87 lines (77 loc) · 3.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import Foundation
extension HTTPURLResponse {
/// Returns `true` if `statusCode` is in range 200...299.
/// Otherwise `false`.
var isSuccessful: Bool {
200 ... 299 ~= statusCode
}
}
extension Client {
func sendRequest(to urlString: String, input: Data?, queryParams: [String: Any]? = nil, options: RunOptions) async throws -> Data {
guard var url = URL(string: urlString) else {
throw FalError.invalidUrl(url: urlString)
}
if let queryParams,
!queryParams.isEmpty,
var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false)
{
urlComponents.queryItems = queryParams.map {
URLQueryItem(name: $0.key, value: String(describing: $0.value))
}
url = urlComponents.url ?? url
}
let targetUrl = url
if let requestProxy = config.requestProxy {
guard let proxyUrl = URL(string: requestProxy) else {
throw FalError.invalidUrl(url: requestProxy)
}
url = proxyUrl
}
var request = URLRequest(url: url)
if let header = config.customHeaders {
for (key, value) in header {
request.setValue(value, forHTTPHeaderField: key)
}
}
request.httpMethod = options.httpMethod.rawValue.uppercased()
request.setValue("application/json", forHTTPHeaderField: "accept")
request.setValue("application/json", forHTTPHeaderField: "content-type")
request.setValue(userAgent, forHTTPHeaderField: "user-agent")
// setup credentials if available
let credentials = config.credentials.description
if !credentials.isEmpty {
request.setValue("Key \(config.credentials.description)", forHTTPHeaderField: "authorization")
}
// setup the request proxy if available
if config.requestProxy != nil {
request.setValue(targetUrl.absoluteString, forHTTPHeaderField: "x-fal-target-url")
}
if input != nil, options.httpMethod != .get {
request.httpBody = input
}
let (data, response) = try await URLSession.shared.data(for: request)
try checkResponseStatus(for: response, withData: data)
return data
}
func checkResponseStatus(for response: URLResponse, withData data: Data) throws {
guard response is HTTPURLResponse else {
throw FalError.invalidResultFormat
}
if let httpResponse = response as? HTTPURLResponse, !httpResponse.isSuccessful {
let errorPayload = try? Payload.create(fromJSON: data)
let statusCode = httpResponse.statusCode
let message = errorPayload?["detail"].stringValue
?? errorPayload?.stringValue
?? HTTPURLResponse.localizedString(forStatusCode: statusCode)
throw FalError.httpError(
status: statusCode,
message: message,
payload: errorPayload
)
}
}
var userAgent: String {
let osVersion = ProcessInfo.processInfo.operatingSystemVersionString
return "fal.ai/swift-client 0.1.0 - \(osVersion)"
}
}