c# - ServiceStack Proxy 特性代码优化

标签 c# proxy servicestack

我的任务是为内部系统创建代理。代理需要为每个请求添加一个基本身份验证 header ,并记录它和响应。

我正在使用 ServiceStack 的 Proxy Feature 插件,但感觉代码是重复的,因为我对每个操作执行以下操作:

Plugins.Add(new ProxyFeature(matchingRequests: req => req.PathInfo.ToLower().StartsWith("/opretaftale"), resolveUrl: req => gensamOpretaftaleUrl)
{
    ProxyRequestFilter = (req, httpWebRequest) =>
    {
        try
        {
            httpWebRequest.AddBasicAuth(clientId, clientPassword);
        }
        catch (System.Exception ex)
        {
            Log.Error(ex, "...");
        }
    },

    TransformRequest = async (res, requestStream) =>
    {
        using (var reader = new StreamReader(requestStream, Encoding.UTF8))
        {
            var requestBody = await reader.ReadToEndAsync();
            Log.Information("request: " + requestBody);
            return MemoryStreamFactory.GetStream(requestBody.ToUtf8Bytes());
        }
    },

    TransformResponse = async (res, responseStream) =>
    {
        using (var reader = new StreamReader(responseStream, Encoding.UTF8))
        {
            var responseBody = await reader.ReadToEndAsync();
            Log.Information("response: " + responseBody);
            return MemoryStreamFactory.GetStream(responseBody.ToUtf8Bytes());
        }
    }
});

是否可以对多个请求执行相同的操作,我真的需要 TransformRequest/TransformResponse 来记录请求/响应吗?我很难从 ProxyRequestFilter/ProxyResponseFilter 操作获取流内容...

谢谢!

最佳答案

您可以使用普通的 C# 进行重构,例如通过将内联 lambda 提取到通用方法中并改为引用它们:

private Func<IHttpRequest, Stream, Task<Stream>> TransformRequest =>
    async (res, requestStream) => {
        using var reader = new StreamReader(requestStream, Encoding.UTF8);
        var requestBody = await reader.ReadToEndAsync();
        Log.Information("request: " + requestBody);
        return MemoryStreamFactory.GetStream(requestBody.ToUtf8Bytes());
    };

哪里可以:

Plugins.Add(new ProxyFeature(...) {
    TransformRequest = TransformRequest,
});

尽管在这种情况下您可能希望创建一个构造 PluginFeature 的工厂方法,例如:

ProxyFeature CreateProxyRule(Func<IHttpRequest, bool> matchingRequests,
    Func<IHttpRequest, string> resolveUrl)
{
    return new ProxyFeature(matchingRequests, resolveUrl)
    {
        ProxyRequestFilter = (req, httpWebRequest) => {
            httpWebRequest.AddBasicAuth(clientId, clientPassword);
        },
        TransformRequest = async (res, requestStream) => {
            using var reader = new StreamReader(requestStream, Encoding.UTF8);
            var requestBody = await reader.ReadToEndAsync();
            Log.Information("request: " + requestBody);
            return MemoryStreamFactory.GetStream(requestBody.ToUtf8Bytes());
        },
        TransformResponse = async (res, responseStream) => {
            using var reader = new StreamReader(responseStream, Encoding.UTF8);
            var responseBody = await reader.ReadToEndAsync();
            Log.Information("response: " + responseBody);
            return MemoryStreamFactory.GetStream(responseBody.ToUtf8Bytes());
        }
    };
}

然后只需传入在不同代理之间可配置的所有部分,例如:

Plugins.Add(CreateProxyRule(
    matchingRequests: req => req.PathInfo.ToLower().StartsWith("/opretaftale"), 
    resolveUrl: req => gensamOpretaftaleUrl));

由于 HTTP 请求通常是只进流,如果您想记录正文,您需要缓冲请求/响应,因此对于代理请求,您需要在 TransformRequest/TransformResponse 中执行此操作。

如果你只是想记录 ServiceStack 请求,你可以注册一个 Request Logger启用 EnableRequestBodyTracking,例如:

Plugins.Add(new RequestLogsFeature { EnableRequestBodyTracking = true });

哪个会 enable Request Buffering为了能够缓冲请求主体以进行日志记录和反序列化。

关于c# - ServiceStack Proxy 特性代码优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62657540/

相关文章:

c# - 运行基本的 orleans 应用程序时出现异常

c# - ServiceStack.RequestFilterAsyncAttribute 错误 : System. ArgumentNullException : Value cannot be null. 参数名称:方​​法

ubuntu - 如何在保持相同 url 的情况下代理 nginx 请求

web-services - 具有基本身份验证和 SetCredentials 的 ServiceStack Web 服务

c# - 帮助解决此 Linq 查询(多对多连接)

C# 可空字符串错误

c# - 从 3 个通用类型中推断出 2 个

node.js - Nodejs请求代理流(mjpeg)连接永远不会结束

java - 使用java代码更改浏览器的互联网设置

nginx - 使用 jwilder nginx-proxy,如何将子目录 url 代理传递到特定容器?