Skip to content

Commit 2f97913

Browse files
committed
Merge branch 'jlukawska-feature/603-bad-gateway'
2 parents 77d4bb1 + cdbd8e8 commit 2f97913

File tree

12 files changed

+97
-9
lines changed

12 files changed

+97
-9
lines changed

docs/features/errorcodes.rst

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Http Error Status Codes
2+
=======================
3+
4+
Ocelot will return HTTP status error codes based on internal logic in certain siturations:
5+
- 401 if the authentication middleware runs and the user is not authenticated.
6+
- 403 if the authorisation middleware runs and the user is unauthenticated, claim value not authroised, scope not authorised, user doesnt have required claim or cannot find claim.
7+
- 503 if the downstream request times out.
8+
- 499 if the request is cancelled by the client.
9+
- 404 if unable to find a downstream route.
10+
- 502 if unable to connect to downstream service.
11+
- 500 if unable to complete the HTTP request downstream and the exception is not OperationCanceledException or HttpRequestException.
12+
- 404 if Ocelot is unable to map an internal error code to a HTTP status code.
13+

docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ Thanks for taking a look at the Ocelot documentation. Please use the left hand n
4242
features/loadbalancer
4343
features/delegatinghandlers
4444
features/raft
45+
features/errorcodes
4546

4647
.. toctree::
4748
:maxdepth: 2

src/Ocelot/Errors/OcelotErrorCode.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ public enum OcelotErrorCode
3939
CannotAddPlaceholderError = 34,
4040
CannotRemovePlaceholderError = 35,
4141
QuotaExceededError = 36,
42-
RequestCanceled = 37,
42+
RequestCanceled = 37,
43+
ConnectionToDownstreamServiceError = 38,
4344
}
4445
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using Ocelot.Errors;
2+
using System;
3+
4+
namespace Ocelot.Requester
5+
{
6+
public class ConnectionToDownstreamServiceError : Error
7+
{
8+
public ConnectionToDownstreamServiceError(Exception exception)
9+
: base($"Error connecting to downstream service, exception: {exception}", OcelotErrorCode.ConnectionToDownstreamServiceError)
10+
{
11+
}
12+
}
13+
}

src/Ocelot/Requester/HttpExeptionToErrorMapper.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ namespace Ocelot.Requester
44
using Microsoft.Extensions.DependencyInjection;
55
using System;
66
using System.Collections.Generic;
7+
using System.Net.Http;
78

89
public class HttpExeptionToErrorMapper : IExceptionToErrorMapper
910
{
@@ -28,6 +29,11 @@ public Error Map(Exception exception)
2829
return new RequestCanceledError(exception.Message);
2930
}
3031

32+
if (type == typeof(HttpRequestException))
33+
{
34+
return new ConnectionToDownstreamServiceError(exception);
35+
}
36+
3137
return new UnableToCompleteRequestError(exception);
3238
}
3339
}

src/Ocelot/Responder/ErrorsToHttpStatusCodeMapper.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ public int Map(List<Error> errors)
3838
if (errors.Any(e => e.Code == OcelotErrorCode.UnableToFindDownstreamRouteError))
3939
{
4040
return 404;
41+
}
42+
43+
if (errors.Any(e => e.Code == OcelotErrorCode.ConnectionToDownstreamServiceError))
44+
{
45+
return 502;
4146
}
4247

4348
if (errors.Any(e => e.Code == OcelotErrorCode.UnableToCompleteRequestError))

src/Ocelot/Responder/IErrorsToHttpStatusCodeMapper.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
using Ocelot.Errors;
2-
using System.Collections.Generic;
1+
namespace Ocelot.Responder
2+
{
3+
using System.Net;
4+
using Ocelot.Errors;
5+
using System.Collections.Generic;
36

4-
namespace Ocelot.Responder
5-
{
67
/// <summary>
78
/// Map a list OceoltErrors to a single appropriate HTTP status code
89
/// </summary>

test/Ocelot.AcceptanceTests/HttpTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ public void should_return_response_200_when_using_http_two_point_zero()
141141
}
142142

143143
[Fact]
144-
public void should_return_response_500_when_using_http_one_to_talk_to_server_running_http_two()
144+
public void should_return_response_502_when_using_http_one_to_talk_to_server_running_http_two()
145145
{
146146
var port = RandomPortFinder.GetRandomPort();
147147

@@ -177,7 +177,7 @@ public void should_return_response_500_when_using_http_one_to_talk_to_server_run
177177
.And(x => _steps.GivenThereIsAConfiguration(configuration))
178178
.And(x => _steps.GivenOcelotIsRunning())
179179
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/", httpContent))
180-
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.InternalServerError))
180+
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.BadGateway))
181181
.BDDfy();
182182
}
183183

test/Ocelot.AcceptanceTests/ReturnsErrorTests.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,38 @@ public ReturnsErrorTests()
1616
{
1717
_serviceHandler = new ServiceHandler();
1818
_steps = new Steps();
19+
}
20+
21+
[Fact]
22+
public void should_return_bad_gateway_error_if_downstream_service_doesnt_respond()
23+
{
24+
var configuration = new FileConfiguration
25+
{
26+
ReRoutes = new List<FileReRoute>
27+
{
28+
new FileReRoute
29+
{
30+
DownstreamPathTemplate = "/",
31+
UpstreamPathTemplate = "/",
32+
UpstreamHttpMethod = new List<string> { "Get" },
33+
DownstreamHostAndPorts = new List<FileHostAndPort>
34+
{
35+
new FileHostAndPort
36+
{
37+
Host = "localhost",
38+
Port = 53877,
39+
},
40+
},
41+
DownstreamScheme = "http",
42+
},
43+
},
44+
};
45+
46+
this.Given(x => _steps.GivenThereIsAConfiguration(configuration))
47+
.And(x => _steps.GivenOcelotIsRunning())
48+
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
49+
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.BadGateway))
50+
.BDDfy();
1951
}
2052

2153
[Fact]

test/Ocelot.AcceptanceTests/SslTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public void should_not_dangerous_accept_any_server_certificate_validator()
8989
.And(x => _steps.GivenThereIsAConfiguration(configuration))
9090
.And(x => _steps.GivenOcelotIsRunning())
9191
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
92-
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.InternalServerError))
92+
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.BadGateway))
9393
.BDDfy();
9494
}
9595

0 commit comments

Comments
 (0)