Skip to content

Commit e950cf2

Browse files
#653 Adding null check for downstreamResponse (#1334)
* Adding a check for null downstreamResponse, plus tests. * Target-typed new expressions * Remove and Sort Usings * Fix test * Remove usings --------- Co-authored-by: raman-m <[email protected]>
1 parent 5a81cce commit e950cf2

File tree

3 files changed

+83
-23
lines changed

3 files changed

+83
-23
lines changed

src/Ocelot/Responder/Middleware/ResponderMiddleware.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ public async Task Invoke(HttpContext httpContext)
3232
await _next.Invoke(httpContext);
3333

3434
var errors = httpContext.Items.Errors();
35+
var downstreamResponse = httpContext.Items.DownstreamResponse();
3536

3637
// todo check errors is ok
3738
if (errors.Count > 0)
@@ -40,12 +41,14 @@ public async Task Invoke(HttpContext httpContext)
4041

4142
SetErrorResponse(httpContext, errors);
4243
}
44+
else if (downstreamResponse == null)
45+
{
46+
Logger.LogDebug($"Pipeline was terminated early in {MiddlewareName}");
47+
}
4348
else
4449
{
4550
Logger.LogDebug("no pipeline errors, setting and returning completed response");
4651

47-
var downstreamResponse = httpContext.Items.DownstreamResponse();
48-
4952
await _responder.SetResponseOnHttpContext(httpContext, downstreamResponse);
5053
}
5154
}

test/Ocelot.AcceptanceTests/CustomMiddlewareTests.cs

Lines changed: 67 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ public void should_call_pre_query_string_builder_middleware()
2828
_counter++;
2929
await next.Invoke();
3030
},
31-
};
32-
31+
};
32+
3333
var port = RandomPortFinder.GetRandomPort();
3434

3535
var fileConfiguration = new FileConfiguration
@@ -73,8 +73,8 @@ public void should_call_authorization_middleware()
7373
_counter++;
7474
await next.Invoke();
7575
},
76-
};
77-
76+
};
77+
7878
var port = RandomPortFinder.GetRandomPort();
7979

8080
var fileConfiguration = new FileConfiguration
@@ -118,8 +118,8 @@ public void should_call_authentication_middleware()
118118
_counter++;
119119
await next.Invoke();
120120
},
121-
};
122-
121+
};
122+
123123
var port = RandomPortFinder.GetRandomPort();
124124

125125
var fileConfiguration = new FileConfiguration
@@ -163,8 +163,8 @@ public void should_call_pre_error_middleware()
163163
_counter++;
164164
await next.Invoke();
165165
},
166-
};
167-
166+
};
167+
168168
var port = RandomPortFinder.GetRandomPort();
169169

170170
var fileConfiguration = new FileConfiguration
@@ -208,8 +208,8 @@ public void should_call_pre_authorization_middleware()
208208
_counter++;
209209
await next.Invoke();
210210
},
211-
};
212-
211+
};
212+
213213
var port = RandomPortFinder.GetRandomPort();
214214

215215
var fileConfiguration = new FileConfiguration
@@ -253,8 +253,8 @@ public void should_call_pre_http_authentication_middleware()
253253
_counter++;
254254
await next.Invoke();
255255
},
256-
};
257-
256+
};
257+
258258
var port = RandomPortFinder.GetRandomPort();
259259

260260
var fileConfiguration = new FileConfiguration
@@ -286,8 +286,54 @@ public void should_call_pre_http_authentication_middleware()
286286
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
287287
.And(x => x.ThenTheCounterIs(1))
288288
.BDDfy();
289-
}
289+
}
290+
291+
[Fact]
292+
public void should_not_throw_when_pipeline_terminates_early()
293+
{
294+
var configuration = new OcelotPipelineConfiguration
295+
{
296+
PreQueryStringBuilderMiddleware = (context, next) =>
297+
Task.Run(() =>
298+
{
299+
_counter++;
300+
return; // do not invoke the rest of the pipeline
301+
}),
302+
};
303+
304+
var port = RandomPortFinder.GetRandomPort();
290305

306+
var fileConfiguration = new FileConfiguration
307+
{
308+
Routes = new List<FileRoute>
309+
{
310+
new()
311+
{
312+
DownstreamPathTemplate = "/",
313+
DownstreamHostAndPorts = new List<FileHostAndPort>
314+
{
315+
new()
316+
{
317+
Host = "localhost",
318+
Port = port,
319+
},
320+
},
321+
DownstreamScheme = "http",
322+
UpstreamPathTemplate = "/",
323+
UpstreamHttpMethod = new List<string> { "Get" },
324+
},
325+
},
326+
};
327+
328+
this.Given(x => x.GivenThereIsAServiceRunningOn($"http://localhost:{port}", 200, ""))
329+
.And(x => _steps.GivenThereIsAConfiguration(fileConfiguration))
330+
.And(x => _steps.GivenOcelotIsRunning(configuration))
331+
.When(x => _steps.WhenIGetUrlOnTheApiGateway("/"))
332+
.Then(x => _steps.ThenTheStatusCodeShouldBe(HttpStatusCode.OK))
333+
.And(x => x.ThenTheCounterIs(1))
334+
.BDDfy();
335+
}
336+
291337
[Fact(Skip = "This is just an example to show how you could hook into Ocelot pipeline with your own middleware. At the moment you must use Response.OnCompleted callback and cannot change the response :( I will see if this can be changed one day!")]
292338
public void should_fix_issue_237()
293339
{
@@ -296,14 +342,14 @@ public void should_fix_issue_237()
296342
var httpContext = (HttpContext)state;
297343

298344
if (httpContext.Response.StatusCode > 400)
299-
{
345+
{
300346
Debug.WriteLine("COUNT CALLED");
301347
Console.WriteLine("COUNT CALLED");
302348
}
303349

304350
return Task.CompletedTask;
305-
};
306-
351+
};
352+
307353
var port = RandomPortFinder.GetRandomPort();
308354

309355
var fileConfiguration = new FileConfiguration
@@ -367,8 +413,8 @@ public void Dispose()
367413
public class FakeMiddleware
368414
{
369415
private readonly RequestDelegate _next;
370-
private readonly Func<object, Task> _callback;
371-
416+
private readonly Func<object, Task> _callback;
417+
372418
public FakeMiddleware(RequestDelegate next, Func<object, Task> callback)
373419
{
374420
_next = next;
@@ -377,10 +423,10 @@ public FakeMiddleware(RequestDelegate next, Func<object, Task> callback)
377423

378424
public async Task Invoke(HttpContext context)
379425
{
380-
await _next(context);
381-
426+
await _next(context);
427+
382428
context.Response.OnCompleted(_callback, context);
383429
}
384430
}
385431
}
386-
}
432+
}

test/Ocelot.UnitTests/Responder/ResponderMiddlewareTests.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,17 @@ public void should_return_any_errors()
4949
.BDDfy();
5050
}
5151

52+
[Fact]
53+
public void should_not_call_responder_when_null_downstream_response()
54+
{
55+
this._responder.Reset();
56+
this.Given(x => x.GivenTheHttpResponseMessageIs(null))
57+
.When(x => x.WhenICallTheMiddleware())
58+
.Then(x => x.ThenThereAreNoErrors())
59+
.Then(x => x._responder.VerifyNoOtherCalls())
60+
.BDDfy();
61+
}
62+
5263
private void WhenICallTheMiddleware()
5364
{
5465
_middleware.Invoke(_httpContext).GetAwaiter().GetResult();

0 commit comments

Comments
 (0)