@@ -16,9 +16,14 @@ import XCTestDynamicOverlay
1616/// responses.
1717public struct URLRoutingClient < Route> {
1818 var request : ( Route ) async throws -> ( Data , URLResponse )
19+ let decoder : JSONDecoder
1920
20- public init ( request: @escaping ( Route ) async throws -> ( Data , URLResponse ) ) {
21+ public init (
22+ request: @escaping ( Route ) async throws -> ( Data , URLResponse ) ,
23+ decoder: JSONDecoder = . init( )
24+ ) {
2125 self . request = request
26+ self . decoder = decoder
2227 }
2328
2429 /// Makes a request to a route.
@@ -32,11 +37,11 @@ public struct URLRoutingClient<Route> {
3237 public func request< Value: Decodable > (
3338 _ route: Route ,
3439 as type: Value . Type = Value . self,
35- decoder: JSONDecoder = . init ( )
40+ decoder: JSONDecoder ? = nil
3641 ) async throws -> ( value: Value , response: URLResponse ) {
3742 let ( data, response) = try await self . request ( route)
3843 do {
39- return ( try decoder. decode ( type, from: data) , response)
44+ return ( try ( decoder ?? self . decoder ) . decode ( type, from: data) , response)
4045 } catch {
4146 throw URLRoutingDecodingError ( bytes: data, response: response, underlyingError: error)
4247 }
@@ -60,39 +65,46 @@ extension URLRoutingClient {
6065 /// - session: A URL session.
6166 /// - Returns: A live API client that makes requests through a URL session.
6267 @available ( macOS 10 . 15 , iOS 13 , watchOS 6 , tvOS 13 , * )
63- public static func live< R: ParserPrinter > ( router: R , session: URLSession = . shared) -> Self
68+ public static func live< R: ParserPrinter > (
69+ router: R ,
70+ session: URLSession = . shared,
71+ decoder: JSONDecoder = . init( )
72+ ) -> Self
6473 where R. Input == URLRequestData , R. Output == Route {
65- Self { route in
66- let request = try router. request ( for: route)
74+ Self . init (
75+ request: { route in
76+ let request = try router. request ( for: route)
6777
68- #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
69- if #available( macOS 12 , iOS 15 , tvOS 15 , watchOS 8 , * ) {
70- return try await session. data ( for: request)
71- }
72- #endif
73- var dataTask : URLSessionDataTask ?
74- let cancel : ( ) -> Void = { dataTask? . cancel ( ) }
78+ #if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
79+ if #available( macOS 12 , iOS 15 , tvOS 15 , watchOS 8 , * ) {
80+ return try await session. data ( for: request)
81+ }
82+ #endif
83+ var dataTask : URLSessionDataTask ?
84+ let cancel : ( ) -> Void = { dataTask? . cancel ( ) }
7585
76- return try await withTaskCancellationHandler (
77- handler: { cancel ( ) } ,
78- operation: {
79- try await withCheckedThrowingContinuation { continuation in
80- dataTask = session. dataTask ( with: request) { data, response, error in
81- guard
82- let data = data,
83- let response = response
84- else {
85- continuation. resume ( throwing: error ?? URLError ( . badServerResponse) )
86- return
87- }
86+ return try await withTaskCancellationHandler (
87+ handler: { cancel ( ) } ,
88+ operation: {
89+ try await withCheckedThrowingContinuation { continuation in
90+ dataTask = session. dataTask ( with: request) { data, response, error in
91+ guard
92+ let data = data,
93+ let response = response
94+ else {
95+ continuation. resume ( throwing: error ?? URLError ( . badServerResponse) )
96+ return
97+ }
8898
89- continuation. resume ( returning: ( data, response) )
99+ continuation. resume ( returning: ( data, response) )
100+ }
101+ dataTask? . resume ( )
90102 }
91- dataTask? . resume ( )
92103 }
93- }
94- )
95- }
104+ )
105+ } ,
106+ decoder: decoder
107+ )
96108 }
97109}
98110
0 commit comments