Back to: ASP.NET Core Web API Tutorials
504 HTTP Status Code in ASP.NET Core Web API
In this article, I will discuss how to Return the 504 Gateway Timeout HTTP Status Code in an ASP.NET Core Web API Application with Examples. Please read our previous article on how to Return the 503 Service Unavailable HTTP Status Code in an ASP.NET Core Web API application with Examples.
What is 504 HTTP Status Code?
The 504 HTTP Status Code, also known as the “Gateway Timeout” error, indicates that a server while acting as a gateway or proxy, did not receive a timely response from an upstream server it needed to access in order to complete the request. This typically means that the upstream server is either down or not responding in time. This can occur in various scenarios where one server is acting as an intermediary between the client and another server.
504 HTTP Status Code in ASP.NET Core Web API
In the context of an ASP.NET Core Web API, a 504 Status Code typically indicates that the API server, acting as a reverse proxy, made a request to another server (such as a database, external service, or API) and did not receive a response in time. This is usually a sign of network issues, server overload, or issues with the upstream service.
Common Reasons for a 504 HTTP Status Code in ASP.NET Core Web API
The following are some of the Common Reasons for a 504 HTTP Status Code in ASP.NET Core Web API:
- Upstream Server Timeout: If our ASP.NET Core Web API application calls another service (e.g., database, external API) and that service does not respond in a timely manner because it is down or unreachable, a 504 Error will result. The upstream server is taking too long to respond.
- Network Issues: Network connectivity issues between the ASP.NET Core application and the upstream servers (like database servers and external APIs) can lead to 504 errors.
- Resource Limitations: If the upstream server is overloaded with requests or under heavy load, it may fail to respond quickly enough, causing a timeout. That means the upstream server has insufficient resources (CPU, memory).
- Configuration Issues: Misconfiguration of the gateway or proxy server settings, such as Incorrect timeout settings, can also result in a 504 error.
How to Return 504 HTTP Status Code in ASP.NET Core Web API
In ASP.NET Core Web API, we can return a 504 HTTP Status Code in several ways, such as within a controller action, middleware, or exception handling.
Returning a 504 Status Code Directly:
You can return a 504 status code directly from an action method by using the StatusCode method of the ControllerBase class. For a better understanding, please modify the Sample Controller as follows. The following code is self-explained, so please read the comment lines for a better understanding:
using Microsoft.AspNetCore.Mvc; using System.Text.Json; namespace ReturnTypeAndStatusCodes.Controllers { [Route("api/[controller]")] [ApiController] public class SampleController : ControllerBase { // Declares a private readonly field to hold the HttpClient instance private readonly HttpClient _httpClient; // Constructor to initialize the HttpClient through dependency injection public SampleController(HttpClient httpClient) { // Assigns the injected HttpClient to the private field _httpClient = httpClient; } // Specifies that this action responds to HTTP GET requests [HttpGet] public async Task<IActionResult> GetResource() { // URL of the external API to call var requestUrl = "https://httpstat.us/504"; try { // Sends a GET request to the specified URL var response = await _httpClient.GetAsync(requestUrl); // Checks if the response status code is 504 Gateway Timeout if (response.StatusCode == System.Net.HttpStatusCode.GatewayTimeout) { // Creates a custom response object for the 504 error var customResponse = new { Code = 504, Message = "The request timed out waiting for an external service.", }; // Serializes the custom response object to JSON var responseJson = JsonSerializer.Serialize(customResponse); // Returns a 504 status code with the custom JSON response return StatusCode(504, responseJson); } // Checks if the response from the external API was successful if (response.IsSuccessStatusCode) { // Reads the response content as a string var content = await response.Content.ReadAsStringAsync(); // Returns the content with a 200 OK status return Ok(content); } else { // Returns the status code from the external API response along with an error message return StatusCode((int)response.StatusCode, "Failed to retrieve the resource."); } } catch (Exception ex) // Catches any exceptions that occur during the process { // Optionally log the exception details here (e.g., using a logging framework) // Creates a custom response object for the 500 internal server error var customResponse = new { Code = 500, Message = $"Internal Server Error: {ex.Message}", }; // Serializes the custom response object to JSON var responseJson = JsonSerializer.Serialize(customResponse); // Returns a 500 status code with the custom JSON response return StatusCode(500, responseJson); } } } }
Register HttpClient in the DI Container
In your Program.cs file, register the HttpClient service as follows:
// Register HttpClient
builder.Services.AddHttpClient();
Now, if you access the above endpoint, you will get the 504 Gateway Timeout response as shown in the below image:
Using Custom Middleware to Handle 504 Gateway Timeout Error in ASP.NET Core Web API:
If you want to apply this behavior globally, consider implementing a custom middleware component. Middleware inspects and modifies HTTP requests and responses flowing through the application processing pipeline. So, create a class file named GatewayTimeoutMiddleware.cs within the Models folder 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. The following code is self-explained, so please read the comments lines for a better understanding:
using System.Text.Json; namespace ReturnTypeAndStatusCodes.Middleware { // Middleware class to handle HTTP 504 Gateway Timeout errors globally public class GatewayTimeoutMiddleware { // Field to hold the next middleware in the pipeline private readonly RequestDelegate _next; // Constructor to initialize the middleware with the next middleware in the pipeline public GatewayTimeoutMiddleware(RequestDelegate next) { // Assign the next middleware to the private field _next = next; } // Method to handle the HTTP request public async Task Invoke(HttpContext context) { try { // Proceed to the next middleware component await _next(context); } catch (HttpRequestException ex) when (ex.StatusCode == System.Net.HttpStatusCode.GatewayTimeout) { // Catch HttpRequestException when the status code is 504 Gateway Timeout if (!context.Response.HasStarted) { // Check if the response has not already started context.Response.Clear(); // Clear the existing response context.Response.StatusCode = StatusCodes.Status504GatewayTimeout; // Set the status code to 504 context.Response.ContentType = "application/json"; // Set the response content type to JSON // Create a custom response object with code and message var customResponse = new { Code = 504, Message = "Server did not receive a timely response from an upstream server." }; // Serialize the custom response object to a JSON string var responseJson = JsonSerializer.Serialize(customResponse); // Write the JSON response to the HTTP response await context.Response.WriteAsync(responseJson); } } catch (Exception ex) { // Catch all other exceptions if (!context.Response.HasStarted) { // Check if the response has not already started context.Response.Clear(); // Clear the existing response context.Response.StatusCode = StatusCodes.Status500InternalServerError; // Set the status code to 500 context.Response.ContentType = "application/json"; // Set the response content type to JSON // Create a custom response object with code, message, and details var customResponse = new { Code = 500, Message = "Internal Server Error", Details = ex.Message // Include exception message in the response }; // Serialize the custom response object to a JSON string var responseJson = JsonSerializer.Serialize(customResponse); // Write the JSON response to the HTTP response await context.Response.WriteAsync(responseJson); } } } } }
Register the Middleware
Then register this middleware in your Program.cs file:
app.UseMiddleware<GatewayTimeoutMiddleware>();
Modifying the Sample Controller:
Next, modify the Sample Controller as follows:
using Microsoft.AspNetCore.Mvc; namespace ReturnTypeAndStatusCodes.Controllers { [Route("api/[controller]")] [ApiController] public class SampleController : ControllerBase { // Declares a private readonly field to hold the HttpClient instance private readonly HttpClient _httpClient; // Constructor to initialize the HttpClient through dependency injection public SampleController(HttpClient httpClient) { // Assigns the injected HttpClient to the private field _httpClient = httpClient; } // Defines an action method to handle HTTP GET requests [HttpGet] public async Task<IActionResult> GetResource() { // URL of the external API to call var requestUrl = "https://httpstat.us/504"; // Sends a GET request to the specified URL and awaits the response var response = await _httpClient.GetAsync(requestUrl); // Ensures the response status code is successful; otherwise, throws an exception response.EnsureSuccessStatusCode(); // Reads the response content as a string var content = await response.Content.ReadAsStringAsync(); // Returns the content with a 200 OK status return Ok(content); } } }
Response:
How Do We Troubleshoot a 504 HTTP Status Code in ASP.NET Core Web API?
To troubleshoot a 504 error in an ASP.NET Core environment, please follow the below steps:
- Check the Upstream Server: Verify if the upstream server is up and running. Check its health and status. Look into its logs for any errors or issues.
- Network Diagnostics: Test network connectivity between your ASP.NET Core application and the upstream server. Use tools like ping, traceroute, or telnet to diagnose network issues.
- Review Logs: Check the logs of both the API server and the upstream server for any error messages or performance issues. Enable detailed logging in ASP.NET Core to get more information about the request handling process.
- Monitor Performance: Use monitoring tools to check the performance of your upstream server. Ensure that the server is not overloaded and has adequate resources.
- Load Testing: Perform load testing to understand how your API handles high traffic and to identify potential bottlenecks. Use tools like Apache JMeter, k6, or others to simulate load and analyze performance.
- Timeout Settings: Review and adjust the timeout settings in your ASP.NET Core application. Configure appropriate timeout settings for HTTP clients, such as HttpClient in ASP.NET Core.
- Scale Up/Out: Scale up the resources of your upstream server if it’s under heavy load. Scale out by adding more instances to handle the load.
In the next article, I will discuss Model Binding Techniques in ASP.NET Core Web API with Examples. In this article, I will try to explain how to return a 504 Gateway Timeout HTTP Status Code in ASP.NET Core Web API with examples. I hope you enjoy this article.
Hi,Did you updated Web Api Tutorial recently. Please let me know.
Yes. Now, we are updating the content.