Skip to content

Commit 7e2cd26

Browse files
alexeyzimarevrassilon
authored andcommitted
WIP
1 parent 36ebe2f commit 7e2cd26

File tree

3 files changed

+83
-8
lines changed

3 files changed

+83
-8
lines changed

src/RestSharp/RestClient.Async.cs

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -89,10 +89,6 @@ async Task<HttpResponse> ExecuteRequestAsync(RestRequest request, CancellationTo
8989
var httpMethod = AsHttpMethod(request.Method);
9090
var url = this.BuildUri(request);
9191

92-
using var message = new HttpRequestMessage(httpMethod, url) { Content = requestContent.BuildContent() };
93-
message.Headers.Host = Options.BaseHost;
94-
message.Headers.CacheControl = request.CachePolicy ?? Options.CachePolicy;
95-
9692
using var timeoutCts = new CancellationTokenSource(request.Timeout > 0 ? request.Timeout : int.MaxValue);
9793
using var cts = CancellationTokenSource.CreateLinkedTokenSource(timeoutCts.Token, cancellationToken);
9894

@@ -109,11 +105,46 @@ async Task<HttpResponse> ExecuteRequestAsync(RestRequest request, CancellationTo
109105
.AddCookieHeaders(url, cookieContainer)
110106
.AddCookieHeaders(url, Options.CookieContainer);
111107

112-
message.AddHeaders(headers);
108+
HttpResponseMessage? responseMessage;
109+
110+
while (true) {
111+
using var requestContent = new RequestContent(this, request);
112+
using var message = PrepareRequestMessage(httpMethod, url, requestContent, headers);
113+
114+
if (request.OnBeforeRequest != null) await request.OnBeforeRequest(message).ConfigureAwait(false);
115+
116+
responseMessage = await HttpClient.SendAsync(message, request.CompletionOption, ct).ConfigureAwait(false);
117+
118+
if (request.OnAfterRequest != null) await request.OnAfterRequest(responseMessage).ConfigureAwait(false);
119+
120+
if (!IsRedirect(responseMessage)) {
121+
// || !Options.FollowRedirects) {
122+
break;
123+
}
124+
125+
var location = responseMessage.Headers.Location;
126+
127+
if (location == null) {
128+
break;
129+
}
130+
131+
if (!location.IsAbsoluteUri) {
132+
location = new Uri(url, location);
133+
}
113134

114-
if (request.OnBeforeRequest != null) await request.OnBeforeRequest(message).ConfigureAwait(false);
135+
if (responseMessage.StatusCode == HttpStatusCode.RedirectMethod) {
136+
httpMethod = HttpMethod.Get;
137+
}
115138

116-
var responseMessage = await HttpClient.SendAsync(message, request.CompletionOption, ct).ConfigureAwait(false);
139+
url = location;
140+
141+
if (responseMessage.Headers.TryGetValues(KnownHeaders.SetCookie, out var cookiesHeader)) {
142+
// ReSharper disable once PossibleMultipleEnumeration
143+
cookieContainer.AddCookies(url, cookiesHeader);
144+
// ReSharper disable once PossibleMultipleEnumeration
145+
Options.CookieContainer?.AddCookies(url, cookiesHeader);
146+
}
147+
}
117148

118149
// Parse all the cookies from the response and update the cookie jar with cookies
119150
if (responseMessage.Headers.TryGetValues(KnownHeaders.SetCookie, out var cookiesHeader)) {
@@ -132,6 +163,27 @@ async Task<HttpResponse> ExecuteRequestAsync(RestRequest request, CancellationTo
132163
}
133164
}
134165

166+
HttpRequestMessage PrepareRequestMessage(HttpMethod httpMethod, Uri url, RequestContent requestContent, RequestHeaders headers) {
167+
var message = new HttpRequestMessage(httpMethod, url) { Content = requestContent.BuildContent() };
168+
message.Headers.Host = Options.BaseHost;
169+
message.Headers.CacheControl = Options.CachePolicy;
170+
message.AddHeaders(headers);
171+
172+
return message;
173+
}
174+
175+
static bool IsRedirect(HttpResponseMessage responseMessage)
176+
=> responseMessage.StatusCode switch {
177+
HttpStatusCode.MovedPermanently => true,
178+
HttpStatusCode.SeeOther => true,
179+
HttpStatusCode.TemporaryRedirect => true,
180+
HttpStatusCode.Redirect => true,
181+
#if NET
182+
HttpStatusCode.PermanentRedirect => true,
183+
#endif
184+
_ => false
185+
};
186+
135187
record HttpResponse(
136188
HttpResponseMessage? ResponseMessage,
137189
Uri Url,

test/RestSharp.Tests.Integrated/RedirectTests.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,14 @@ namespace RestSharp.Tests.Integrated;
2121
[Collection(nameof(TestServerCollection))]
2222
public class RedirectTests {
2323
readonly RestClient _client;
24+
readonly string _host;
2425

2526
public RedirectTests(TestServerFixture fixture) {
2627
var options = new RestClientOptions(fixture.Server.Url) {
27-
FollowRedirects = true
28+
FollowRedirects = false
2829
};
2930
_client = new RestClient(options);
31+
_host = _client.Options.BaseUrl!.Host;
3032
}
3133

3234
[Fact]
@@ -40,6 +42,17 @@ public async Task Can_Perform_GET_Async_With_Redirect() {
4042
response.Data!.Message.Should().Be(val);
4143
}
4244

45+
[Fact]
46+
public async Task Can_Perform_GET_Async_With_Request_Cookies() {
47+
var request = new RestRequest("get-cookies-redirect") {
48+
CookieContainer = new CookieContainer(),
49+
};
50+
request.CookieContainer.Add(new Cookie("cookie", "value", null, _host));
51+
request.CookieContainer.Add(new Cookie("cookie2", "value2", null, _host));
52+
var response = await _client.ExecuteAsync(request);
53+
response.Content.Should().Be("[\"cookie=value\",\"cookie2=value2\"]");
54+
}
55+
4356
class Response {
4457
public string? Message { get; set; }
4558
}

test/RestSharp.Tests.Integrated/Server/TestServer.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Microsoft.Extensions.Logging;
66
using RestSharp.Tests.Integrated.Server.Handlers;
77
using RestSharp.Tests.Shared.Extensions;
8+
89
// ReSharper disable ConvertClosureToMethodGroup
910

1011
namespace RestSharp.Tests.Integrated.Server;
@@ -36,12 +37,21 @@ public HttpServer(ITestOutputHelper? output = null) {
3637
_app.MapGet("headers", HeaderHandlers.HandleHeaders);
3738
_app.MapGet("request-echo", async context => await context.Request.BodyReader.AsStream().CopyToAsync(context.Response.BodyWriter.AsStream()));
3839
_app.MapDelete("delete", () => new TestResponse { Message = "Works!" });
40+
_app.MapGet("redirect", () => Results.Redirect("/success", false, true));
3941

4042
// Cookies
4143
_app.MapGet("get-cookies", CookieHandlers.HandleCookies);
4244
_app.MapGet("set-cookies", CookieHandlers.HandleSetCookies);
4345
_app.MapGet("redirect", () => Results.Redirect("/success", false, true));
4446

47+
_app.MapGet(
48+
"get-cookies-redirect",
49+
(HttpContext ctx) => {
50+
ctx.Response.Cookies.Append("redirectCookie", "value1");
51+
return Results.Redirect("/get-cookies", false, true);
52+
}
53+
);
54+
4555
// PUT
4656
_app.MapPut(
4757
ContentResource,

0 commit comments

Comments
 (0)