From 9005a972ac640fe3ee8f88e8d2dda08e16c41c05 Mon Sep 17 00:00:00 2001 From: Jonathan Channon Date: Thu, 26 May 2016 12:46:08 +0100 Subject: [PATCH] added try catch calls to statuscode handlers (#2457) --- src/Nancy/NancyEngine.cs | 15 ++++++- test/Nancy.Tests/Unit/NancyEngineFixture.cs | 47 +++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/Nancy/NancyEngine.cs b/src/Nancy/NancyEngine.cs index 3e5f00632f..0082c9dc8a 100644 --- a/src/Nancy/NancyEngine.cs +++ b/src/Nancy/NancyEngine.cs @@ -2,6 +2,7 @@ { using System; using System.Collections.Generic; + using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -252,7 +253,19 @@ private void CheckStatusCodeHandler(NancyContext context) return; } - handler.Handle(context.Response.StatusCode, context); + try + { + handler.Handle(context.Response.StatusCode, context); + } + catch (Exception ex) + { + if (defaultHandler == null) + { + throw; + } + + defaultHandler.Handle(context.Response.StatusCode, context); + } } private async Task InvokeRequestLifeCycle(NancyContext context, CancellationToken cancellationToken, IPipelines pipelines) diff --git a/test/Nancy.Tests/Unit/NancyEngineFixture.cs b/test/Nancy.Tests/Unit/NancyEngineFixture.cs index 577677a5a7..d5536c7900 100644 --- a/test/Nancy.Tests/Unit/NancyEngineFixture.cs +++ b/test/Nancy.Tests/Unit/NancyEngineFixture.cs @@ -339,6 +339,53 @@ public async Task Should_invoke_status_handler_if_supported_status_code() A.CallTo(() => this.statusCodeHandler.Handle(A.Ignored, A.Ignored)).MustHaveHappened(Repeated.Exactly.Once); } + [Fact] + public async Task Should_catch_exception_inside_status_code_handler_and_return_default_error_response() + { + // Given + A.CallTo(() => this.requestDispatcher.Dispatch(A.Ignored, A.Ignored)) + .Returns(new Response() { StatusCode = HttpStatusCode.InternalServerError }); + + var statusCodeHandlers = new[] + { + this.statusCodeHandler, + new DefaultStatusCodeHandler(this.negotiator, this.environment), + }; + + var engine = + new NancyEngine(this.requestDispatcher, this.contextFactory, statusCodeHandlers, + A.Fake(), + new DisabledStaticContentProvider(), this.negotiator, this.environment) + { + RequestPipelinesFactory = ctx => new Pipelines() + }; + + var request = new Request("GET", "/", "http"); + + A.CallTo(() => this.statusCodeHandler.HandlesStatusCode(A.Ignored, A.Ignored)).Returns(true); + A.CallTo(() => this.statusCodeHandler.Handle(A.Ignored, A.Ignored)) + .Throws(); + + // When + await engine.HandleRequest(request); + + // Then + this.context.Response.StatusCode.ShouldEqual(HttpStatusCode.InternalServerError); + } + + [Fact] + public async Task Should_throw_exception_if_no_default_status_code_handler_present_when_custom_status_code_handler_throws() + { + // Given + var request = new Request("GET", "/", "http"); + A.CallTo(() => this.statusCodeHandler.HandlesStatusCode(A.Ignored, A.Ignored)).Returns(true); + A.CallTo(() => this.statusCodeHandler.Handle(A.Ignored, A.Ignored)) + .Throws(); + + // When,Then + await AssertAsync.Throws(async () => await this.engine.HandleRequest(request)); + } + [Fact] public async Task Should_set_status_code_to_500_if_route_throws() {