Numbers in text/plain content is parsed as JSON. #628

Closed
opened 2025-12-29 08:31:26 +01:00 by adam · 0 comments
Owner

Originally created by @ruxo on GitHub (Sep 9, 2024).

Describe the bug

I am working with a PATCH API that sends a number as text content using the text/plain MIME type. However, when the request body is proxied through the WireMock server, the number gets automatically converted into a decimal if it appears in octal (with a leading zero) or hexadecimal format (with a 0x prefix).

Expected behavior:

I expect the text content with the text/plain MIME type to remain unprocessed, as-is. Any automatic conversion of the number should only occur if the content type is set to application/json.

Test to reproduce

Here, a unit test example:

using System.Net;
using System.Net.Http.Headers;
using System.Reactive.Disposables;
using System.Text;
using FluentAssertions;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using WireMock.Net.StandAlone;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
using WireMock.Settings;

public sealed class IntegrationTests
{
    [Fact]
    public async Task Test1()
    {
        // Given
        using var server = await TestServer.New(5000).Run();

        var settings = new WireMockServerSettings {
            Port = 9091,
            StartAdminInterface = true
        };
        using var mockServer = StandAloneApp.Start(settings);
        mockServer.Given(Request.Create().WithPath("/key").UsingPatch())
                  .RespondWith(Response.Create().WithProxy("http://localhost:5000/key"));

        using var client = new HttpClient { BaseAddress = new Uri("http://localhost:9091") };
        using var content = new ByteArrayContent("0x11"u8.ToArray());
        content.Headers.ContentType = new MediaTypeHeaderValue("text/plain");

        // When
        var response = await client.PatchAsync("/key", content);

        // Then
        response.StatusCode.Should().Be(HttpStatusCode.OK);
        var result = await response.Content.ReadAsStringAsync();
        result.Should().Be("0x11");  // failed here, as `17` is returned
    }
}

sealed class TestServer(WebApplication app)
{
    public static TestServer New(int port) {
        var builder = WebApplication.CreateBuilder(new WebApplicationOptions {
            Args = [$"--urls=http://localhost:{port}"]
        });

        var app = builder.Build();

        app.MapPatch("/key", async (HttpRequest req) => {
            var memory = new MemoryStream();
            await req.Body.CopyToAsync(memory);
            var content = Encoding.UTF8.GetString(memory.ToArray());
            return content;
        });
        return new(app);
    }

    public async ValueTask<IDisposable> Run() {
        var started = new TaskCompletionSource();
        var host = app.Services.GetRequiredService<IHostApplicationLifetime>();
        host.ApplicationStarted.Register(() => started.SetResult());
        _ = Task.Run(() => app.RunAsync());
        await started.Task;
        return Disposable.Create(host, h => h.StopApplication());
    }
}
Originally created by @ruxo on GitHub (Sep 9, 2024). ### Describe the bug I am working with a `PATCH` API that sends a number as text content using the `text/plain` MIME type. However, when the request body is proxied through the WireMock server, the number gets automatically converted into a decimal if it appears in octal (with a leading zero) or hexadecimal format (with a `0x` prefix). ### Expected behavior: I expect the text content with the `text/plain` MIME type to remain unprocessed, as-is. Any automatic conversion of the number should only occur if the content type is set to `application/json`. ### Test to reproduce Here, a unit test example: ```csharp using System.Net; using System.Net.Http.Headers; using System.Reactive.Disposables; using System.Text; using FluentAssertions; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using WireMock.Net.StandAlone; using WireMock.RequestBuilders; using WireMock.ResponseBuilders; using WireMock.Settings; public sealed class IntegrationTests { [Fact] public async Task Test1() { // Given using var server = await TestServer.New(5000).Run(); var settings = new WireMockServerSettings { Port = 9091, StartAdminInterface = true }; using var mockServer = StandAloneApp.Start(settings); mockServer.Given(Request.Create().WithPath("/key").UsingPatch()) .RespondWith(Response.Create().WithProxy("http://localhost:5000/key")); using var client = new HttpClient { BaseAddress = new Uri("http://localhost:9091") }; using var content = new ByteArrayContent("0x11"u8.ToArray()); content.Headers.ContentType = new MediaTypeHeaderValue("text/plain"); // When var response = await client.PatchAsync("/key", content); // Then response.StatusCode.Should().Be(HttpStatusCode.OK); var result = await response.Content.ReadAsStringAsync(); result.Should().Be("0x11"); // failed here, as `17` is returned } } sealed class TestServer(WebApplication app) { public static TestServer New(int port) { var builder = WebApplication.CreateBuilder(new WebApplicationOptions { Args = [$"--urls=http://localhost:{port}"] }); var app = builder.Build(); app.MapPatch("/key", async (HttpRequest req) => { var memory = new MemoryStream(); await req.Body.CopyToAsync(memory); var content = Encoding.UTF8.GetString(memory.ToArray()); return content; }); return new(app); } public async ValueTask<IDisposable> Run() { var started = new TaskCompletionSource(); var host = app.Services.GetRequiredService<IHostApplicationLifetime>(); host.ApplicationStarted.Register(() => started.SetResult()); _ = Task.Run(() => app.RunAsync()); await started.Task; return Disposable.Create(host, h => h.StopApplication()); } } ```
adam added the bug label 2025-12-29 08:31:26 +01:00
adam closed this issue 2025-12-29 08:31:26 +01:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/WireMock.Net#628