Search code examples
c#asp.net.netazureazure-web-app-service

What could cause a POST request to be sent as a GET request in C# / ASP.NET Core 7


I have two ASP.NET Core 7 applications deployed on Azure app service. For certain requests, service1 needs to make a POST request on a private vnet to service2. This works fine in our staging environment. However, in our production environment the POST is converted to a GET for some reason, causing the request to fail.

What could be some reason for .NET Core to convert an outgoing POST request to a GET?

Context - adding extra logging to Refit:

services
    .AddRefitClient<IService2Api>(
        (sp) =>
            new RefitSettings
            {
                CollectionFormat = CollectionFormat.Multi,
                HttpMessageHandlerFactory = () =>
                    new LoggingHandler(
                        sp.GetRequiredService<ILoggerFactory>()
                            .CreateLogger<LoggingHandler>(),
                        new HttpClientHandler() { AllowAutoRedirect = true }
                    )
            }
    )
    .ConfigureHttpClient(
        // ...

LoggingHandler:

private class LoggingHandler : DelegatingHandler
{
    private readonly ILogger<LoggingHandler> logger;

    public LoggingHandler(ILogger<LoggingHandler> logger, HttpMessageHandler innerHandler)
        : base(innerHandler)
    {
        this.logger = logger;
    }

    protected override HttpResponseMessage Send(
        HttpRequestMessage request,
        CancellationToken cancellationToken
    )
    {
        logger.LogDebug("Before [{Method}] to {Url}", request.Method, request.RequestUri);
        var response = base.Send(request, cancellationToken);
        logger.LogDebug("After [{Method}] to {Url}", request.Method, request.RequestUri);
        return response;
    }

    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request,
        CancellationToken cancellationToken
    )
    {
        logger.LogDebug("Before [{Method}] to {Url}", request.Method, request.RequestUri);
        var response = await base.SendAsync(request, cancellationToken);
        logger.LogDebug("After [{Method}] to {Url}", request.Method, request.RequestUri);
        return response;
    }
}

Logs:

2023-11-24 23:34:11.315 +00:00 [Information] System.Net.Http.HttpClient.Refit.Implementation.Generated+IService2Api, Common, Version=1.0.1.0, Culture=neutral, PublicKeyToken=null.ClientHandler: Sending HTTP request POST http://service2.azurewebsites.net/my/endpoint/
2023-11-24 23:34:11.315 +00:00 [Trace] System.Net.Http.HttpClient.Refit.Implementation.Generated+IService2Api, Common, Version=1.0.1.0, Culture=neutral, PublicKeyToken=null.ClientHandler: Request Headers:
Authorization: Bearer [Redacted]
User-Agent: Service1, (Service1/1.0.1.0)
Content-Type: application/json; charset=utf-8

2023-11-24 23:34:11.315 +00:00 [Debug] LoggingHandler: Before [POST] to http://service2.azurewebsites.net/my/endpoint/
2023-11-24 23:34:11.400 +00:00 [Debug] LoggingHandler: After [GET] to https://service2.azurewebsites.net/my/endpoint/
2023-11-24 23:34:11.401 +00:00 [Information] System.Net.Http.HttpClient.Refit.Implementation.Generated+IService2Api, Common, Version=1.0.1.0, Culture=neutral, PublicKeyToken=null.ClientHandler: Received HTTP response headers after 85.2956ms - 405
2023-11-24 23:34:11.401 +00:00 [Trace] System.Net.Http.HttpClient.Refit.Implementation.Generated+IService2Api, Common, Version=1.0.1.0, Culture=neutral, PublicKeyToken=null.ClientHandler: Response Headers:
Date: Fri, 24 Nov 2023 23:34:11 GMT
Set-Cookie: [Redacted]
Content-Length: 0
Allow: POST

See also:


Solution

  • In ConfigureHttpClient, try disabling redirects by setting AllowAutoRedirect = false in your HttpClientHandler (example for Refit):

    services
        .AddRefitClient<T>(
            (sp) =>
                new()
                {
                    HttpMessageHandlerFactory = () =>
                        new HttpClientHandler() { AllowAutoRedirect = false }
                }
        )
    

    Then log the response status and headers.

    I think you have a 301/302 redirect in the mix somehow and the default behaviour of the http client is to automatically follow it.

    Maybe you've configured your base URL in one environment to start with http:// and the server is configured to redirect to https://?