jsonasp.net-corefast-endpoints

How to sign HTTP Response and put it into header?


I use FastEndpoints over ASP.NET Core minimal API and want to sign the response body which is in application/json format.

I think instead of calling SendAsync(MyResponse) I need to:

I'd like to use the same JSON serializer with exactly the same options as if I call SendAsync(MyResponse). And I don't know how to access the serializer from endpoint.

What I tried to do:

I use custom json options like this:

var app = bld.Build();
app
    .UseAuthentication()
    .UseAuthorization()
    .UseFastEndpoints(c =>
    {
        c.Endpoints.RoutePrefix = "api/v1";
        c.Serializer.Options.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.SnakeCaseUpper));
    })
    .UseSwaggerGen()
    ;

Solution

  • a custom send extension method should get the job done nicely. something like the following:

    var bld = WebApplication.CreateBuilder(args);
    bld.Services
       .Configure<JsonOptions>(o => o.SerializerOptions.PropertyNamingPolicy = null)
       .AddFastEndpoints()
       .SwaggerDocument();
    
    var app = bld.Build();
    app.UseFastEndpoints()
       .UseSwaggerGen();
    app.Run();
    
    sealed class MyResponse
    {
        public string Name { get; set; }
    }
    
    sealed class MyEndpoint : Ep.NoReq.Res<MyResponse>
    {
        public override void Configure()
        {
            Get("test");
            AllowAnonymous();
        }
    
        public override async Task HandleAsync(CancellationToken c)
        {
            await this.SendSignedResponse(new MyResponse { Name = "test" });
        }
    }
    
    static class SendExtensions
    {
        public static Task SendSignedResponse<TResponse>(this IEndpoint ep, TResponse dto)
        {
            var jsonOptions = ep.HttpContext.Resolve<IOptions<JsonOptions>>().Value.SerializerOptions;
            var json = JsonSerializer.Serialize(dto, jsonOptions);
            var md5 = BitConverter.ToString(MD5.HashData(Encoding.UTF8.GetBytes(json))).Replace("-", "").ToLower();
    
            ep.HttpContext.MarkResponseStart();
            ep.HttpContext.Response.Headers.Append("x-signature", md5);
    
            return ep.HttpContext.Response.SendStringAsync(json);
        }
    }