From 29f21d9243b043eedc9ca884d6811207d7c6a397 Mon Sep 17 00:00:00 2001 From: rassilon Date: Thu, 2 Nov 2023 15:38:08 -0400 Subject: [PATCH] Improvements (and corrections on some tiny merge errors during) based on rebasing... --- .../Options/RestClientRedirectionOptions.cs | 11 +++++- src/RestSharp/RestClient.Async.cs | 36 ++++++------------- .../Server/TestServer.cs | 1 - 3 files changed, 21 insertions(+), 27 deletions(-) diff --git a/src/RestSharp/Options/RestClientRedirectionOptions.cs b/src/RestSharp/Options/RestClientRedirectionOptions.cs index 2b5b83e64..8962b10d6 100644 --- a/src/RestSharp/Options/RestClientRedirectionOptions.cs +++ b/src/RestSharp/Options/RestClientRedirectionOptions.cs @@ -21,6 +21,7 @@ public class RestClientRedirectionOptions { /// redirect from HTTPS to HTTP. /// public bool FollowRedirectsToInsecure { get; set; } = false; + /// /// Set to true (default), when you want to include the originally /// requested headers in redirected requests. @@ -32,8 +33,9 @@ public class RestClientRedirectionOptions { /// Authorization header to the redirected destination. /// public bool ForwardAuthorization { get; set; } = false; + /// - /// Set to true (default), when you want to include cookie3s from the + /// Set to true (default), when you want to include cookies from the /// CookieContainer on the redirected URL. /// /// @@ -88,6 +90,13 @@ public class RestClientRedirectionOptions { /// fragment should inherit the fragment from the original URI. /// public bool ForwardFragment { get; set; } = true; + + /// + /// Set to true (default), to allow the HTTP Method used on the original request to + /// be replaced with GET when the status code 303 (HttpStatusCode.RedirectMethod) + /// was returned. Setting this to false will disallow the altering of the verb. + /// + public bool AllowRedirectMethodStatusCodeToAlterVerb { get; set; } = true; /// /// HttpStatusCodes that trigger redirect processing. Defaults to MovedPermanently (301), diff --git a/src/RestSharp/RestClient.Async.cs b/src/RestSharp/RestClient.Async.cs index 862fad3cb..b13037daf 100644 --- a/src/RestSharp/RestClient.Async.cs +++ b/src/RestSharp/RestClient.Async.cs @@ -94,26 +94,12 @@ async Task ExecuteRequestAsync(RestRequest request, CancellationTo using var cts = CancellationTokenSource.CreateLinkedTokenSource(timeoutCts.Token, cancellationToken); var ct = cts.Token; - - - HttpResponseMessage? responseMessage; - // Make sure we have a cookie container if not provided in the request - CookieContainer cookieContainer = request.CookieContainer ??= new CookieContainer(); - var headers = new RequestHeaders() - .AddHeaders(request.Parameters) - .AddHeaders(DefaultParameters) - .AddAcceptHeader(AcceptedContentTypes) - .AddCookieHeaders(url, cookieContainer) - .AddCookieHeaders(url, Options.CookieContainer); + HttpResponseMessage? responseMessage = null; + var cookieContainer = request.CookieContainer ??= new CookieContainer(); - message.AddHeaders(headers); - if (request.OnBeforeRequest != null) await request.OnBeforeRequest(message).ConfigureAwait(false); - await OnBeforeRequest(message).ConfigureAwait(false); - try { // Make sure we have a cookie container if not provided in the request - var cookieContainer = request.CookieContainer ??= new CookieContainer(); var headers = new RequestHeaders() .AddHeaders(request.Parameters) @@ -123,7 +109,6 @@ async Task ExecuteRequestAsync(RestRequest request, CancellationTo .AddCookieHeaders(url, Options.CookieContainer); bool foundCookies = false; - HttpResponseMessage? responseMessage = null; do { using var requestContent = new RequestContent(this, request); @@ -137,10 +122,12 @@ async Task ExecuteRequestAsync(RestRequest request, CancellationTo using var message = PrepareRequestMessage(httpMethod, url, content, headers); if (request.OnBeforeRequest != null) await request.OnBeforeRequest(message).ConfigureAwait(false); + await OnBeforeRequest(message).ConfigureAwait(false); responseMessage = await HttpClient.SendAsync(message, request.CompletionOption, ct).ConfigureAwait(false); if (request.OnAfterRequest != null) await request.OnAfterRequest(responseMessage).ConfigureAwait(false); + await OnAfterRequest(responseMessage).ConfigureAwait(false); if (!IsRedirect(Options.RedirectOptions, responseMessage)) { break; @@ -171,15 +158,17 @@ async Task ExecuteRequestAsync(RestRequest request, CancellationTo // Disallow automatic redirection from secure to non-secure schemes // based on the option setting: - if (HttpUtilities.IsSupportedSecureScheme(requestUri.Scheme) + if (HttpUtilities.IsSupportedSecureScheme(originalUrl.Scheme) && !HttpUtilities.IsSupportedSecureScheme(location.Scheme) && !Options.RedirectOptions.FollowRedirectsToInsecure) { // TODO: Log here... break; } - if (responseMessage.StatusCode == HttpStatusCode.RedirectMethod) { - // TODO: Add RedirectionOptions property for this decision: + // This is the expected behavior for this status code, but + // ignore it if requested from the RedirectOptions: + if (responseMessage.StatusCode == HttpStatusCode.RedirectMethod + && Options.RedirectOptions.AllowRedirectMethodStatusCodeToAlterVerb) { httpMethod = HttpMethod.Get; } @@ -199,10 +188,8 @@ async Task ExecuteRequestAsync(RestRequest request, CancellationTo if (!Options.RedirectOptions.ForceForwardBody) { // HttpClient RedirectHandler sets request.Content to null here: message.Content = null; - // HttpClient Redirect handler also does this: - //if (message.Headers.TansferEncodingChunked == true) { - // request.Headers.TransferEncodingChunked = false; - //} + // HttpClient Redirect handler also foribly removes + // a Transfer-Encoding of chunked in this case. Parameter? transferEncoding = request.Parameters.TryFind(KnownHeaders.TransferEncoding); if (transferEncoding != null && transferEncoding.Type == ParameterType.HttpHeader @@ -237,7 +224,6 @@ async Task ExecuteRequestAsync(RestRequest request, CancellationTo if (request.OnAfterRequest != null) await request.OnAfterRequest(responseMessage).ConfigureAwait(false); await OnAfterRequest(responseMessage).ConfigureAwait(false); return new HttpResponse(responseMessage, url, cookieContainer, null, timeoutCts.Token); - } /// diff --git a/test/RestSharp.Tests.Integrated/Server/TestServer.cs b/test/RestSharp.Tests.Integrated/Server/TestServer.cs index 0c32396b1..46988ba28 100644 --- a/test/RestSharp.Tests.Integrated/Server/TestServer.cs +++ b/test/RestSharp.Tests.Integrated/Server/TestServer.cs @@ -38,7 +38,6 @@ public HttpServer(ITestOutputHelper? output = null) { _app.MapGet("headers", HeaderHandlers.HandleHeaders); _app.MapGet("request-echo", async context => await context.Request.BodyReader.AsStream().CopyToAsync(context.Response.BodyWriter.AsStream())); _app.MapDelete("delete", () => new TestResponse { Message = "Works!" }); - _app.MapGet("redirect", () => Results.Redirect("/success", false, true)); // Cookies _app.MapGet("get-cookies", CookieHandlers.HandleCookies);