Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow setting the Content-Length header for a HTTP method HEAD #951

Merged
merged 2 commits into from
Jun 6, 2023
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
20 changes: 19 additions & 1 deletion src/WireMock.Net/Http/HttpRequestMessageHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,18 @@
using System.Net.Http.Headers;
using Newtonsoft.Json;
using Stef.Validation;
using WireMock.Constants;
using WireMock.Types;

namespace WireMock.Http;

internal static class HttpRequestMessageHelper
{
private static readonly IDictionary<string, bool> ContentLengthHeaderAllowed = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase)
{
{ HttpRequestMethod.HEAD, true }
};

internal static HttpRequestMessage Create(IRequestMessage requestMessage, string url)
{
Guard.NotNull(requestMessage);
Expand Down Expand Up @@ -50,7 +56,19 @@ internal static HttpRequestMessage Create(IRequestMessage requestMessage, string
return httpRequestMessage;
}

var excludeHeaders = new List<string> { HttpKnownHeaderNames.Host, HttpKnownHeaderNames.ContentLength };
var excludeHeaders = new List<string> { HttpKnownHeaderNames.Host };

var contentLengthHeaderAllowed = ContentLengthHeaderAllowed.TryGetValue(requestMessage.Method, out var allowed) && allowed;
if (contentLengthHeaderAllowed)
{
// Set Content to empty ByteArray to be able to set the Content-Length on the content in case of a HEAD method.
httpRequestMessage.Content ??= new ByteArrayContent(EmptyArray<byte>.Value);
}
else
{
excludeHeaders.Add(HttpKnownHeaderNames.ContentLength);
}

if (contentType != null)
{
// Content-Type should be set on the content
Expand Down
27 changes: 27 additions & 0 deletions test/WireMock.Net.Tests/Http/HttpRequestMessageHelperTests.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using NFluent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FluentAssertions;
using WireMock.Http;
using WireMock.Models;
using WireMock.Types;
Expand Down Expand Up @@ -160,4 +162,29 @@ public void HttpRequestMessageHelper_Create_String_With_ContentType_ApplicationX
// Assert
Check.That(message.Content.Headers.GetValues("Content-Type")).ContainsExactly("application/xml; charset=Ascii");
}

[Theory]
[InlineData("HEAD", true)]
[InlineData("GET", false)]
[InlineData("PUT", false)]
[InlineData("POST", false)]
[InlineData("DELETE", false)]
[InlineData("TRACE", false)]
[InlineData("OPTIONS", false)]
[InlineData("CONNECT", false)]
[InlineData("PATCH", false)]
public void HttpRequestMessageHelper_Create_ContentLengthAllowedForMethod(string method, bool resultShouldBe)
{
// Arrange
var key = "Content-Length";
var value = 1234;
var headers = new Dictionary<string, string[]> { { key, new[] { "1234" } } };
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), method, ClientIp, null, headers);

// Act
var message = HttpRequestMessageHelper.Create(request, "http://url");

// Assert
message.Content?.Headers.ContentLength.Should().Be(resultShouldBe ? value : null);
}
}