@@ -86,16 +86,11 @@ async Task<HttpResponse> ExecuteRequestAsync(RestRequest request, CancellationTo
8686 throw new ObjectDisposedException ( nameof ( RestClient ) ) ;
8787 }
8888
89- using var requestContent = new RequestContent ( this , request ) ;
90-
9189 var authenticator = request . Authenticator ?? Options . Authenticator ;
9290 if ( authenticator != null ) await authenticator . Authenticate ( this , request ) . ConfigureAwait ( false ) ;
9391
9492 var httpMethod = AsHttpMethod ( request . Method ) ;
9593 var url = this . BuildUri ( request ) ;
96- var message = new HttpRequestMessage ( httpMethod , url ) { Content = requestContent . BuildContent ( ) } ;
97- message . Headers . Host = Options . BaseHost ;
98- message . Headers . CacheControl = Options . CachePolicy ;
9994
10095 using var timeoutCts = new CancellationTokenSource ( request . Timeout > 0 ? request . Timeout : int . MaxValue ) ;
10196 using var cts = CancellationTokenSource . CreateLinkedTokenSource ( timeoutCts . Token , cancellationToken ) ;
@@ -116,11 +111,50 @@ async Task<HttpResponse> ExecuteRequestAsync(RestRequest request, CancellationTo
116111 headers . AddCookieHeaders ( Options . CookieContainer , url ) ;
117112 }
118113
119- message . AddHeaders ( headers ) ;
114+ HttpResponseMessage ? responseMessage ;
115+
116+ while ( true ) {
117+ using var requestContent = new RequestContent ( this , request ) ;
118+ using var message = PrepareRequestMessage ( httpMethod , url , requestContent , headers ) ;
120119
121- if ( request . OnBeforeRequest != null ) await request . OnBeforeRequest ( message ) . ConfigureAwait ( false ) ;
120+ if ( request . OnBeforeRequest != null ) await request . OnBeforeRequest ( message ) . ConfigureAwait ( false ) ;
121+
122+ responseMessage = await HttpClient . SendAsync ( message , request . CompletionOption , ct ) . ConfigureAwait ( false ) ;
123+
124+ if ( request . OnAfterRequest != null ) await request . OnAfterRequest ( responseMessage ) . ConfigureAwait ( false ) ;
125+
126+ if ( ! IsRedirect ( responseMessage ) ) {
127+ // || !Options.FollowRedirects) {
128+ break ;
129+ }
130+
131+ var location = responseMessage . Headers . Location ;
132+
133+ if ( location == null ) {
134+ break ;
135+ }
136+
137+ if ( ! location . IsAbsoluteUri ) {
138+ location = new Uri ( url , location ) ;
139+ }
140+
141+ if ( responseMessage . StatusCode == HttpStatusCode . RedirectMethod ) {
142+ httpMethod = HttpMethod . Get ;
143+ }
122144
123- var responseMessage = await HttpClient . SendAsync ( message , request . CompletionOption , ct ) . ConfigureAwait ( false ) ;
145+ url = location ;
146+
147+ if ( responseMessage . Headers . TryGetValues ( KnownHeaders . SetCookie , out var ch ) ) {
148+ foreach ( var header in ch ) {
149+ try {
150+ cookieContainer . SetCookies ( url , header ) ;
151+ }
152+ catch ( CookieException ) {
153+ // Do not fail request if we cannot parse a cookie
154+ }
155+ }
156+ }
157+ }
124158
125159 // Parse all the cookies from the response and update the cookie jar with cookies
126160 if ( responseMessage . Headers . TryGetValues ( KnownHeaders . SetCookie , out var cookiesHeader ) ) {
@@ -134,15 +168,34 @@ async Task<HttpResponse> ExecuteRequestAsync(RestRequest request, CancellationTo
134168 }
135169 }
136170
137- if ( request . OnAfterRequest != null ) await request . OnAfterRequest ( responseMessage ) . ConfigureAwait ( false ) ;
138-
139171 return new HttpResponse ( responseMessage , url , cookieContainer , null , timeoutCts . Token ) ;
140172 }
141173 catch ( Exception ex ) {
142174 return new HttpResponse ( null , url , null , ex , timeoutCts . Token ) ;
143175 }
144176 }
145177
178+ HttpRequestMessage PrepareRequestMessage ( HttpMethod httpMethod , Uri url , RequestContent requestContent , RequestHeaders headers ) {
179+ var message = new HttpRequestMessage ( httpMethod , url ) { Content = requestContent . BuildContent ( ) } ;
180+ message . Headers . Host = Options . BaseHost ;
181+ message . Headers . CacheControl = Options . CachePolicy ;
182+ message . AddHeaders ( headers ) ;
183+
184+ return message ;
185+ }
186+
187+ static bool IsRedirect ( HttpResponseMessage responseMessage )
188+ => responseMessage . StatusCode switch {
189+ HttpStatusCode . MovedPermanently => true ,
190+ HttpStatusCode . SeeOther => true ,
191+ HttpStatusCode . TemporaryRedirect => true ,
192+ HttpStatusCode . Redirect => true ,
193+ #if NET
194+ HttpStatusCode . PermanentRedirect => true,
195+ #endif
196+ _ => false
197+ } ;
198+
146199 record HttpResponse (
147200 HttpResponseMessage ? ResponseMessage ,
148201 Uri Url ,
0 commit comments