根据要求修改 OWIN/Katana PhysicalFileSystem 页面

Modify OWIN/Katana PhysicalFileSystem page on request

我有一个 self-hosted 应用程序使用 OWIN 提供基本的网络服务器。配置的关键部分是以下行:

appBuilder.UseFileServer(new FileServerOptions {
    FileSystem = new PhysicalFileSystem(filePath)
});

这提供了 filePath 中列出的静态文件供浏览,这一切都按预期工作。

然而,我 运行 遇到了这样一种情况,我想在 request-by-request 的基础上稍微修改其中一个文件。特别是,我想从文件系统加载文件的 "normal" 版本,根据传入的 Web 请求的 headers 稍微更改它,然后 return 将更改后的版本发送给客户端原来的。所有其他文件应保持不变。

我该怎么做?

好吧,我不知道这是否好的方法,但它似乎有效:

internal class FileReplacementMiddleware : OwinMiddleware
{
    public FileReplacementMiddleware(OwinMiddleware next) : base(next) {}

    public override async Task Invoke(IOwinContext context)
    {
        MemoryStream memStream = null;
        Stream httpStream = null;
        if (ShouldAmendResponse(context))
        {
            memStream = new MemoryStream();
            httpStream = context.Response.Body;
            context.Response.Body = memStream;
        }

        await Next.Invoke(context);

        if (memStream != null)
        {
            var content = await ReadStreamAsync(memStream);
            if (context.Response.StatusCode == 200)
            {
                content = AmendContent(context, content);
            }
            var contentBytes = Encoding.UTF8.GetBytes(content);
            context.Response.Body = httpStream;
            context.Response.ETag = null;
            context.Response.ContentLength = contentBytes.Length;
            await context.Response.WriteAsync(contentBytes, context.Request.CallCancelled);
        }
    }

    private static async Task<string> ReadStreamAsync(MemoryStream stream)
    {
        stream.Seek(0, SeekOrigin.Begin);
        using (var reader = new StreamReader(stream, Encoding.UTF8))
        {
            return await reader.ReadToEndAsync();
        }
    }

    private bool ShouldAmendResponse(IOwinContext context)
    {
        // logic
    }

    private string AmendContent(IOwinContext context, string content)
    {
        // logic
    }
}

将其添加到管道中静态文件中间件之前的某处。