Nancy: Need ability to modify response generated in OnError pipeline

Created on 21 Nov 2016  路  1Comment  路  Source: NancyFx/Nancy

Prerequisites

  • [x] I have written a descriptive issue title
  • [x] I have verified that I am running the latest version of Nancy
  • [x] I have searched open and closed issues to ensure it has not already been reported

Description

I've implemented a custom correlation ID strategy. I first check to see if there is a Correlation-ID header present in a request. If there isn't, I create a correlation ID. Then I assign the correlation ID to a NancyContext.Items entry.

The issue I'm running into is with the OnError pipeline. In my browsing of NancyFx's source code, I was unable to find a place to modify the response generated by my OnError handler. That means I am unable to add a Correlation-ID response header. The AfterRequest pipeline does not exhibit this same limitation.

// Fails because context.Response is null
context.Response.WithHeader("Correlation-ID", correlationId.Value.ToString("D"));

One possible design would be to call the AfterRequest pipeline after the OnError pipeline has executed, and pass the delegate a value that allows AfterRequest handlers to determine if there was an error (perhaps pass the relevant Exception, or null?)

Steps to Reproduce

N/A

System Configuration

N/A

Most helpful comment

Using http://bytefish.de/blog/consistent_error_handling_with_nancy as a guide, I managed to work around this with this implementation:

protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines)
{
    var responseNegotiator = container.Resolve<IResponseNegotiator>();

    pipelines.BeforeRequest.AddItemToEndOfPipeline(BeforeRequestProcessCorrelationIds);
    pipelines.AfterRequest.AddItemToEndOfPipeline(AfterRequestProcessCorrelationIds);
    pipelines.OnError.AddItemToEndOfPipeline((context, exception) => OnErrorWrapInErrorEnvelope(context, exception, responseNegotiator));

    base.ApplicationStartup(container, pipelines);
}

private static dynamic OnErrorWrapInErrorEnvelope(NancyContext context, Exception exception, IResponseNegotiator responseNegotiator)
{
    Log.Error(exception, "An unhandled exception occurred.");

    var responseModel = new ErrorResponseModel
                        {
                            Exception = CreateExceptionModel(exception),
                            Message = "An unhandled exception occurred."
                        };
    Response response = responseNegotiator.NegotiateResponse(responseModel, context);

    AddCorrelationIdsToResponse(context, response);

    return response;
}

>All comments

Using http://bytefish.de/blog/consistent_error_handling_with_nancy as a guide, I managed to work around this with this implementation:

protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines)
{
    var responseNegotiator = container.Resolve<IResponseNegotiator>();

    pipelines.BeforeRequest.AddItemToEndOfPipeline(BeforeRequestProcessCorrelationIds);
    pipelines.AfterRequest.AddItemToEndOfPipeline(AfterRequestProcessCorrelationIds);
    pipelines.OnError.AddItemToEndOfPipeline((context, exception) => OnErrorWrapInErrorEnvelope(context, exception, responseNegotiator));

    base.ApplicationStartup(container, pipelines);
}

private static dynamic OnErrorWrapInErrorEnvelope(NancyContext context, Exception exception, IResponseNegotiator responseNegotiator)
{
    Log.Error(exception, "An unhandled exception occurred.");

    var responseModel = new ErrorResponseModel
                        {
                            Exception = CreateExceptionModel(exception),
                            Message = "An unhandled exception occurred."
                        };
    Response response = responseNegotiator.NegotiateResponse(responseModel, context);

    AddCorrelationIdsToResponse(context, response);

    return response;
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

phillip-haydon picture phillip-haydon  路  10Comments

phillip-haydon picture phillip-haydon  路  3Comments

jchannon picture jchannon  路  9Comments

juniormayhe picture juniormayhe  路  4Comments

epsitec picture epsitec  路  5Comments