@@ -22,29 +22,17 @@ extension URLServer {
2222 process: @escaping ( Data ? , URLResponse ? , Error ? ) -> Result < R , ErrorType > ,
2323 completion: @escaping ( Result < R , ErrorType > ) -> Void
2424 ) -> URLSessionDataTask ? {
25- let requestId = UUID ( ) . uuidString
26- let startTime = Date ( )
27-
28- networkTracer? . logAndTrackRequest ( request: request, requestId: requestId)
25+ let tokens = networkObservers. map { RequestToken ( observer: $0, request: request) }
2926
3027 let task = urlSession. dataTask ( with: request) { data, response, error in
31- networkTracer? . logAndTrackResponse (
32- request: request,
33- response: response,
34- data: data,
35- requestId: requestId,
36- startTime: startTime
37- )
28+ tokens. forEach { $0. didReceiveResponse ( response, data) }
3829
3930 let result = process ( data, response, error)
4031
41- if case let . failure( error) = result {
42- networkTracer? . logAndTrackError (
43- request: request,
44- error: error,
45- requestId: requestId
46- )
32+ if case let . failure( apiError) = result {
33+ tokens. forEach { $0. didFail ( apiError) }
4734 }
35+
4836 completion ( result)
4937 }
5038 task. resume ( )
@@ -57,29 +45,15 @@ extension URLServer {
5745 process: @escaping ( Data ? , URLResponse ? , Error ? ) -> Result < R , ErrorType > ,
5846 completion: @escaping ( Result < R , ErrorType > ) -> Void
5947 ) -> URLSessionUploadTask ? {
60- let requestId = UUID ( ) . uuidString
61- let startTime = Date ( )
62-
63- networkTracer? . logAndTrackRequest ( request: request, requestId: requestId)
48+ let tokens = networkObservers. map { RequestToken ( observer: $0, request: request) }
6449
6550 let task = urlSession. uploadTask ( with: request, fromFile: file) { data, response, error in
66- networkTracer? . logAndTrackResponse (
67- request: request,
68- response: response,
69- data: data,
70- requestId: requestId,
71- startTime: startTime
72- )
51+ tokens. forEach { $0. didReceiveResponse ( response, data) }
7352
7453 let result = process ( data, response, error)
7554
76- // Log and track error if any
77- if case let . failure( error) = result {
78- networkTracer? . logAndTrackError (
79- request: request,
80- error: error,
81- requestId: requestId
82- )
55+ if case let . failure( apiError) = result {
56+ tokens. forEach { $0. didFail ( apiError) }
8357 }
8458
8559 completion ( result)
@@ -93,28 +67,15 @@ extension URLServer {
9367 process: @escaping ( URL ? , URLResponse ? , Error ? ) -> Result < URL , ErrorType > ,
9468 completion: @escaping ( Result < URL , ErrorType > ) -> Void
9569 ) -> URLSessionDownloadTask ? {
96- let requestId = UUID ( ) . uuidString
97- let startTime = Date ( )
98-
99- networkTracer? . logAndTrackRequest ( request: request, requestId: requestId)
70+ let tokens = networkObservers. map { RequestToken ( observer: $0, request: request) }
10071
10172 let task = urlSession. downloadTask ( with: request) { url, response, error in
102- networkTracer? . logAndTrackResponse (
103- request: request,
104- response: response,
105- data: nil ,
106- requestId: requestId,
107- startTime: startTime
108- )
73+ tokens. forEach { $0. didReceiveResponse ( response, nil ) }
10974
11075 let result = process ( url, response, error)
11176
112- if case let . failure( error) = result {
113- networkTracer? . logAndTrackError (
114- request: request,
115- error: error,
116- requestId: requestId
117- )
77+ if case let . failure( apiError) = result {
78+ tokens. forEach { $0. didFail ( apiError) }
11879 }
11980
12081 completion ( result)
@@ -146,3 +107,24 @@ extension URLServer {
146107 return . failure( error)
147108 }
148109}
110+
111+ // This hides the specific 'Context' type inside closures.
112+ private struct RequestToken : Sendable {
113+ let didReceiveResponse : @Sendable ( URLResponse ? , Data ? ) -> Void
114+ let didFail : @Sendable ( Error ) -> Void
115+
116+ // The generic 'T' captures the specific observer type and its associated Context
117+ init < T: NetworkObserver > ( observer: T , request: URLRequest ) {
118+ // We generate the context immediately upon initialization
119+ let context = observer. willSendRequest ( request)
120+
121+ // We capture the specific 'observer' and 'context' inside these closures
122+ self . didReceiveResponse = { [ weak observer] response, data in
123+ observer? . didReceiveResponse ( for: request, response: response, data: data, context: context)
124+ }
125+
126+ self . didFail = { [ weak observer] error in
127+ observer? . didFail ( request: request, error: error, context: context)
128+ }
129+ }
130+ }
0 commit comments