Ocelot - The API Gateway

Ocelot Aug 01, 2020

This article is series of article which will explain need of API Gateway and how to use Ocelot with ASP.net Core application as API gateway.

What is Ocelot

Ocelot is an Open source API GW for the ASP.net core platform . It acts as primary entry point to you back-end services . API GW are also known as backend for frontends (since front end only knows about API GW endpoints not actual services).

Behind the scene Ocelot library contains numerous middleware in a pre-defined order. When request reaches Ocelot middleware it inspect and manipulate request object per need, you can also write your own custom middleware {More details in next article} to modify per your project need.

I will build working application to showcase Ocelot capabilities such as

  • Base setup
  • Response aggregation
  • Rate limiting
  • Service discovery
  • Custom middleware
  • Logging
  • Securing API GW using IdentityServer4

BASE SETUP

We will be using ASP.net core 3.1 for this project. Open Visual Studio 2019 and create a new blank solution .

Usually we create separate solution for Microservices but for sake of simplicity I am keeping all services in same solution . These are sample services with single endpoints to show case how request is being handled at GW and how response is being returned .

Create a folder name Microservices and add two asp.net core webapi projects. You can name them Catalog & Customer API.

Open project and add new controller CatalogController and add following code .

namespace CatalogAPI.Services.Controllers
{
    [Route("api/[controller]")]
    public class CatalogController : Controller
    {
        [HttpGet]
        public IEnumerable<string> Get()
        {
            return new string[] { "Google Pixel", "Apple iPhone", "OnePlus Nord","Moto razor" };
        }
    }
}

Repeat same step for CustomerAPI.Services project and add following code

namespace CustomerAPI.Services.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class CustomerController : ControllerBase
    {
        [HttpGet]
        public IEnumerable<string> Get()
        {
            return new string[] { "Kylie J", "Justin B", "Cardy B", "Justin T" };
        }
    }
}

so back to original topic , lets setup Gateway . Add Empty Project under Gateway folder

Install Ocelot package

Install-Package Ocelot

Lets configure our empty webAPI app to use as API GW. Add a json file to project which will be used for Ocelot configuration.

Open Program.cs and update code as given below

 public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
              Host.CreateDefaultBuilder(args)
                 .ConfigureWebHostDefaults(webBuilder =>
                 {
                     webBuilder.UseStartup<Startup>();
                 })
                 .ConfigureAppConfiguration((hostingContext, config) =>
                 {
                     config
                     .SetBasePath(hostingContext.HostingEnvironment.ContentRootPath)
                     .AddJsonFile("OcelotConfiguration.json", optional: false, reloadOnChange: true);
                 });
    }
Gateway Program.cs

Startup.cs

public void ConfigureServices(IServiceCollection services)
        {
            services.AddOcelot();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapGet("/", async context =>
                {
                    await context.Response.WriteAsync("Hello World!");
                });
            });

            app.UseOcelot();
        }

Most important step to run your api gateway is route mapping, this is where your GW will decide which request needs to be send which downstream api. Open OcelotConfiguration.json and update following code

{
  "Routes": [
    {
      "DownstreamPathTemplate": "/api/catalog",
      "DownstreamScheme": "https",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 44343
        }
      ],
      "UpstreamPathTemplate": "/catalog",
      "UpstreamHttpMethod": [ "GET" ]
    },
    {
      "DownstreamPathTemplate": "/api/customer",
      "DownstreamScheme": "https",
      "DownstreamHostAndPorts": [
        {
          "Host": "localhost",
          "Port": 44303
        }
      ],
      "UpstreamPathTemplate": "/customer",
      "UpstreamHttpMethod": [ "GET" ]
    }
  ]
}
Change port number per your machine/project configuration

UpstreamPath -> Exposed endpoint on GW side and where client will send request

DownstreamPath -> Actual backend service end point

When request comes to https://ocelotapigateway.xyz.com/customer end point then ocelot automatically maps this request to https://localhost:44303/api/customer. This is all configuration based and you do not read to write single line of code for same.

Before you test out make sure you have set multiple startup project in VS.

I am using postman to test these request

Catalog request -

Here request is being redirected to CatalogAPI.Services and we are getting response accordingly .

Customer request-

With this we are done with foundational base setup for ocelot and we make more changes and make it generic in upcoming articles .

Download working code from https://github.com/DMehro/OcelotAPIGW

Tags