Last active
July 12, 2016 21:59
-
-
Save jamescrowley/4c2648cba97bf0b6c030 to your computer and use it in GitHub Desktop.
Global OWIN handling of errors & page not found
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class Startup | |
{ | |
public void Configuration(IAppBuilder app) | |
{ | |
app | |
.Use<StatusCodeFromExceptionMiddleware>() | |
.UseNancy(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class RethrowInternalServerErrorHandler : IStatusCodeHandler | |
{ | |
public bool HandlesStatusCode(HttpStatusCode statusCode, NancyContext context) | |
{ | |
Exception exception; | |
if (!context.TryGetException(out exception) || exception == null) | |
{ | |
return false; | |
} | |
return statusCode == HttpStatusCode.InternalServerError; | |
} | |
public void Handle(HttpStatusCode statusCode, NancyContext context) | |
{ | |
Exception innerException = ((Exception)context.Items[NancyEngine.ERROR_EXCEPTION]).InnerException; | |
ExceptionDispatchInfo | |
.Capture(innerException) | |
.Throw(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class RethrowPageNotFoundErrorHandler : IStatusCodeHandler | |
{ | |
public bool HandlesStatusCode(HttpStatusCode statusCode, NancyContext context) | |
{ | |
return statusCode == HttpStatusCode.NotFound; | |
} | |
public void Handle(HttpStatusCode statusCode, NancyContext context) | |
{ | |
// have to throw exception here, as otherwise the status code | |
// is not passed outside of Nancy (even with Passthrough enabled) | |
throw new PageNotFoundException(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class StatusCodeFromExceptionMiddleware : OwinMiddleware | |
{ | |
public StatusCodeFromExceptionMiddleware(OwinMiddleware next) : base(next) | |
{ | |
} | |
public override async Task Invoke(IOwinContext context) | |
{ | |
try | |
{ | |
await Next.Invoke(context); | |
} | |
catch (Exception ex) | |
{ | |
OnError(context, ex.InnerException); | |
} | |
} | |
static void OnError(IOwinContext context, Exception ex) | |
{ | |
context.Response.StatusCode = (int)GetStatusCode(ex); | |
if (ShouldRenderFriendlyErrorPage(context)) | |
{ | |
RenderFriendlyErrorPage(context); | |
} | |
} | |
static HttpStatusCode GetStatusCode(Exception ex) | |
{ | |
if (ex is PageNotFoundException) | |
{ | |
return HttpStatusCode.NotFound; | |
} | |
return HttpStatusCode.InternalServerError; | |
} | |
static bool ShouldRenderFriendlyErrorPage(IOwinContext context) | |
{ | |
var acceptHeader = context.Request.Headers.GetCommaSeparatedValues("Accept") ?? new string[] {}; | |
var ranges = acceptHeader.Select(MediaRange.FromString).ToList(); | |
foreach (var item in ranges) | |
{ | |
if (item.Matches("application/json")) | |
return false; | |
if (item.Matches("text/json")) | |
return false; | |
if (item.Matches("text/html")) | |
return true; | |
} | |
return true; | |
} | |
static void RenderFriendlyErrorPage(IOwinContext context) | |
{ | |
context.Response.ContentType = "text/html"; | |
if (context.Response.StatusCode == 404) | |
context.Response.Write(NotFoundHtml); | |
else | |
context.Response.Write(ServerErrorHtml); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment