@@ -26,6 +26,10 @@ extension HTTPClient {
26
26
/// - request: HTTP request to execute.
27
27
/// - deadline: Point in time by which the request must complete.
28
28
/// - logger: The logger to use for this request.
29
+ ///
30
+ /// - warning: This method may violates Structured Concurrency because it returns a `HTTPClientResponse` that needs to be
31
+ /// streamed by the user. This means the request, the connection and other resources are still alive when the request returns.
32
+ ///
29
33
/// - Returns: The response to the request. Note that the `body` of the response may not yet have been fully received.
30
34
public func execute(
31
35
_ request: HTTPClientRequest ,
@@ -51,6 +55,10 @@ extension HTTPClient {
51
55
/// - request: HTTP request to execute.
52
56
/// - timeout: time the the request has to complete.
53
57
/// - logger: The logger to use for this request.
58
+ ///
59
+ /// - warning: This method may violates Structured Concurrency because it returns a `HTTPClientResponse` that needs to be
60
+ /// streamed by the user. This means the request, the connection and other resources are still alive when the request returns.
61
+ ///
54
62
/// - Returns: The response to the request. Note that the `body` of the response may not yet have been fully received.
55
63
public func execute(
56
64
_ request: HTTPClientRequest ,
@@ -67,6 +75,8 @@ extension HTTPClient {
67
75
68
76
@available ( macOS 10 . 15 , iOS 13 . 0 , watchOS 6 . 0 , tvOS 13 . 0 , * )
69
77
extension HTTPClient {
78
+ /// - warning: This method may violates Structured Concurrency because it returns a `HTTPClientResponse` that needs to be
79
+ /// streamed by the user. This means the request, the connection and other resources are still alive when the request returns.
70
80
private func executeAndFollowRedirectsIfNeeded(
71
81
_ request: HTTPClientRequest ,
72
82
deadline: NIODeadline ,
@@ -75,11 +85,29 @@ extension HTTPClient {
75
85
) async throws -> HTTPClientResponse {
76
86
var currentRequest = request
77
87
var currentRedirectState = redirectState
88
+ var history : [ HTTPClientRequestResponse ] = [ ]
78
89
79
90
// this loop is there to follow potential redirects
80
91
while true {
81
92
let preparedRequest = try HTTPClientRequest . Prepared ( currentRequest, dnsOverride: configuration. dnsOverride)
82
- let response = try await self . executeCancellable ( preparedRequest, deadline: deadline, logger: logger)
93
+ let response = try await {
94
+ var response = try await self . executeCancellable ( preparedRequest, deadline: deadline, logger: logger)
95
+
96
+ history. append (
97
+ . init(
98
+ request: currentRequest,
99
+ responseHead: . init(
100
+ version: response. version,
101
+ status: response. status,
102
+ headers: response. headers
103
+ )
104
+ )
105
+ )
106
+
107
+ response. history = history
108
+
109
+ return response
110
+ } ( )
83
111
84
112
guard var redirectState = currentRedirectState else {
85
113
// a `nil` redirectState means we should not follow redirects
@@ -116,6 +144,8 @@ extension HTTPClient {
116
144
}
117
145
}
118
146
147
+ /// - warning: This method may violates Structured Concurrency because it returns a `HTTPClientResponse` that needs to be
148
+ /// streamed by the user. This means the request, the connection and other resources are still alive when the request returns.
119
149
private func executeCancellable(
120
150
_ request: HTTPClientRequest . Prepared ,
121
151
deadline: NIODeadline ,
0 commit comments