diff --git a/src/RestSharp/Request/RequestContent.cs b/src/RestSharp/Request/RequestContent.cs index 9b24ad1ea..7e7619ab9 100644 --- a/src/RestSharp/Request/RequestContent.cs +++ b/src/RestSharp/Request/RequestContent.cs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System.Net; using System.Net.Http.Headers; using System.Runtime.Serialization; using RestSharp.Extensions; @@ -157,13 +158,16 @@ void AddPostParameters(ParametersCollection? postParameters) { } } else { - // we should not have anything else except the parameters, so we send them as form URL encoded - var formContent = new FormUrlEncodedContent( - _request.Parameters - .Where(x => x.Type == ParameterType.GetOrPost) - .Select(x => new KeyValuePair(x.Name!, x.Value!.ToString()!))! - ); - Content = formContent; + // we should not have anything else except the parameters, so we send them as form URL encoded. However due + // to bugs in HttpClient FormUrlEncodedContent (see https://github.com/restsharp/RestSharp/issues/1814) we + // do the encoding ourselves using WebUtility.UrlEncode instead. + var formData = _request.Parameters + .Where(x => x.Type == ParameterType.GetOrPost) + .Select(x => new KeyValuePair(x.Name!, x.Value!.ToString()!))!; + var encodedItems = formData.Select(i => $"{WebUtility.UrlEncode(i.Key)}={WebUtility.UrlEncode(i.Value)}"/*.Replace("%20", "+")*/); + var encodedContent = new StringContent(string.Join("&", encodedItems), null, "application/x-www-form-urlencoded"); + + Content = encodedContent; } } diff --git a/test/RestSharp.Tests.Integrated/PostTests.cs b/test/RestSharp.Tests.Integrated/PostTests.cs index 9b825f30c..566b2981d 100644 --- a/test/RestSharp.Tests.Integrated/PostTests.cs +++ b/test/RestSharp.Tests.Integrated/PostTests.cs @@ -1,3 +1,4 @@ +using System.Net; using RestSharp.Tests.Integrated.Server; namespace RestSharp.Tests.Integrated; @@ -33,4 +34,19 @@ public async Task Should_post_json_with_PostJsonAsync() { response.Message.Should().Be(body.Data); } + + class Response { + public string Message { get; set; } + } + + [Fact] + public async Task Should_post_large_form_data() { + const int length = 1024 * 1024; + var superLongString = new string('?', length); + var request = new RestRequest("post/form", Method.Post).AddParameter("big_string", superLongString); + var response = await _client.ExecuteAsync(request); + + response.StatusCode.Should().Be(HttpStatusCode.OK); + response.Data!.Message.Should().Be($"Works! Length: {length}"); + } } diff --git a/test/RestSharp.Tests.Integrated/Server/TestServer.cs b/test/RestSharp.Tests.Integrated/Server/TestServer.cs index 12681fa1e..fa7a365da 100644 --- a/test/RestSharp.Tests.Integrated/Server/TestServer.cs +++ b/test/RestSharp.Tests.Integrated/Server/TestServer.cs @@ -53,6 +53,7 @@ public HttpServer(ITestOutputHelper output = null) { // POST _app.MapPost("/post/json", (TestRequest request) => new TestResponse { Message = request.Data }); + _app.MapPost("/post/form", (HttpContext context) => new TestResponse { Message = $"Works! Length: {context.Request.Form["big_string"].ToString().Length}" }); IResult HandleHeaders(HttpContext ctx) { var response = ctx.Request.Headers.Select(x => new TestServerResponse(x.Key, x.Value));