@@ -24,9 +24,8 @@ public struct ErrorResponse: Codable, Error {
24
24
//
25
25
// MARK: API Client
26
26
//
27
- @available ( macOS 12 . 0 , * )
28
- @available ( iOS 15 . 0 , * )
29
- public class APIClient {
27
+ @available ( macOS 12 . 0 , iOS 15 . 0 , watchOS 8 . 0 , tvOS 15 . 0 , * )
28
+ public final class APIClient {
30
29
typealias HTTPResponse = ( data: Data , response: HTTPURLResponse )
31
30
32
31
private var username : String ?
@@ -41,26 +40,49 @@ public class APIClient {
41
40
case json = " application/json "
42
41
}
43
42
43
+ /// Initializes the API client with optional username and password.
44
+ /// - Parameters:
45
+ /// - username: The username for basic authentication.
46
+ /// - password: The password for basic authentication.
44
47
public init ( username: String ? = nil , password: String ? = nil ) {
45
48
self . username = username
46
49
self . password = password
47
50
}
48
51
52
+ /// Retrieves the cookies stored for the VRChat API domain.
53
+ /// - Returns: An array of `HTTPCookie` objects.
49
54
public var cookies : [ HTTPCookie ] {
50
- HTTPCookieStorage . shared. cookies ( for: domainUrl) ?? [ ]
55
+ guard let cookies = HTTPCookieStorage . shared. cookies ( for: domainUrl) else { return [ ] }
56
+ return cookies
51
57
}
52
58
59
+ /// Deletes all cookies stored for the VRChat API domain.
53
60
public func deleteCookies( ) {
54
- for cookie in cookies {
55
- HTTPCookieStorage . shared. deleteCookie ( cookie)
56
- }
61
+ cookies. forEach { HTTPCookieStorage . shared. deleteCookie ( $0) }
57
62
}
58
63
59
- var encodedAuthorization : String {
60
- " Basic \( ( ( username ?? " " ) + " : " + ( password ?? " " ) ) . data ( using: . utf8) !. base64EncodedString ( ) ) "
64
+ /// Encodes the given username and password into a Basic Authentication token.
65
+ /// - Parameters:
66
+ /// - username: The username for authentication.
67
+ /// - password: The password associated with the username.
68
+ /// - Returns: A Basic Authentication token string.
69
+ /// - Throws: `VRCKitError.unexpectedError` if the username and password cannot be converted to UTF-8 data.
70
+ func encodeAuthorization( _ username: String , _ password: String ) throws -> String {
71
+ let authString = " \( username) : \( password) "
72
+ guard let payload = authString. data ( using: . utf8) else {
73
+ throw VRCKitError . unexpectedError
74
+ }
75
+ return " Basic \( payload. base64EncodedString ( ) ) "
61
76
}
62
77
63
- /// Request to API
78
+ /// Sends a request to the API.
79
+ /// - Parameters:
80
+ /// - url: The URL for the request.
81
+ /// - httpMethod: The HTTP method to use for the request.
82
+ /// - basic: Whether to include basic authorization.
83
+ /// - httpBody: The HTTP body to include in the request.
84
+ /// - Returns: A tuple containing the data and the HTTP response.
85
+ /// - Throws: `VRCKitError` if an error occurs during the request.
64
86
func request(
65
87
url: URL ,
66
88
httpMethod: HttpMethod ,
@@ -70,15 +92,16 @@ public class APIClient {
70
92
var request = URLRequest ( url: url)
71
93
request. httpMethod = httpMethod. description
72
94
73
- // Authorization
74
- if basic {
75
- request. addValue ( encodedAuthorization, forHTTPHeaderField: " Authorization " )
95
+ // Add authorization header if required.
96
+ if basic, let username = username, let password = password {
97
+ let authorizationHeader = try encodeAuthorization ( username, password)
98
+ request. addValue ( authorizationHeader, forHTTPHeaderField: " Authorization " )
76
99
}
77
100
78
- // Cookie
101
+ // Add cookies to the request headers.
79
102
request. allHTTPHeaderFields = HTTPCookie . requestHeaderFields ( with: cookies)
80
103
81
- // HTTP Body
104
+ // Add HTTP body and content type if body is provided.
82
105
if let httpBody = httpBody {
83
106
request. addValue ( ContentType . json. rawValue, forHTTPHeaderField: " Content-Type " )
84
107
request. httpBody = httpBody
@@ -92,8 +115,7 @@ public class APIClient {
92
115
}
93
116
}
94
117
95
- @available ( macOS 12 . 0 , * )
96
- @available ( iOS 15 . 0 , * )
118
+ @available ( macOS 12 . 0 , iOS 15 . 0 , watchOS 8 . 0 , tvOS 15 . 0 , * )
97
119
extension APIClient . HttpMethod : CustomStringConvertible {
98
120
var description : String {
99
121
self . rawValue. uppercased ( )
0 commit comments