0

I have an AspNet.Core.Mvc REST API that is routed through a proxy gateway. The gateway has a limit of 10mb for the response body. If the body is over that threshold it returns 500 Internal Server Error.

My goal: To check the size of the response body before returning from my API project and if it is over that threshold, return a BadRequest error instead, with a helpful error message in the response body content. Something like, "The response is too large. Try narrowing your request."

I've tried handling this in middleware, where the byte size of the body is known, but this is too late and the framework prevents this. I've tried working around this, something like this where you swap out the Body temporarily with a MemoryStream:

Modify middleware response

However, the status code is already set to 200 at that point and the framework throws an error if you try to change it. Here is the code snippet from the middleware where it copies the new response stream to the original body:

// Replace the body with a BadRequest error notifying user that the response
// was too large and they should narrow down their search parameters.
var errorStream = new MemoryStream();
var sw = new StreamWriter(errorStream);
sw.Write("Response exceeds maximum size. Try narrowing request parameters or setting a smaller page size if applicable.");
sw.Flush();
errorStream.Position = 0;

await errorStream.CopyToAsync(originalBody);
httpContext.Response.StatusCode = (int)HttpStatusCode.BadRequest; // throws exception!

I've also tried to handle it in the Controller method itself before returning, by serializing the response content to json, then converting the json string to bytes to check the size:

string json = JsonConvert.SerializeObject(value, jsonSerializerSettings);
byte[] bytes = Encoding.UTF8.GetBytes(json);

But that is all work that the framework will do for me, and seems wasteful (and frankly ugly). Is there a way to set this as the response and return it from the Controller? Maybe I can create a base class for the Controller that all API methods can use that will do this logic?

This all seems like a lot of trouble for something seemingly simple. I'm hoping someone here has a better solution.

6
  • First, .NET Core 2.2 went out of support a long time ago. Even .NET Core 3.1, the Long Term Support version that replaces it reaches End of Life this December. The current LTS version is .NET 6. Commented Jul 19, 2022 at 17:31
  • Second, why is the response so big? What are you returning? What is value? It's far better to check the size of the returned data before serialization. If you return rows from a query, you can use a TOP in SQL or Take in LINQ to limit the results from the start. Commented Jul 19, 2022 at 17:33
  • I agree that it is far easier to limit the number of records in the response before serializing, however it doesn't allow for any precision at all in terms of bytes. Commented Jul 19, 2022 at 17:35
  • My question is specifically how to check the byte size of the response body before sending it. Commented Jul 19, 2022 at 17:36
  • 1
    By that point you've already paid the cost of retrieving and serializing data that won't be sent to the caller. I'd argue that byte precision doesn't matter and you should be able to reject such requests as soon as possible Commented Jul 19, 2022 at 18:18

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.