504 HTTP Status Code in ASP.NET Core Web API

504 HTTP Status Code in ASP.NET Core Web API

In this article, I will discuss How to Return 504 Gateway Timeout HTTP Status Code in ASP.NET Core Web API Application with Examples. Please read our previous article discussing How to Return 503 Service Unavailable HTTP Status Code in ASP.NET Core Web API with Examples.

504 HTTP Status Code

The 504 Gateway Timeout HTTP status code is an error response returned by a server when it is acting as a gateway or proxy and cannot get a response in time from the upstream server. This situation implies that the request was unsuccessful due to the upstream server taking too long to respond, which could be due to various reasons such as network issues, server overload, or the upstream server being down.

In more detail, when a client request is made to a web service, the request might pass through multiple servers or proxies. These intermediate servers or proxies forward the request to the next node in the chain until it reaches the server that can fulfil the request. If any server in this chain cannot get a response from the next server within a set timeframe, it will return a 504 Gateway Timeout error to the client.

The 504 Status Code suggests that the problem is temporary and may be resolved by retrying the request after some time. However, persistent 504 errors indicate a more serious issue that needs to be addressed by the website or service provider’s technical team. To troubleshoot a 504 Gateway Timeout error, one can:

  • Retry the request: Simply refreshing the browser or retrying the action after a brief wait can sometimes resolve the issue if it was caused by a temporary glitch or overload.
  • Check network connectivity: Ensuring there are no network issues on the client side that could be preventing communication with the server.
  • Contact the website or service provider: If the issue persists, reaching out to the website or service’s support team can help, as they may be aware of the issue and can provide updates or workarounds.
How to Return 504 HTTP Status Code in ASP.NET Core Web API

Returning a 504 HTTP status code in an ASP.NET Core Web API indicates that the server, while acting as a gateway or proxy, did not receive a timely response from the upstream server or some other auxiliary service it accessed in attempting to fulfil the request. Implementing this involves manually setting the response status code in your controller action. Here’s how you can do it:

Directly in an Action Method:

You can set the status code directly in your controller’s action method when you know the request has timed out or if an upstream service is not responding in time. For a better understanding, please modify the Sample Controller as follows:

using Microsoft.AspNetCore.Mvc;
namespace ReturnTypeAndStatusCodes.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class SampleController : ControllerBase
    {
        [HttpGet]
        public async Task<IActionResult> GetResource()
        {
            //Creating an Instance of CancellationTokenSource
            CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
            
            //Setting the Duration to 5 Seconds after which it will cancel the execution
            cancellationTokenSource.CancelAfter(5000);

            try
            {
                await LongRunningTask(cancellationTokenSource.Token);

                return Ok("Operation Successful");
            }
            catch (Exception ex)
            {
                //Log the Error Message

                // Return a 504 Gateway Timeout response
                var customResponse = new
                {
                    Code = 504,
                    Message = $"The request timed out waiting for an external service.",

                    //Do Not Expose the Actual Error Message to the Client
                    //ErrorMessage = ex.Message
                };
                
                return StatusCode(504, customResponse);
            }
        }

        public static async Task LongRunningTask(CancellationToken token)
        {
            //Actual Service Call and Database Call goes here

            for (int i = 0; i < 10; i++)
            {
                if (token.IsCancellationRequested)
                {
                    throw new TaskCanceledException();
                }

                //Delaying the Execution for 10 Secons
                await Task.Delay(1000);
            }
        }
    }
}

Now, if you access the above endpoint, then after 5 seconds, you will get the 504 Gateway Timeout response as shown in the below image:

504 HTTP Status Code in ASP.NET Core Web API

Using Custom Middleware to Handle 504 Gateway Timeout Error in ASP.NET Core Web API:

If you want to apply this behaviour globally, consider implementing a custom middleware component. Middleware allows you to inspect and modify HTTP requests and responses flowing through your application’s pipeline.

So, create a class file named TimeoutMiddleware.cs and copy and paste the following code. The following middleware will check for a specific condition (like a timeout exception) and set the response status code accordingly:

using System.Text.Json;

namespace ReturnTypeAndStatusCodes.Models
{
    public class TimeoutMiddleware
    {
        private readonly RequestDelegate _next;

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

        public async Task Invoke(HttpContext httpContext)
        {
            try
            {
                await _next(httpContext);
            }
            catch (TimeoutException)
            {
                if (!httpContext.Response.HasStarted)
                {
                    httpContext.Response.Clear();
                    httpContext.Response.StatusCode = 504; // Gateway Timeout

                    httpContext.Response.ContentType = "application/json";
                    var customResponse = new
                    {
                        Code = 504,
                        Message = "Server did not receive a timely response from an upstream server.",
                    };

                    var responseJson = JsonSerializer.Serialize(customResponse);
                    await httpContext.Response.WriteAsync(responseJson);
                }
            }
        }
    }
}
In the above example,
  • RequestDelegate _next: This private field holds the next piece of middleware in the application pipeline. A RequestDelegate is a function that handles an HTTP request and returns a Task. In the context of middleware, this delegate represents the next middleware component that should be invoked.
  • Constructor: The constructor takes a RequestDelegate named next as a parameter. This delegate points to the next middleware in the pipeline. The passed delegate is assigned to the _next field, allowing the current middleware to call the next one in the sequence.
  • Invoke Method: The Invoke method is the core of any middleware component. It is called by the ASP.NET Core framework for each HTTP request. The method takes an HttpContext object as a parameter, which represents all HTTP-specific information about an individual HTTP request.
  • await _next(httpContext): This line asynchronously invokes the next middleware in the pipeline, passing along the HttpContext object. By calling _next, the middleware defers control to the subsequent middleware, allowing the request to progress further through the pipeline.
  • catch (TimeoutException): This block catches any TimeoutException thrown by the downstream middleware or the application code. A TimeoutException typically indicates that a task or operation has not been completed in an expected time frame.
  • Response Handling: Before modifying the response, it checks if the response has not already started using httpContext.Response.HasStarted. This is crucial because headers and status codes can only be modified before any part of the response body is written. If the response has not started, the middleware:
    1. Clears any existing content in the response by calling httpContext.Response.Clear().
    2. Sets the HTTP status code to 504 (Gateway Timeout) to indicate that the server, acting as a gateway or proxy, did not receive a timely response from an upstream server.
    3. Write a custom error message to the response body explaining the issue.
Register the Middleware

Then register this middleware in your Program.cs file:

app.UseMiddleware<TimeoutMiddleware>();

Modifying the Sample Controller:
using Microsoft.AspNetCore.Mvc;
namespace ReturnTypeAndStatusCodes.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class SampleController : ControllerBase
    {
        [HttpGet]
        public IActionResult GetResource()
        {
            throw new TimeoutException("The operation took longer than the allowed time.");
        }
    }
}
Response:

Using Custom Middleware to Handle 504 Gateway Timeout Error in ASP.NET Core Web API

Causes of a 504 Gateway Timeout Error
  • Network Issues: The most common cause is Network Issues between your server and the upstream server it’s trying to communicate with.
  • Server Overload: The upstream server might be overloaded and unable to handle the request in a timely manner.
  • Faulty Firewall Configurations: Sometimes, firewall or security configurations can block or delay communications between servers.
  • DNS Issues: Incorrect DNS configurations can lead to your server being unable to resolve the address of the upstream service.
  • Timeout Configurations: If the timeout settings for the upstream request are too short, this can lead to premature 504 errors.
Handling 504 Errors in ASP.NET Core Web API

To handle 504 Gateway Timeout errors effectively in an ASP.NET Core Web API, consider the following strategies:

  • Error Handling Middleware: Implement custom middleware to catch and log 504 errors. This can help in diagnosing whether the issue is within your control or due to external services.
  • Increase Timeout Settings: If the issue is related to short timeout periods, consider increasing the timeout settings for your HTTP client requests in your API.
  • Retry Mechanisms: Implement retry logic for requests to upstream services. 
  • Monitoring and Alerts: Utilize application performance monitoring (APM) tools to track these errors. Setting up alerts for 504 errors can help in quickly identifying and responding to issues.
  • Communicate with Upstream Services: If a particular service is consistently causing 504 errors, communication with the service provider is necessary. They might be unaware of the issues or could provide guidance on mitigating them.

In the next article, I will discuss Model Binding Techniques in ASP.NET Core Web API with Examples. In this article, I try to explain How to Return 504 Gateway Timeout HTTP Status Code in ASP.NET Core Web API with Examples. I hope you enjoy this article “504 Gateway Timeout HTTP Status Code in ASP.NET Core Web API”.

2 thoughts on “504 HTTP Status Code in ASP.NET Core Web API”

Leave a Reply

Your email address will not be published. Required fields are marked *