Custom Response Filter Attributes seem to be getting headers replaced

I have some custom response filters that I’m trying to use to apply header changes on responses. However, it seems that the headers are getting changed/overwritten at a later point. I’ve tried with both GlobalResponseFilters (which has worse results) and now attributes.

Below is full test code that shows the problem. It fails because my Vary headers don’t exist as set. Vary is set to accept only.

[TestFixture()]
public class ResponseFilterTests : BaseServiceTest
{
    protected override AppHostMocked CreateAppHost()
    {
        return (AppHostMocked)new AppHostMocked(typeof(ResponseFilterTests).Assembly)
            .Init()
            .Start(BaseUri);
    }

    [Test]
    public void ResponseFilterIShouldHaveVaryFilterTest()
    {
        using (var client = new JsonHttpClient(BaseUri))
        {
            client.ResponseFilter = message =>
            {
                message.Headers.Vary.Should().Contain("origin");
                message.Headers.Vary.Should().Contain("authorization");            
                message.Headers.CacheControl.Should().Be("no-cache");
            };

            var response = client.Get(new ResponseFilterWithVaryRequest());
            response.Should().Be("Should have vary headers.");

        }
    }
}

[NoCacheResponseFilter]
[VaryResponseFilter]
public class ResponseFilterService : IService
{
    public object Get(ResponseFilterWithVaryRequest withVaryRequest)
    {
        return "Should have vary headers.";
    }
}

public class ResponseFilterWithVaryRequest: IGet, IReturn<string>, IShouldHaveVaryFilter
{
}

public class NoCacheResponseFilterAttribute : ResponseFilterAttribute
{
    public override void Execute(IRequest req, IResponse res, object responseDto)
    {
        res.AddHeader("Cache-Control", "no-cahce");
    }
}

public class VaryResponseFilterAttribute : ResponseFilterAttribute
{
    public override void Execute(IRequest req, IResponse res, object responseDto)
    {
        res.AddHeader(HttpHeaders.Vary, "origin, authorization");
    }
}

You spelt no-cache wrong and you need to inherit Service or move your Response filters to the method.

Inheriting Service base makes no difference with the Vary header. It’s always changed to Accept. I want to avoid moving them into the method as I need this applied globally to over 100 endpoints.

Any other suggestions?

This works in .NET Core but looks like ASP.NET doesn’t support combining multiple Vary headers so you would need to remove the default Vary: Accept header with:

Config.GlobalResponseHeaders.Remove(HttpHeaders.Vary);

In which case you should include Accept which says to have different caches based on the Content-Type.

Otherwise if you always want the same Vary headers returned you can set it once in GlobalResponseHeaders:

SetConfig(new HostConfig {
    GlobalResponseHeaders = {
        [HttpHeaders.Vary] = "accept,origin,authorization"
    }
});

Thanks. Will try this out. I just found the one in HostConfig. It may be all i need.

Both options worked. I’m going to stick with attributes as there are times when I don’t want those headers set.

1 Like