From 777bf194ec2d14271e7807cc704e73ec18fcaf7e Mon Sep 17 00:00:00 2001 From: Kenny Carneal Date: Tue, 27 Aug 2024 05:51:20 -0400 Subject: [PATCH 1/3] Fixed sentence to be easier to read (#2251) Fixed a sentence that accidentally used the word "only" twice. --- docs/versioned_docs/version-v111/intro.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/versioned_docs/version-v111/intro.md b/docs/versioned_docs/version-v111/intro.md index 6d8d61664..8144a61cd 100644 --- a/docs/versioned_docs/version-v111/intro.md +++ b/docs/versioned_docs/version-v111/intro.md @@ -84,7 +84,7 @@ There is no need to set the `Content-Type` or add the `DataFormat` parameter to RestSharp will also handle both XML and JSON responses and perform all necessary deserialization tasks, depending on the server response type. Therefore, you only need to add the `Accept` header if you want to deserialize the response manually. -For example, only you'd only need these lines to make a request with JSON body: +For example, you'd only need these lines to make a request with JSON body: ```csharp var request = new RestRequest("address/update").AddJsonBody(updatedAddress); From 7b7950b1b6cfb7f1251f6c2e4cf74062ace41e65 Mon Sep 17 00:00:00 2001 From: Sergey Nechaev <6499856+snechaev@users.noreply.github.com> Date: Thu, 29 Aug 2024 20:59:33 +0200 Subject: [PATCH 2/3] Fixed the Simple Factory example. Fixes #2255 (#2256) --- docs/docs/usage/client.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/docs/usage/client.md b/docs/docs/usage/client.md index 0207c3e25..e84b955f4 100644 --- a/docs/docs/usage/client.md +++ b/docs/docs/usage/client.md @@ -56,7 +56,8 @@ Constructor parameters to configure the `HttpMessageHandler` and default `HttpCl You need to set the `useClientFactory` parameter to `true` in the `RestClient` constructor to enable the factory. ```csharp -var client = new RestClient("https://api.twitter.com/2", true); +var options = new RestClientOptions("https://api.twitter.com/2"); +var client = new RestClient(options, useClientFactory: true); ``` ## Reusing HttpClient From 0fba5e727d241b1867bd71efc912594075c2934b Mon Sep 17 00:00:00 2001 From: Alexey Zimarev Date: Thu, 29 Aug 2024 21:04:54 +0200 Subject: [PATCH 3/3] Don't allow CRLF in headers (#2258) --- src/RestSharp/Parameters/HeaderParameter.cs | 61 +++++++++++++++++-- .../Request/RestRequestExtensions.Headers.cs | 32 ++-------- test/RestSharp.Tests/RequestHeaderTests.cs | 6 ++ 3 files changed, 65 insertions(+), 34 deletions(-) diff --git a/src/RestSharp/Parameters/HeaderParameter.cs b/src/RestSharp/Parameters/HeaderParameter.cs index 1607eaeda..7dce5df92 100644 --- a/src/RestSharp/Parameters/HeaderParameter.cs +++ b/src/RestSharp/Parameters/HeaderParameter.cs @@ -13,22 +13,71 @@ // limitations under the License. // +using System.Text; +using System.Text.RegularExpressions; + namespace RestSharp; -public record HeaderParameter : Parameter { +public partial record HeaderParameter : Parameter { /// /// Instantiates a header parameter /// - /// Parameter name - /// Parameter value - public HeaderParameter(string name, string value) + /// Header name + /// Header value + /// Set to true to encode header value according to RFC 2047. Default is false. + public HeaderParameter(string name, string value, bool encode = false) : base( - Ensure.NotEmptyString(name, nameof(name)), - Ensure.NotNull(value, nameof(value)), + EnsureValidHeaderString(Ensure.NotEmptyString(name, nameof(name)), "name"), + EnsureValidHeaderValue(name, value, encode), ParameterType.HttpHeader, false ) { } public new string Name => base.Name!; public new string Value => (string)base.Value!; + + static string EnsureValidHeaderValue(string name, string value, bool encode) { + CheckAndThrowsForInvalidHost(name, value); + + return EnsureValidHeaderString(GetValue(Ensure.NotNull(value, nameof(value)), encode), "value"); + } + + static string EnsureValidHeaderString(string value, string type) + => !IsInvalidHeaderString(value) ? value : throw new ArgumentException($"Invalid character found in header {type}: {value}"); + + static string GetValue(string value, bool encode) => encode ? GetBase64EncodedHeaderValue(value) : value; + + static string GetBase64EncodedHeaderValue(string value) => $"=?UTF-8?B?{Convert.ToBase64String(Encoding.UTF8.GetBytes(value))}?="; + + static bool IsInvalidHeaderString(string stringValue) { + // ReSharper disable once ForCanBeConvertedToForeach + for (var i = 0; i < stringValue.Length; i++) { + switch (stringValue[i]) { + case '\t': + case '\r': + case '\n': + return true; + } + } + + return false; + } + + static readonly Regex PortSplitRegex = PartSplit(); + + static void CheckAndThrowsForInvalidHost(string name, string value) { + if (name == KnownHeaders.Host && InvalidHost(value)) + throw new ArgumentException("The specified value is not a valid Host header string.", nameof(value)); + + return; + + static bool InvalidHost(string host) => Uri.CheckHostName(PortSplitRegex.Split(host)[0]) == UriHostNameType.Unknown; + } + +#if NET7_0_OR_GREATER + [GeneratedRegex(@":\d+")] + private static partial Regex PartSplit(); +#else + static Regex PartSplit() => new(@":\d+"); +#endif } \ No newline at end of file diff --git a/src/RestSharp/Request/RestRequestExtensions.Headers.cs b/src/RestSharp/Request/RestRequestExtensions.Headers.cs index 8091a1a50..d3e6b7815 100644 --- a/src/RestSharp/Request/RestRequestExtensions.Headers.cs +++ b/src/RestSharp/Request/RestRequestExtensions.Headers.cs @@ -12,8 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -using System.Text.RegularExpressions; - namespace RestSharp; public static partial class RestRequestExtensions { @@ -39,10 +37,8 @@ public static RestRequest AddHeader(this RestRequest request, string name, strin /// Header name /// Header value /// - public static RestRequest AddHeader(this RestRequest request, string name, string value) { - CheckAndThrowsForInvalidHost(name, value); - return request.AddParameter(new HeaderParameter(name, value)); - } + public static RestRequest AddHeader(this RestRequest request, string name, string value) + => request.AddParameter(new HeaderParameter(name, value)); /// /// Adds a header to the request. RestSharp will try to separate request and content headers when calling the resource. @@ -62,10 +58,8 @@ public static RestRequest AddHeader(this RestRequest request, string name, T /// Header name /// Header value /// - public static RestRequest AddOrUpdateHeader(this RestRequest request, string name, string value) { - CheckAndThrowsForInvalidHost(name, value); - return request.AddOrUpdateParameter(new HeaderParameter(name, value)); - } + public static RestRequest AddOrUpdateHeader(this RestRequest request, string name, string value) + => request.AddOrUpdateParameter(new HeaderParameter(name, value)); /// /// Adds or updates the request header. RestSharp will try to separate request and content headers when calling the resource. @@ -121,22 +115,4 @@ static void CheckAndThrowsDuplicateKeys(ICollection throw new ArgumentException($"Duplicate header names exist: {string.Join(", ", duplicateKeys)}"); } } - - static readonly Regex PortSplitRegex = PartSplit(); - - static void CheckAndThrowsForInvalidHost(string name, string value) { - if (name == KnownHeaders.Host && InvalidHost(value)) - throw new ArgumentException("The specified value is not a valid Host header string.", nameof(value)); - - return; - - static bool InvalidHost(string host) => Uri.CheckHostName(PortSplitRegex.Split(host)[0]) == UriHostNameType.Unknown; - } - -#if NET7_0_OR_GREATER - [GeneratedRegex(@":\d+")] - private static partial Regex PartSplit(); -#else - static Regex PartSplit() => new(@":\d+"); -#endif } \ No newline at end of file diff --git a/test/RestSharp.Tests/RequestHeaderTests.cs b/test/RestSharp.Tests/RequestHeaderTests.cs index 6fa6c8215..bf8bc4c4b 100644 --- a/test/RestSharp.Tests/RequestHeaderTests.cs +++ b/test/RestSharp.Tests/RequestHeaderTests.cs @@ -174,6 +174,12 @@ public void Should_not_allow_empty_header_name() { var request = new RestRequest(); Assert.Throws("name", () => request.AddHeader("", "value")); } + + [Fact] + public void Should_not_allow_CRLF_in_header_value() { + var request = new RestRequest(); + Assert.Throws(() => request.AddHeader("name", "test\r\nUser-Agent: injected header!\r\n\r\nGET /smuggled HTTP/1.1\r\nHost: insert.some.site.here")); + } static Parameter[] GetHeaders(RestRequest request) => request.Parameters.Where(x => x.Type == ParameterType.HttpHeader).ToArray(); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy