API Gateway using Ocelot.NET and Consul

This article will show how to setup API Gateway using Ocelot.Net and Consul.

Step 1

Step 2

In C# Rest Services (Each service needs to be configured like below).

Install Nuget Packages,

Inject like this in all services (we need to configure service discovery)

services.AddSingleton<IConsulClient, ConsulClient>(p => new ConsulClient(consulConfig =>
{
    consulConfig.Address = new Uri("http://127.0.0.1:8500");
}));

Using the Consul,

public static IApplicationBuilder UseConsul(this IApplicationBuilder app)
{

    var consulClient = app.ApplicationServices.GetRequiredService<IConsulClient>();
    var lifetime = app.ApplicationServices.GetRequiredService<IApplicationLifetime>();
    var settings = app.ApplicationServices.GetRequiredService<ConfigurationMaster>();


    if (!(app.Properties["server.Features"] is FeatureCollection features))
    {
        return app;
    } 
     
    var serviceName = settings.ServiceDiscoveryConfig.NameOfService;
    var serviceId = settings.ServiceDiscoveryConfig.IdOfService;
    var uri = new Uri($"http://{settings.ServiceDiscoveryConfig.Host}");

    var registration = new AgentServiceRegistration()
    {
        ID = serviceId,
        Name = serviceName,
        Address = $"localhost",
        Port = uri.Port,
        Tags = new[] { $"urlprefix-/{settings.ServiceDiscoveryConfig.IdOfService}" }
    };

   var result= consulClient.Agent.ServiceDeregister(registration.ID).Result;
    result = consulClient.Agent.ServiceRegister(registration).Result;

    lifetime.ApplicationStopping.Register(() =>
    {
        consulClient.Agent.ServiceDeregister(registration.ID).Wait();
    });

    return app;
}

Update App Settings (JSON) File:

"ServiceDiscoveryConfig": {
  "Host": "localhost:7201",
  "Port": {Hosted Service Port},
  "NameOfService": "{Service Name Unique}",
  "IdOfService": "{Service ID Our Wish}"
}

Update the Gateway Settings File as Follow in (GlobalConfiguration):

"ServiceDiscoveryProvider": {
  "Host": "localhost",
  "Port": 8500,
  "Type": "PollConsul",
  "PollingInterval": 100
  //"Type": "Consul" - Each Request it will update information
  /*
    Type
      Consul, means that Ocelot will get service information from consul per request
      PollConsul, means that Ocelot will poll Consul for latest service information
  */
}

Sample Gateway End Point Configuration:

{
  "Routes": [
    {
      "UseServiceDiscovery": true,
      "DownstreamPathTemplate": "/v1/{everything}",
      "DownstreamScheme": "http",
      "ServiceName": "Sample API",
      "UpstreamPathTemplate": "/v1/{everything}",
      "UpstreamHttpMethod": [ "GET" ],
      "Priority": 1,
      "ReRoutesCaseSensitive": false,
      "LoadBalancerOptions": {
        "Type": "LeastConnection"
      }
    },
    {
      "DownstreamPathTemplate": "/v1/{everything}",
      "DownstreamScheme": "http",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 7201
        }
      ],
      "UpstreamPathTemplate": "/api/v2/{everything}",
      "UpstreamHttpMethod": [ "GET", "POST" ],
      "Priority": 1
    }
  ],
  "GlobalConfiguration": {
    "BaseUrl": "https://localhost:7123",
    "ServiceDiscoveryProvider": {
      "Host": "localhost",
      "Port": 8500,
      "Type": "PollConsul",
      "PollingInterval": 100
      //"Type": "Consul" - Each Request it will update information
      /*
        Type
          Consul, means that Ocelot will get service information from consul per request
          PollConsul, means that Ocelot will poll Consul for latest service information
      */
    }
  }
}