@@ -86,16 +86,11 @@ async Task<HttpResponse> ExecuteRequestAsync(RestRequest request, CancellationTo
86
86
throw new ObjectDisposedException ( nameof ( RestClient ) ) ;
87
87
}
88
88
89
- using var requestContent = new RequestContent ( this , request ) ;
90
-
91
89
var authenticator = request . Authenticator ?? Options . Authenticator ;
92
90
if ( authenticator != null ) await authenticator . Authenticate ( this , request ) . ConfigureAwait ( false ) ;
93
91
94
92
var httpMethod = AsHttpMethod ( request . Method ) ;
95
93
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 ;
99
94
100
95
using var timeoutCts = new CancellationTokenSource ( request . Timeout > 0 ? request . Timeout : int . MaxValue ) ;
101
96
using var cts = CancellationTokenSource . CreateLinkedTokenSource ( timeoutCts . Token , cancellationToken ) ;
@@ -116,11 +111,50 @@ async Task<HttpResponse> ExecuteRequestAsync(RestRequest request, CancellationTo
116
111
headers . AddCookieHeaders ( Options . CookieContainer , url ) ;
117
112
}
118
113
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 ) ;
120
119
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
+ }
122
144
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
+ }
124
158
125
159
// Parse all the cookies from the response and update the cookie jar with cookies
126
160
if ( responseMessage . Headers . TryGetValues ( KnownHeaders . SetCookie , out var cookiesHeader ) ) {
@@ -134,15 +168,34 @@ async Task<HttpResponse> ExecuteRequestAsync(RestRequest request, CancellationTo
134
168
}
135
169
}
136
170
137
- if ( request . OnAfterRequest != null ) await request . OnAfterRequest ( responseMessage ) . ConfigureAwait ( false ) ;
138
-
139
171
return new HttpResponse ( responseMessage , url , cookieContainer , null , timeoutCts . Token ) ;
140
172
}
141
173
catch ( Exception ex ) {
142
174
return new HttpResponse ( null , url , null , ex , timeoutCts . Token ) ;
143
175
}
144
176
}
145
177
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
+
146
199
record HttpResponse (
147
200
HttpResponseMessage ? ResponseMessage ,
148
201
Uri Url ,
0 commit comments