简体   繁体   中英

How to create simple IIS site to redirect all calls to another service?

I've written a REST API service in Delphi, which runs as its own stand-alone service. I also have IIS hosting some sites on port 80 . I would like to use port 80 for my REST API as well, but since I'm already using it in IIS, I'm forced to use another port.

What I'd like to do to overcome this is create a very simple site in IIS (Preferably with ASP.NET/C#) which simply redirects all incoming HTTP requests to this other service running on a different port. This would allow me to take advantage of binding multiple sites under the same port in IIS. I don't want to perform a literal "redirect", but just replicate the request to the desired server, and respond back - as if user was connecting to original REST server. Only, without having to use a non-standard port. The URL on the client-side shouldn't change (as what you normally see with an HTTP Redirect).

Essentially, if user makes such a request:

http://api.mydomain.com/SomeReq?some=query

It will turn around and make a corresponding request to the real server, and carry over the entire URI - just a different port number:

http://api.mydomain.com:8664/SomeReq?some=query

How can I accomplish this?

Using ASP.NET Web API it is pretty simple to write such a proxy server. All you need is a delegating handler:

public class ProxyHandler : DelegatingHandler
{
    private static HttpClient client = new HttpClient();

    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request,
        CancellationToken cancellationToken)
    {
        // strip the /proxy portion of the path when making the request
        // to the backend node because our server will be made to listen
        // to :80/proxy/*   (see below when registering the /proxy route)
        var forwardUri = new UriBuilder(request.RequestUri.AbsoluteUri.Replace("/proxy", string.Empty));

        // replace the port from 80 to the backend target port
        forwardUri.Port = 8664;
        request.RequestUri = forwardUri.Uri;

        if (request.Method == HttpMethod.Get)
        {
            request.Content = null;
        }

        // replace the Host header when making the request to the 
        // backend node
        request.Headers.Host = "localhost:8664";
        var response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
        return response;
    }
}

and finally all that's left is to register this handler:

config.Routes.MapHttpRoute(
    name: "Proxy",
    routeTemplate: "proxy/{*path}",
    handler: HttpClientFactory.CreatePipeline(
        innerHandler: new HttpClientHandler(),
        handlers: new DelegatingHandler[]
        {
            new ProxyHandler()
        }
    ),
    defaults: new { path = RouteParameter.Optional },
    constraints: null
);

In this example the proxy will listen on :80/proxy/* and forward it to :8664/* .

So if you send the following request to your Web API:

GET http://localhost:80/proxy/SomeReq?some=query HTTP/1.1
Host: localhost:80
Connection: close

it will be translated to:

GET http://localhost:8664/SomeReq?some=query HTTP/1.1
Host: localhost:8664
Connection: close

This will also work for POST and other verbs made to :80/proxy/* .

Obviously if you want to turn your entire webserver into a proxy and listen to :80/* then you could get rid of the /proxy prefix that I used in my example.

This being said, this is only a proof-of-concept proxy server. In a real production system I would off-load this task to a full blown frontend load balancer such as nginx or HAProxy which are designed exactly for this purpose. Then both your IIS and Delphi application could listen on arbitrary ports and your nginx configured to listen to port 80 and forward the traffic to the backend node(s) based on some patterns. Using a load balancer also has other benefits as if you are having multiple backend nodes, it will distribute the load between them and also give you the possibility to make updates to your applications without any downtime (because you have full control over which node is in the load balancer pool).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM