【问题标题】:What would it take to build a simple proxy server using ServiceStack? [closed]使用 ServiceStack 构建一个简单的代理服务器需要什么? [关闭]
【发布时间】:2014-02-21 21:21:01
【问题描述】:

我想知道在 ServiceStack 上/使用 ServiceStack 构建代理服务会有多困难。考虑到 ServiceStack 使用 Redis / 序列化 / 等的速度有多快,以及总体上实现堆栈是多么简单,这似乎很诱人。还有人尝试这个吗?这有多难?

【问题讨论】:

  • 这需要“编写代码” - 开始吧!但是为什么要使用 ServiceStack 呢?我以前用过它,但对于真正的代理服务器(例如Squid),它似乎“做得太多”,或者更确切地说“是为不同的目的而设计的”。代理确实需要与直接网络请求非常接近和舒适......并且可以通过各种方式完成存储。
  • 为什么?首先,出于问题中提到的原因。它的底层组件非常快,并且可以在 Windows 和 Linux 上流畅地运行(通过 Mono)。恕我直言,那里没有一个好的 C#/.NET 代理项目,偶尔需要一个可以以编程方式/不同于 Squid 之类的方式调整的代理。
  • ServiceStack 已经是一个中间层(即 SS 本身依赖一个特定的较低级别的服务/接口),它需要 编写代码 来完成这样的任务。 “使用 XYZ 构建一个简单的代理服务器需要什么?” - 这里没有合适的问题。我想只需要一个小时左右就能搞定一个非常基本的代理。如果你愿意,就去做吧。
  • 直接使用像 SS 这样的中间层进行像 non-trivial 代理这样的低级操作的一个问题是,它不一定取代直接正确处理请求(毕竟,它主要基于 Web 服务端点) - 例如过去的基本请求,无论如何它可能需要一个自定义的 HttpHandlerModule。当然,您可以使用 ServiceStack 拥有的所有有趣的东西;但是您可以直接使用大多数库/组件,或者可以使用完全不同的库或访问策略。
  • @FredLackey:好主意。我无法忍受 Squid 或 Linux。拥有一个基于 C# 的代理服务器项目会很棒。在后端使用 Redis 真的会很快。

标签: servicestack


【解决方案1】:

ServiceStack v4.5.10 中添加了一个新的Proxy Feature,大大简化了创建代理的过程,您只需注册一个插件即可创建代理,例如:

Plugins.Add(new ProxyFeature(
    matchingRequests: req => req.PathInfo.StartsWith("/proxy"),
    resolveUrl:req => $"http://remote.server.org" + req.RawUrl.Replace("/proxy","/")) 
{
    // Use TransformResponse to rewrite response returned
    TransformResponse = async (res, responseStream) => 
    {
        using (var reader = new StreamReader(responseStream, Encoding.UTF8))
        {
            var responseBody = await reader.ReadToEndAsync();
            var replacedBody = responseBody.Replace(
                "http://remote.server.org",
                "https://external.domain.com/proxy");
            return MemoryStreamFactory.GetStream(replacedBody.ToUtf8Bytes());
        }
    }
})

这会将您的 ServiceStack 实例中对 /proxy 的所有请求填充到 http://remote.server.org

手动创建反向代理

ServiceStack's Request Pipeline 中的第一个条目让您注册 Raw ASP.NET IHttpHandlers,它可以执行原始 ASP.NET 处理程序并接管执行来自 ServiceStack 的请求。

这将允许您通过将 use an ASP.NET IHttpHandler proxy like this 注册为您的 AppHost 来使用它,例如:

this.RawHttpHandlers.Add(httpReq =>
    httpReq.PathInfo.StartsWith("/proxy")
        ? new ReverseProxy()
        : null);                

这将告诉 ServiceStack 使用自定义 ReverseProxy IHttpHandler 执行以 /proxy 开头的请求。

如果您想在 ServiceStack 的自托管中使用它,您还必须更改 ReverseProxy 以继承 ServiceStack 方便的 HttpAsyncTaskHandler 基类(或仅实现 IServiceStackHandler),例如:

public class ReverseProxy : HttpAsyncTaskHandler
{
    public override void ProcessRequest(IRequest req, IResponse res, 
        string operationName)
    {
        var httpReq = (IHttpRequest)req; //Get HTTP-specific Interfaces
        var httpRes = (IHttpResponse)res;

        // Create a connection to the Remote Server to redirect all requests
        var server = new RemoteServer(httpReq, httpRes);
        // Create a request with same data in navigator request
        HttpWebRequest request = server.GetRequest();

        // Send the request to the remote server and return the response
        HttpWebResponse response = server.GetResponse(request);
        byte[] responseData = server.GetResponseStreamBytes(response);

        // Send the response to client
        res.ContentType = response.ContentType;
        res.OutputStream.Write(responseData, 0, responseData.Length);
        server.SetContextCookies(response); // Handle cookies to navigator

        res.EndHttpHandlerRequest(); // End Request
    }

    public override void ProcessRequest(HttpContextBase context)
    {
        var httpReq = context.ToRequest("CustomAction");
        ProcessRequest(httpReq, httpReq.Response, "CustomAction");
    }

    ....
}

您还必须重构示例中 RemoteServer 的实现,以使用 ServiceStack 的 IHttpRequest / IHttpResponse 接口。

如果需要,您还可以通过以下方式访问底层 ASP.NET(或 HttpListener)请求对象:

var aspNetReq = httpReq.OriginalRequest as HttpRequestBase; 
var aspNetRes = httpRes.OriginalResponse as HttpResponseBase; 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-22
    • 1970-01-01
    • 2015-11-09
    • 1970-01-01
    • 2015-10-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多