Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions src/RestSharp/Request/RequestContent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,22 @@
namespace RestSharp;

class RequestContent : IDisposable {
readonly RestClient _client;
readonly RestRequest _request;
readonly List<Stream> _streams = new();
readonly RestClient _client;
readonly RestRequest _request;
readonly List<Stream> _streams = new();
readonly ParametersCollection _parameters;

HttpContent? Content { get; set; }

public RequestContent(RestClient client, RestRequest request) {
_client = client;
_request = request;
_client = client;
_request = request;
_parameters = new ParametersCollection(_request.Parameters.Union(_client.DefaultParameters));
}

public HttpContent BuildContent() {
AddFiles();
var postParameters = _request.Parameters.GetContentParameters(_request.Method).ToArray();
var postParameters = _parameters.GetContentParameters(_request.Method).ToArray();
AddBody(postParameters.Length > 0);
AddPostParameters(postParameters);
AddHeaders();
Expand Down Expand Up @@ -170,15 +172,15 @@ void AddPostParameters(GetOrPostParameter[] postParameters) {
#else
// 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 encodedItems = postParameters.Select(x => $"{x.Name!.UrlEncode()}={x.Value?.ToString()?.UrlEncode() ?? string.Empty}");
var encodedItems = postParameters.Select(x => $"{x.Name!.UrlEncode()}={x.Value?.ToString()?.UrlEncode() ?? string.Empty}");
var encodedContent = new StringContent(encodedItems.JoinToString("&"), null, ContentType.FormUrlEncoded.Value);
Content = encodedContent;
#endif
}
}

void AddHeaders() {
var contentHeaders = _request.Parameters
var contentHeaders = _parameters
.GetParameters<HeaderParameter>()
.Where(x => IsContentHeader(x.Name!))
.ToArray();
Expand Down
48 changes: 38 additions & 10 deletions test/RestSharp.Tests.Integrated/HttpHeadersTests.cs
Original file line number Diff line number Diff line change
@@ -1,34 +1,62 @@
using System.Net;
using RestSharp.Tests.Integrated.Fixtures;
using RestSharp.Tests.Integrated.Server;
using RestSharp.Tests.Shared.Fixtures;

namespace RestSharp.Tests.Integrated;

public class HttpHeadersTests : CaptureFixture {
[Collection(nameof(TestServerCollection))]
public class HttpHeadersTests {
readonly ITestOutputHelper _output;
readonly RestClient _client;

public HttpHeadersTests(ITestOutputHelper output) => _output = output;
public HttpHeadersTests(TestServerFixture fixture, ITestOutputHelper output) {
_output = output;
_client = new RestClient(new RestClientOptions(fixture.Server.Url) { ThrowOnAnyError = true });
}

[Fact]
public async Task Ensure_headers_correctly_set_in_the_hook() {
const string headerName = "HeaderName";
const string headerValue = "HeaderValue";

using var server = SimpleServer.Create(Handlers.Generic<RequestHeadCapturer>());

// Prepare
var client = new RestClient(server.Url);

var request = new RestRequest(RequestHeadCapturer.Resource) {
var request = new RestRequest("/headers") {
OnBeforeRequest = http => {
http.Headers.Add(headerName, headerValue);
return default;
}
};

// Run
await client.ExecuteAsync(request);
var response = await _client.ExecuteAsync<TestServerResponse[]>(request);

// Assert
RequestHeadCapturer.CapturedHeaders[headerName].Should().Be(headerValue);
response.StatusCode.Should().Be(HttpStatusCode.OK);
var header = response.Data!.First(x => x.Name == headerName);
header.Should().NotBeNull();
header.Value.Should().Be(headerValue);
}

[Fact]
public async Task Should_use_both_default_and_request_headers() {
var defaultHeader = new Header("defName", "defValue");
var requestHeader = new Header("reqName", "reqValue");

_client.AddDefaultHeader(defaultHeader.Name, defaultHeader.Value);

var request = new RestRequest("/headers")
.AddHeader(requestHeader.Name, requestHeader.Value);

var response = await _client.ExecuteAsync<TestServerResponse[]>(request);
CheckHeader(defaultHeader);
CheckHeader(requestHeader);

void CheckHeader(Header header) {
var h = response.Data!.First(x => x.Name == header.Name);
h.Should().NotBeNull();
h.Value.Should().Be(header.Value);
}
}

record Header(string Name, string Value);
}
25 changes: 25 additions & 0 deletions test/RestSharp.Tests.Integrated/PostTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,32 @@ public async Task Should_post_large_form_data() {
response.Data!.Message.Should().Be($"Works! Length: {length}");
}

[Fact]
public async Task Should_post_both_default_and_request_parameters() {
var defParam = new PostParameter("default", "default");
var reqParam = new PostParameter("request", "request");

_client.AddDefaultParameter(defParam.Name, defParam.Value);

var request = new RestRequest("post/data")
.AddParameter(reqParam.Name, reqParam.Value);

var response = await _client.ExecutePostAsync<TestServerResponse[]>(request);
response.StatusCode.Should().Be(HttpStatusCode.OK);

CheckResponse(defParam);
CheckResponse(reqParam);

void CheckResponse(PostParameter parameter) {
var p = response.Data!.FirstOrDefault(x => x.Name == parameter.Name);
p.Should().NotBeNull();
p.Value.Should().Be(parameter.Value);
}
}

class Response {
public string Message { get; set; }
}

record PostParameter(string Name, string Value);
}
2 changes: 1 addition & 1 deletion test/RestSharp.Tests.Integrated/RequestHeadTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public async Task Passes_Default_Credentials_When_UseDefaultCredentials_Is_True(
response.StatusCode.ToString().Should().BeOneOf(HttpStatusCode.OK.ToString(),HttpStatusCode.Unauthorized.ToString());
RequestHeadCapturer.CapturedHeaders.Should().NotBeNull();

var keys = RequestHeadCapturer.CapturedHeaders.Keys.Cast<string>().ToArray();
var keys = RequestHeadCapturer.CapturedHeaders!.Keys.Cast<string>().ToArray();

keys.Should()
.Contain(
Expand Down
12 changes: 12 additions & 0 deletions test/RestSharp.Tests.Integrated/Server/Handlers/FormRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using Microsoft.AspNetCore.Http;

namespace RestSharp.Tests.Integrated.Server.Handlers;

public static class FormRequestHandler {
public static IResult HandleForm(HttpContext ctx) {
var response = ctx.Request.Form.Select(
x => new TestServerResponse(x.Key, x.Value)
);
return Results.Ok(response);
}
}
2 changes: 2 additions & 0 deletions test/RestSharp.Tests.Integrated/Server/TestServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ public HttpServer(ITestOutputHelper? output = null) {
"/post/form",
(HttpContext context) => new TestResponse { Message = $"Works! Length: {context.Request.Form["big_string"].ToString().Length}" }
);

_app.MapPost("/post/data", FormRequestHandler.HandleForm);
}

public Uri Url => new(Address);
Expand Down
3 changes: 3 additions & 0 deletions test/RestSharp.Tests.Serializers.Xml/SampleClasses/twitter.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
using RestSharp.Serializers;
// ReSharper disable InconsistentNaming

namespace RestSharp.Tests.Serializers.Xml.SampleClasses;

#pragma warning disable CS8981
public class status {
#pragma warning restore CS8981
public bool truncated { get; set; }

public string created_at { get; set; }
Expand Down