Skip to content

Commit abc6761

Browse files
committed
Fixes for Interceptor tests.
1 parent 29f21d9 commit abc6761

File tree

7 files changed

+82
-13
lines changed

7 files changed

+82
-13
lines changed

src/RestSharp/Options/RestClientOptions.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,12 @@ public RestClientOptions(string baseUrl) : this(new Uri(Ensure.NotEmptyString(ba
5050
/// <summary>
5151
/// Custom configuration for the underlying <seealso cref="HttpMessageHandler"/>
5252
/// </summary>
53+
/// <remarks>
54+
/// With the addition of all redirection processing being implemented directly by <see cref="RestClient"/>
55+
/// please do not alter the <see cref="System.Net.Http.HttpClientHandler.AllowAutoRedirect""/> from its default supplied by RestClient.
56+
/// If you set <see cref="System.Net.Http.HttpClientHandler.AllowAutoRedirect""/> to true, then redirection cookie
57+
/// processing improvements in RestClient will be skipped since <see cref="System.Net.Http.HttpClient"/> will hide the details from us.
58+
/// </remarks>
5359
public Func<HttpMessageHandler, HttpMessageHandler>? ConfigureMessageHandler { get; set; }
5460

5561
/// <summary>
@@ -139,6 +145,9 @@ public RestClientOptions(string baseUrl) : this(new Uri(Ensure.NotEmptyString(ba
139145
/// <summary>
140146
/// Instruct the client to follow redirects. Default is true.
141147
/// </summary>
148+
/// <remarks>
149+
/// Note: This now delegates the property implementation to <see cref="RestClientRedirectionOptions"/>.
150+
/// </remarks>
142151
public bool FollowRedirects {
143152
get {
144153
return RedirectOptions.FollowRedirects;

src/RestSharp/Options/RestClientRedirectionOptions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ public class RestClientRedirectionOptions {
100100

101101
/// <summary>
102102
/// HttpStatusCodes that trigger redirect processing. Defaults to MovedPermanently (301),
103-
/// SeeOther (303),
103+
/// SeeOther/RedirectMethod (303),
104104
/// TemporaryRedirect (307),
105105
/// Redirect (302),
106106
/// PermanentRedirect (308)

src/RestSharp/RestClient.Async.cs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,10 @@ async Task<HttpResponse> ExecuteRequestAsync(RestRequest request, CancellationTo
9696
var ct = cts.Token;
9797

9898
HttpResponseMessage? responseMessage = null;
99+
// Make sure we have a cookie container if not provided in the request
99100
var cookieContainer = request.CookieContainer ??= new CookieContainer();
100101

101102
try {
102-
// Make sure we have a cookie container if not provided in the request
103-
104103
var headers = new RequestHeaders()
105104
.AddHeaders(request.Parameters)
106105
.AddHeaders(DefaultParameters)
@@ -109,6 +108,7 @@ async Task<HttpResponse> ExecuteRequestAsync(RestRequest request, CancellationTo
109108
.AddCookieHeaders(url, Options.CookieContainer);
110109

111110
bool foundCookies = false;
111+
bool firstAttempt = true;
112112

113113
do {
114114
using var requestContent = new RequestContent(this, request);
@@ -121,14 +121,19 @@ async Task<HttpResponse> ExecuteRequestAsync(RestRequest request, CancellationTo
121121
}
122122
using var message = PrepareRequestMessage(httpMethod, url, content, headers);
123123

124-
if (request.OnBeforeRequest != null) await request.OnBeforeRequest(message).ConfigureAwait(false);
125-
await OnBeforeRequest(message).ConfigureAwait(false);
124+
if (firstAttempt) {
125+
firstAttempt = false;
126+
try {
127+
if (request.OnBeforeRequest != null) await request.OnBeforeRequest(message).ConfigureAwait(false);
128+
await OnBeforeRequest(message).ConfigureAwait(false);
129+
}
130+
catch (Exception e) {
131+
throw new RestClientInternalException("RestClient.ExecuteRequestAsync OnBeforeRequest threw an exception: ", e);
132+
}
133+
}
126134

127135
responseMessage = await HttpClient.SendAsync(message, request.CompletionOption, ct).ConfigureAwait(false);
128136

129-
if (request.OnAfterRequest != null) await request.OnAfterRequest(responseMessage).ConfigureAwait(false);
130-
await OnAfterRequest(responseMessage).ConfigureAwait(false);
131-
132137
if (!IsRedirect(Options.RedirectOptions, responseMessage)) {
133138
break;
134139
}
@@ -187,6 +192,10 @@ async Task<HttpResponse> ExecuteRequestAsync(RestRequest request, CancellationTo
187192
httpMethod = HttpMethod.Get;
188193
if (!Options.RedirectOptions.ForceForwardBody) {
189194
// HttpClient RedirectHandler sets request.Content to null here:
195+
// TODO: I don't think is quite correct yet..
196+
// We don't necessarily want to modify the original request, but..
197+
// is there a way to clone it properly and then clear out what we don't
198+
// care about?
190199
message.Content = null;
191200
// HttpClient Redirect handler also foribly removes
192201
// a Transfer-Encoding of chunked in this case.
@@ -218,6 +227,9 @@ async Task<HttpResponse> ExecuteRequestAsync(RestRequest request, CancellationTo
218227
Options.CookieContainer?.AddCookies(url, cookiesHeader2);
219228
}
220229
}
230+
catch (RestClientInternalException e) {
231+
throw e.InnerException!;
232+
}
221233
catch (Exception ex) {
222234
return new HttpResponse(null, url, null, ex, timeoutCts.Token);
223235
}
@@ -310,7 +322,7 @@ HttpRequestMessage PrepareRequestMessage(HttpMethod httpMethod, Uri url, HttpCon
310322
}
311323

312324
static bool IsRedirect(RestClientRedirectionOptions options, HttpResponseMessage responseMessage) {
313-
return options.RedirectStatusCodes.Contains(responseMessage.StatusCode);
325+
return options.FollowRedirects && options.RedirectStatusCodes.Contains(responseMessage.StatusCode);
314326
}
315327

316328
record HttpResponse(

src/RestSharp/RestClient.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,9 @@ static void ConfigureHttpMessageHandler(HttpClientHandler handler, ReadOnlyRestC
249249
#if NET
250250
}
251251
#endif
252-
handler.AllowAutoRedirect = options.FollowRedirects;
252+
// ExecuteAsync and RedirectionOptions now own
253+
// redirection processing:
254+
handler.AllowAutoRedirect = false;
253255

254256
#if NET
255257
if (!OperatingSystem.IsBrowser() && !OperatingSystem.IsIOS() && !OperatingSystem.IsTvOS()) {
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Runtime.Serialization;
4+
using System.Text;
5+
6+
namespace RestSharp;
7+
8+
/// <summary>
9+
/// This exception SHOULD only be used for catching and throwing internal
10+
/// exceptions within RestSharp.
11+
/// </summary>
12+
[Serializable]
13+
public class RestClientInternalException : Exception {
14+
public RestClientInternalException() {
15+
}
16+
17+
public RestClientInternalException(string? message, Exception? innerException) : base(message, innerException) {
18+
}
19+
20+
protected RestClientInternalException(SerializationInfo info, StreamingContext context) : base(info, context) {
21+
}
22+
}

test/RestSharp.Tests.Integrated/RedirectTests.cs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public class RedirectTests {
2525

2626
public RedirectTests(TestServerFixture fixture) {
2727
var options = new RestClientOptions(fixture.Server.Url) {
28-
FollowRedirects = false
28+
FollowRedirects = true
2929
};
3030
_client = new RestClient(options);
3131
_host = _client.Options.BaseUrl!.Host;
@@ -99,6 +99,30 @@ public async Task Can_Perform_PUT_Async_With_RedirectionResponse_Cookies() {
9999
response.StatusCode.Should().Be(HttpStatusCode.MethodNotAllowed);
100100
}
101101

102+
// Needed tests:
103+
//Test: ForwardHeaders = false
104+
//Test: ForwardHeaders = true (default) might not need separate test
105+
//Test: ForwardAuthorization = true
106+
//Test: ForwardAuthorization = false (default) probably need separate test
107+
//Test: ForwardCookies = true (might already have test)
108+
//Test: ForwardCookies = false
109+
//Test: ForwardBody = true (default, might not need test)
110+
//Test: ForwardBody = false
111+
//Test: ForceForwardBody = false (default, might not need test)
112+
//Test: ForwardQuery = true (default, might not need test)
113+
//Test: ForwardQuery = false
114+
//Test: MaxRedirects
115+
//Test: ForwardFragment = true
116+
//Test: ForwardFragment = false
117+
//Test: AllowRedirectMethodStatusCodeToAlterVerb = true (default, might not need test)
118+
//Test: AllowRedirectMethodStatusCodeToAlterVerb = false
119+
//Test: Altered Redirect Status Codes list
120+
//Test: FollowRedirects = false
121+
// Problem: Need secure test server:
122+
//Test: FollowRedirectsToInsecure = true
123+
//Test: FollowRedirectsToInsecure = false
124+
125+
102126
class Response {
103127
public string? Message { get; set; }
104128
}

test/RestSharp.Tests/OptionsTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ namespace RestSharp.Tests;
22

33
public class OptionsTests {
44
[Fact]
5-
public void Ensure_follow_redirect() {
5+
public void Ensure_no_httpclient_follow_redirect() {
66
var value = false;
77
var options = new RestClientOptions { FollowRedirects = true, ConfigureMessageHandler = Configure};
88
var _ = new RestClient(options);
9-
value.Should().BeTrue();
9+
value.Should().BeFalse();
1010

1111
HttpMessageHandler Configure(HttpMessageHandler handler) {
1212
value = (handler as HttpClientHandler)!.AllowAutoRedirect;

0 commit comments

Comments
 (0)