I'm trying to get my self-hosted service using Nancy to return json formatted errors upon an uncaught exception. However, I am always getting the response:
{"readyState":4,"status":404,"statusText":"error"}
(below is the amalgamation of several examples across the net).
My bootstrapper contains the following:
pipelines.OnError.AddItemToEndOfPipeline((ctx, exc) =>
{
if (exc is Exception)
{
// this is always executed upon failure to handle an exception.
Log.Error("Unhandled error on request: " + context.Request.Url + " : " + exc.Message, exc);
JsonResponse response = new JsonResponse(string.Format("{0}:{1}", exc, exc.Message), new DefaultJsonSerializer());
response.StatusCode = HttpStatusCode.InternalServerError;
return response;
}
return HttpStatusCode.InternalServerError;
});
I have a StatusCodeHandler:
public class JsonErrorStatusCodeHandler : IStatusCodeHandler
{
public bool HandlesStatusCode(HttpStatusCode statusCode, NancyContext context)
{
return statusCode == HttpStatusCode.InternalServerError;
}
public void Handle(HttpStatusCode statusCode, NancyContext context)
{
var exception = context.GetException();
if (exception != null)
{
// never executed
}
// this is executed
JsonResponse response = new JsonResponse("wtf"), new DefaultJsonSerializer());
response.StatusCode = HttpStatusCode.InternalServerError;
context.Response = response;
}
Although I've verified that the code in OnError
and Handle
is executed (see comments), my clients still receive 404. I've also tried using
var exception = context.Items[NancyEngine.ERROR_EXCEPTION] as Exception;
instead of
var exception = context.GetException();
with no luck.
Gah, so this was a CORS issue.
I'm automatically adding the CORS headers to the response:
protected override void RequestStartup(TinyIoCContainer container, IPipelines pipelines, NancyContext context)
{
pipelines.AfterRequest.AddItemToEndOfPipeline((ctx) =>
{
ctx.Response.WithHeader("Access-Control-Allow-Origin", "*")
.WithHeader("Access-Control-Allow-Methods", "POST,GET")
.WithHeader("Access-Control-Allow-Headers", "Accept, Origin, Content-type");
});
pipelines.OnError.AddItemToEndOfPipeline((ctx, exc) =>
{
if (exc != null)
{
throw exc;
}
return HttpStatusCode.InternalServerError;
});
base.RequestStartup(container, pipelines, context);
}
But when the response is replaced in my status code handler I need to set these headers again:
public class JsonErrorStatusCodeHandler : IStatusCodeHandler
{
public bool HandlesStatusCode(HttpStatusCode statusCode, NancyContext context)
{
if (statusCode != HttpStatusCode.InternalServerError)
{
return false;
}
var exception = context.GetException();
return exception != null;
}
public void Handle(HttpStatusCode statusCode, NancyContext context)
{
var exception = context.GetException();
JsonResponse response = new JsonResponse(string.Format("{0}:{1}", exception, exception.Message), new DefaultJsonSerializer());
response.StatusCode = HttpStatusCode.InternalServerError;
context.Response = response;
context.Response.WithHeader("Access-Control-Allow-Origin", "*")
.WithHeader("Access-Control-Allow-Methods", "POST,GET")
.WithHeader("Access-Control-Allow-Headers", "Accept, Origin, Content-type");
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With