使用ServiceStack构建一个简单的代理服务器需要什么?

时间:2014-02-21 21:21:02

标签: servicestack

我想知道使用ServiceStack构建代理服务有多困难。考虑到ServiceStack与Redis /序列化等的速度有多快,以及一般实现堆栈的简单程度,这看起来非常诱人。有人试过这个吗?这有多难?

1 个答案:

答案 0 :(得分:6)

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

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的请求。

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

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;