16
16
import struct Foundation. URL
17
17
import Logging
18
18
import NIOCore
19
+ import NIOHTTP1
19
20
20
21
@available ( macOS 12 . 0 , iOS 15 . 0 , watchOS 8 . 0 , tvOS 15 . 0 , * )
21
22
extension HTTPClient {
@@ -61,7 +62,7 @@ extension HTTPClient {
61
62
return try await self . followRedirect (
62
63
redirectURL: redirectURL,
63
64
redirectState: redirectState,
64
- request : preparedRequest,
65
+ previousRequest : preparedRequest,
65
66
response: response,
66
67
deadline: deadline,
67
68
logger: logger
@@ -73,27 +74,16 @@ extension HTTPClient {
73
74
private func followRedirect(
74
75
redirectURL: URL ,
75
76
redirectState: RedirectState ,
76
- request : HTTPClientRequest . Prepared ,
77
+ previousRequest : HTTPClientRequest . Prepared ,
77
78
response: HTTPClientResponse ,
78
79
deadline: NIODeadline ,
79
80
logger: Logger
80
81
) async throws -> HTTPClientResponse {
81
82
var redirectState = redirectState
82
83
try redirectState. redirect ( to: redirectURL. absoluteString)
83
- let ( method, headers, body) = transformRequestForRedirect (
84
- from: request. url,
85
- method: request. head. method,
86
- headers: request. head. headers,
87
- body: request. body,
88
- to: redirectURL,
89
- status: response. status
90
- )
91
- var newRequest = HTTPClientRequest ( url: redirectURL. absoluteString)
92
- newRequest. method = method
93
- newRequest. headers = headers
94
- newRequest. body = body
84
+
95
85
return try await self . executeAndFollowRedirectsIfNeeded (
96
- newRequest ,
86
+ previousRequest . followingRedirect ( to : redirectURL , status : response . status ) ,
97
87
deadline: deadline,
98
88
logger: logger,
99
89
redirectState: redirectState
@@ -105,44 +95,6 @@ extension HTTPClient {
105
95
deadline: NIODeadline ,
106
96
logger: Logger
107
97
) async throws -> HTTPClientResponse {
108
- /// There is currently no good way to asynchronously cancel an object that is initiated inside the `body` closure of `with*Continuation`.
109
- /// As a workaround we use `TransactionCancelHandler` which will take care of the race between instantiation of `Transaction`
110
- /// in the `body` closure and cancelation from the `onCancel` closure of `with*Continuation`.
111
- actor TransactionCancelHandler {
112
- private enum State {
113
- case initialised
114
- case register( Transaction )
115
- case cancelled
116
- }
117
-
118
- private var state : State = . initialised
119
-
120
- init ( ) { }
121
-
122
- func registerTransaction( _ transaction: Transaction ) {
123
- switch self . state {
124
- case . initialised:
125
- self . state = . register( transaction)
126
- case . cancelled:
127
- transaction. cancel ( )
128
- case . register:
129
- preconditionFailure ( " transaction already set " )
130
- }
131
- }
132
-
133
- func cancel( ) {
134
- switch self . state {
135
- case . register( let bag) :
136
- self . state = . cancelled
137
- bag. cancel ( )
138
- case . cancelled:
139
- break
140
- case . initialised:
141
- self . state = . cancelled
142
- }
143
- }
144
- }
145
-
146
98
let cancelHandler = TransactionCancelHandler ( )
147
99
148
100
return try await withTaskCancellationHandler ( operation: { ( ) async throws -> HTTPClientResponse in
@@ -170,4 +122,43 @@ extension HTTPClient {
170
122
}
171
123
}
172
124
125
+ /// There is currently no good way to asynchronously cancel an object that is initiated inside the `body` closure of `with*Continuation`.
126
+ /// As a workaround we use `TransactionCancelHandler` which will take care of the race between instantiation of `Transaction`
127
+ /// in the `body` closure and cancelation from the `onCancel` closure of `with*Continuation`.
128
+ @available ( macOS 12 . 0 , iOS 15 . 0 , watchOS 8 . 0 , tvOS 15 . 0 , * )
129
+ private actor TransactionCancelHandler {
130
+ private enum State {
131
+ case initialised
132
+ case register( Transaction )
133
+ case cancelled
134
+ }
135
+
136
+ private var state : State = . initialised
137
+
138
+ init ( ) { }
139
+
140
+ func registerTransaction( _ transaction: Transaction ) {
141
+ switch self . state {
142
+ case . initialised:
143
+ self . state = . register( transaction)
144
+ case . cancelled:
145
+ transaction. cancel ( )
146
+ case . register:
147
+ preconditionFailure ( " transaction already set " )
148
+ }
149
+ }
150
+
151
+ func cancel( ) {
152
+ switch self . state {
153
+ case . register( let bag) :
154
+ self . state = . cancelled
155
+ bag. cancel ( )
156
+ case . cancelled:
157
+ break
158
+ case . initialised:
159
+ self . state = . cancelled
160
+ }
161
+ }
162
+ }
163
+
173
164
#endif
0 commit comments