Skip to content

Instantly share code, notes, and snippets.

@jamescrowley
Last active July 12, 2016 21:59
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jamescrowley/4c2648cba97bf0b6c030 to your computer and use it in GitHub Desktop.
Save jamescrowley/4c2648cba97bf0b6c030 to your computer and use it in GitHub Desktop.
Global OWIN handling of errors & page not found
public class Startup
{
public void Configuration(IAppBuilder app)
{
app
.Use<StatusCodeFromExceptionMiddleware>()
.UseNancy();
}
}
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();
}
}
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();
}
}
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