@@ -109,16 +109,9 @@ extension HTTPClient {
109
109
/// Request-specific TLS configuration, defaults to no request-specific TLS configuration.
110
110
public var tlsConfiguration : TLSConfiguration ?
111
111
112
- struct RedirectState {
113
- var count : Int
114
- var visited : Set < URL > ?
115
- }
116
-
117
112
/// Parsed, validated and deconstructed URL.
118
113
let deconstructedURL : DeconstructedURL
119
114
120
- var redirectState : RedirectState ?
121
-
122
115
/// Create HTTP request.
123
116
///
124
117
/// - parameters:
@@ -190,7 +183,6 @@ extension HTTPClient {
190
183
public init ( url: URL , method: HTTPMethod = . GET, headers: HTTPHeaders = HTTPHeaders ( ) , body: Body ? = nil , tlsConfiguration: TLSConfiguration ? ) throws {
191
184
self . deconstructedURL = try DeconstructedURL ( url: url)
192
185
193
- self . redirectState = nil
194
186
self . url = url
195
187
self . method = method
196
188
self . headers = headers
@@ -642,87 +634,42 @@ internal struct TaskCancelEvent {}
642
634
643
635
internal struct RedirectHandler < ResponseType> {
644
636
let request : HTTPClient . Request
645
- let execute : ( HTTPClient . Request ) -> HTTPClient . Task < ResponseType >
646
-
647
- func redirectTarget( status: HTTPResponseStatus , headers: HTTPHeaders ) -> URL ? {
648
- switch status {
649
- case . movedPermanently, . found, . seeOther, . notModified, . useProxy, . temporaryRedirect, . permanentRedirect:
650
- break
651
- default :
652
- return nil
653
- }
654
-
655
- guard let location = headers. first ( name: " Location " ) else {
656
- return nil
657
- }
658
-
659
- guard let url = URL ( string: location, relativeTo: request. url) else {
660
- return nil
661
- }
662
-
663
- guard self . request. deconstructedURL. scheme. supportsRedirects ( to: url. scheme) else {
664
- return nil
665
- }
666
-
667
- if url. isFileURL {
668
- return nil
669
- }
670
-
671
- return url. absoluteURL
637
+ let redirectState : RedirectState
638
+ let execute : ( HTTPClient . Request , RedirectState ) -> HTTPClient . Task < ResponseType >
639
+
640
+ func redirectTarget( status: HTTPResponseStatus , responseHeaders: HTTPHeaders ) -> URL ? {
641
+ responseHeaders. extractRedirectTarget (
642
+ status: status,
643
+ originalURL: self . request. url,
644
+ originalScheme: self . request. deconstructedURL. scheme
645
+ )
672
646
}
673
647
674
- func redirect( status: HTTPResponseStatus , to redirectURL: URL , promise: EventLoopPromise < ResponseType > ) {
675
- var nextState : HTTPClient . Request . RedirectState ?
676
- if var state = request. redirectState {
677
- guard state. count > 0 else {
678
- return promise. fail ( HTTPClientError . redirectLimitReached)
679
- }
680
-
681
- state. count -= 1
682
-
683
- if var visited = state. visited {
684
- guard !visited. contains ( redirectURL) else {
685
- return promise. fail ( HTTPClientError . redirectCycleDetected)
686
- }
687
-
688
- visited. insert ( redirectURL)
689
- state. visited = visited
690
- }
691
-
692
- nextState = state
693
- }
694
-
695
- let originalRequest = self . request
696
-
697
- var convertToGet = false
698
- if status == . seeOther, self . request. method != . HEAD {
699
- convertToGet = true
700
- } else if status == . movedPermanently || status == . found, self . request. method == . POST {
701
- convertToGet = true
702
- }
703
-
704
- var method = originalRequest. method
705
- var headers = originalRequest. headers
706
- var body = originalRequest. body
707
-
708
- if convertToGet {
709
- method = . GET
710
- body = nil
711
- headers. remove ( name: " Content-Length " )
712
- headers. remove ( name: " Content-Type " )
713
- }
714
-
715
- if !originalRequest. url. hasTheSameOrigin ( as: redirectURL) {
716
- headers. remove ( name: " Origin " )
717
- headers. remove ( name: " Cookie " )
718
- headers. remove ( name: " Authorization " )
719
- headers. remove ( name: " Proxy-Authorization " )
720
- }
721
-
648
+ func redirect(
649
+ status: HTTPResponseStatus ,
650
+ to redirectURL: URL ,
651
+ promise: EventLoopPromise < ResponseType >
652
+ ) {
722
653
do {
723
- var newRequest = try HTTPClient . Request ( url: redirectURL, method: method, headers: headers, body: body)
724
- newRequest. redirectState = nextState
725
- self . execute ( newRequest) . futureResult. whenComplete { result in
654
+ var redirectState = self . redirectState
655
+ try redirectState. redirect ( to: redirectURL. absoluteString)
656
+
657
+ let ( method, headers, body) = transformRequestForRedirect (
658
+ from: request. url,
659
+ method: self . request. method,
660
+ headers: self . request. headers,
661
+ body: self . request. body,
662
+ to: redirectURL,
663
+ status: status
664
+ )
665
+
666
+ let newRequest = try HTTPClient . Request (
667
+ url: redirectURL,
668
+ method: method,
669
+ headers: headers,
670
+ body: body
671
+ )
672
+ self . execute ( newRequest, redirectState) . futureResult. whenComplete { result in
726
673
promise. futureResult. eventLoop. execute {
727
674
promise. completeWith ( result)
728
675
}
0 commit comments