Skip to content
This repository has been archived by the owner on Jul 17, 2018. It is now read-only.

HTTP Gateway

Christian Weiss edited this page May 14, 2017 · 4 revisions

The package C3.ServiceFabric.HttpServiceGateway contains the actual gateway. It uses the package C3.ServiceFabric.HttpCommunication for the communication with the services. Please look at the corresponding document in this wiki to learn more about it. It is important to understand that package if you want to change the options related to the communication.

The gateway is implemented as an ASP.NET Core middleware called HttpServiceGatewayMiddleware.

Features

The gateway has the following features:

Resolving HTTP based services

The Service Fabric SDK contains classes for resolving services which use one of the built-in communication channels. (ServiceProxy, ActorProxy, WcfCommunicationClientFactory). However if your services use HTTP you have to manually resolve the endpoint by using the lower-level classes like ServicePartitionResolver.

The gateway contains an HTTP implementation of ICommunicationClientFactory for resolving HTTP-based services. (see C3.ServiceFabric.HttpCommunication for details)

Transparent retry logic

The classes ServiceProxy and ActorProxy from the SDK implement transparent retry logic in case of failures (e.g. because a node went down or the service returned a timeout). If you are using HTTP, you are on your own again.

This gateway implements the retry functionality of ICommunicationClientFactory for HTTP. (see C3.ServiceFabric.HttpCommunication for details)

Forwarding requests to the service

After the target service address was resolved, the incoming request is forwarded to the target service by copying all request headers and the request body. (see HttpServiceGatewayMiddleware for details)

Support for multiple services

Since this project is implemented as an ASP.NET Core middleware, you can use the IApplicationBuilder.Map() feature to bind services to different paths of your gateway. You can e.g. map "/service1" to "InternalService1" and "/service2" to "InternalService2". (see samples/HttpGateway/Startup.cs for details)

You can also use this feature to integrate the middleware into an existing application.

Proxy Headers

Since your original client now no longer talks directly to the target service, the target service doesn't get the original IP address of the client and it also doesn't know about the original URL which was requested by the client.

For this reason, the gateway adds standard proxy headers to pass this information to the target services. It implements the new "Forwarded" HTTP header and the non-standard headers X-Forwarded-For, X-Forwarded-Host, X-Forwarded-Proto.

It also sets a custom header called X-Forwarded-PathBase which contains the segment of the path under which the gateway hosts the service (e.g. "/service1").

This way, services can adjust their absolute URLs accordingly. See this page for an example.

How to use

There is a sample project calledsamples/HttpGateway that shows how to use this library.

Install the package

The package is available on NuGet: C3.ServiceFabric.HttpServiceGateway.

Add Service Fabric HTTP Communication

This package relies on C3.ServiceFabric.HttpCommunication which must be configured in your Startup.ConfigureServices() method. Please look at the document HTTP Communication for a detailed explanation.

If you want to use the HttpCommunicationClient with the default options, just add the following snippet to your ConfigureServices() method:

services.AddServiceFabricHttpCommunication();

Retry behavior, timeouts and so on are configured through the HttpCommunicationOptions-class. Please look at the wiki page HTTP Communication for details.

Direct configuration of a single gateway middleware

If you want to configure each service through code or if you need maximum flexibility, you can configure the gateway middleware through the class HttpServiceGatewayOptions, which has the following properties:

  • ServiceName: Name of the service within Service Fabric. (e.g. fabric:/MyApp/MyService)
  • ListenerName: This property must be used to set the HTTP endpoint name if the ServiceManifest.xml contains multiple endpoints. If the service only contains one endpoint, this property is optional.
  • ServicePartitionKeyResolver: Delegate for resolving the partition key for partitioned services.

The gateway middleware can be added to your request pipeline by calling one of the RunHttpServiceGateway extension methods on IApplicationBuilder in your Startup.Configure()-method:

// this would forward every request to the service. this way, your application can only handle one service.
app.RunHttpServiceGateway("fabric:/GatewaySample/HttpService");

// ... this only forwards requests on a certain path. This is the simplest case for non-partitioned services.
app.RunHttpServiceGateway("/service1", "fabric:/GatewaySample/HttpService");

// ... pass an instance of HttpServiceGatewayOptions for more options (e.g. to define the ServicePartitionKeyResolver)
app.RunHttpServiceGateway("/service", new HttpServiceGatewayOptions
{
    ServiceName = new Uri("fabric:/GatewaySample/HttpService"),
    ServicePartitionKeyResolver = (context) =>
    {
        string namedPartitionKey = context.Request.Query["partitionKey"];
        return new ServicePartitionKey(namedPartitionKey);
    }
});

// ... if you need to do multiple things within the path branch, you can use app.Map():
app.Map("/service", appBuilder =>
{
    appBuilder.RunHttpServiceGateway(new HttpServiceGatewayOptions
    {
        ServiceName = new Uri("fabric:/GatewaySample/HttpService")
    });
});

IConfiguration based configuration for multiple gateway middleware instances

The gateway can also be configured through a Microsoft.Extensions.Configuration-based mechanism. This allows you to read the configuration for multiple services from e.g. a file.

This mechanism offers the following configuration options for each service:

  • PathMatch: The path on the gateway that should be used for forwarding requests to the service.
  • ServiceName: Name of the service within Service Fabric. (e.g. fabric:/MyApp/MyService)
  • ListenerName: This property must be used to set the HTTP endpoint name if the ServiceManifest.xml contains multiple endpoints. If the service only contains one endpoint, this property is optional.

Note that this mechanism doesn't allow you to specify a ServicePartitionKeyResolver since this must be a delegate. If you need this, use the RunHttpServiceGateway extension methods.

An example JSON-file for this IConfiguration-based setup would be:

{
  "GatewayServices": [
    {
      "PathMatch": "/some-service1",
      "ServiceName": "fabric:/MyApp/SomeService1"
    },
    {
      "PathMatch": "/some-service2",
      "ServiceName": "fabric:/MyApp/SomeService2",
      "ListenerName": "OwinListener"
    }
  ]
}

In this case, the gateway middleware can be added to your request pipeline by calling one of the RunHttpServiceGateways extension methods on IApplicationBuilder in your Startup.Configure()-method:

// this configures one or many gateway instances based on the Configuration system (e.g. file-based).
app.RunHttpServiceGateways(Configuration.GetSection("GatewayServices"));

// this configures one or many gateway instances based on a list of configuration entries.
var services = new List<HttpServiceGatewayConfigurationEntry>
{
    new HttpServiceGatewayConfigurationEntry("/another-service1", "fabric:/MyApp/AnotherService1"),
    new HttpServiceGatewayConfigurationEntry("/another-service2", "fabric:/MyApp/AnotherService2", "OwinListener")
};
app.RunHttpServiceGateways(services);

"HttpGateway" sample project

Have a look at the HttpGateway-sample project for a working example of this library.