Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RequestSizeLimitAttribute: HTTP 500 instead of 413 in ASP.NET Core 2.1.401

I have [RequestSizeLimit] on my API controller, and it kinda works as expected: requests bigger than specified limit are rejected.

    [HttpPut]
    [RequestSizeLimit(120_000_000)]
    public async Task<IActionResult> Put(IFormCollection form)
    {
       ...
    }

The problem is, an exception is thrown:

Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException: Request body too large.
   at Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException.Throw(RequestRejectionReason reason)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.Http1MessageBody.ForContentLength.OnReadStarting()
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.MessageBody.TryInit()
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.MessageBody.ReadAsync(Memory`1 buffer, CancellationToken cancellationToken)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpRequestStream.ReadAsyncInternal(Memory`1 buffer, CancellationToken cancellationToken)

So HTTP 500 is returned, but I would expect 413 or 400. And I don't expect an exception, since this is a perfectly normal situation.

Could not find any documentation on this. What is the right way to return 413 for requests that are too big?

like image 524
Pavel Tupitsyn Avatar asked Sep 09 '18 11:09

Pavel Tupitsyn


People also ask

How do IIs and ASP NET protect us from large requests?

By default, ASP.NET and IIS protect us from large requests by putting hard limits on the transmitted size. IIS buffers files in our server’s memory before passing the byte array to ASP.NET. IIS’ default limit is 4MB and ASP.NET Core has a default of 30MB. To put that in perspective, one 12 megapixels digital picture can average 3.6 megabytes.

What is the maximum size of an HTTP request?

Which server are you using? For Nginx users, the directive which determines what the allowable HTTP request size can be is client_max_body_size, the default maximum allowable request size is 1MB. The limit in Apache is set via the LimitRequestBody directive and defaults to 0 (meaning unlimited) to 2147483647 (2GB).

What does error 413 mean when sending a request?

Unfortunately when sending the request I receive an error: Response status code does not indicate success: 413 (Request Entity Too Large). The error only seems to occur when the file is large to begin with, which makes sense.

How to return status code from ASP NET Core API?

In ASP.NET Core, returning status code is easier than you might think. HTTP response status codes have so much importance in REST API’s. In any case if you want to return a status code from your ASP.NET Core API, all you have to do is in your controller method,


1 Answers

Kestrel responds with a 413 Payload Too Large response, but HttpSys responds with a generic 500 Internal Server Error response. I assume you use the second one. In this case you can implement Exception handling middelware to handle this case:

public class ExceptionMiddleware
{
    private readonly RequestDelegate _next;

    public ExceptionMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext httpContext)
    {
        try
        {
            await _next(httpContext);
        }
        catch (Exception ex)
        {
            HandleExceptionAsync(httpContext, ex);
        }
    }

    private static void HandleExceptionAsync(HttpContext context, Exception exception)
    {
        if (exception is BadHttpRequestException badRequestException && badRequestException.Message == "Request body too large.")
        {
            context.Response.StatusCode = (int) HttpStatusCode.RequestEntityTooLarge;
        }
    }
}

And register it in Configure in Startup.cs:

public void Configure(IApplicationBuilder app)
{
    ...
    app.UseMiddleware<ExceptionMiddleware>();
    ...
}

As alternative you can also use Exception filter

like image 190
Alex Riabov Avatar answered Oct 23 '22 03:10

Alex Riabov