@@ -3,10 +3,12 @@ import Foundation
3
3
public struct Client {
4
4
public let url : URL
5
5
public var token : String ?
6
+ public var headers : [ HTTPHeader ]
6
7
7
- public init ( url: URL , token: String ? = nil ) {
8
+ public init ( url: URL , token: String ? = nil , headers : [ HTTPHeader ] = [ ] ) {
8
9
self . url = url
9
10
self . token = token
11
+ self . headers = headers
10
12
}
11
13
12
14
static let decoder : JSONDecoder = {
@@ -21,20 +23,17 @@ public struct Client {
21
23
return enc
22
24
} ( )
23
25
24
- func request < T : Encodable & Sendable > (
25
- _ path: String ,
26
+ private func doRequest (
27
+ path: String ,
26
28
method: HTTPMethod ,
27
- body: T ? = nil
29
+ body: Data ? = nil
28
30
) async throws ( ClientError) -> HTTPResponse {
29
31
let url = self . url. appendingPathComponent ( path)
30
32
var req = URLRequest ( url: url)
31
33
if let token { req. addValue ( token, forHTTPHeaderField: Headers . sessionToken) }
32
34
req. httpMethod = method. rawValue
33
- do {
34
- if let body { req. httpBody = try Client . encoder. encode ( body) }
35
- } catch {
36
- throw . encodeFailure
37
- }
35
+ for header in headers { req. addValue ( header. value, forHTTPHeaderField: header. header) }
36
+ req. httpBody = body
38
37
let data : Data
39
38
let resp : URLResponse
40
39
do {
@@ -48,25 +47,25 @@ public struct Client {
48
47
return HTTPResponse ( resp: httpResponse, data: data, req: req)
49
48
}
50
49
51
- func request(
50
+ func request< T : Encodable & Sendable > (
52
51
_ path: String ,
53
- method: HTTPMethod
52
+ method: HTTPMethod ,
53
+ body: T
54
54
) async throws ( ClientError) -> HTTPResponse {
55
- let url = self . url. appendingPathComponent ( path)
56
- var req = URLRequest ( url: url)
57
- if let token { req. addValue ( token, forHTTPHeaderField: Headers . sessionToken) }
58
- req. httpMethod = method. rawValue
59
- let data : Data
60
- let resp : URLResponse
55
+ let encodedBody : Data ?
61
56
do {
62
- ( data , resp ) = try await URLSession . shared . data ( for : req )
57
+ encodedBody = try Client . encoder . encode ( body )
63
58
} catch {
64
- throw . network ( error)
59
+ throw . encodeFailure ( error)
65
60
}
66
- guard let httpResponse = resp as? HTTPURLResponse else {
67
- throw . unexpectedResponse( data)
68
- }
69
- return HTTPResponse ( resp: httpResponse, data: data, req: req)
61
+ return try await doRequest ( path: path, method: method, body: encodedBody)
62
+ }
63
+
64
+ func request(
65
+ _ path: String ,
66
+ method: HTTPMethod
67
+ ) async throws ( ClientError) -> HTTPResponse {
68
+ return try await doRequest ( path: path, method: method)
70
69
}
71
70
72
71
func responseAsError( _ resp: HTTPResponse ) -> ClientError {
@@ -119,7 +118,7 @@ public enum ClientError: Error {
119
118
case api( APIError )
120
119
case network( any Error )
121
120
case unexpectedResponse( Data )
122
- case encodeFailure
121
+ case encodeFailure( any Error )
123
122
124
123
public var description : String {
125
124
switch self {
@@ -129,8 +128,8 @@ public enum ClientError: Error {
129
128
return error. localizedDescription
130
129
case let . unexpectedResponse( data) :
131
130
return " Unexpected or non HTTP response: \( data) "
132
- case . encodeFailure:
133
- return " Failed to encode body "
131
+ case let . encodeFailure( error ) :
132
+ return " Failed to encode body: \( error ) "
134
133
}
135
134
}
136
135
}
0 commit comments