Thinking about the microservices architecture pattern leads us to think of the API gateway. So, let's disccuss a bit and implement an API gateway using the Ocelot framework.
I've read two great articles, the microservices.io and the Microsoft documentation that help me a lot to understand the use of the API gateway. I also implemented an API gateway on my open source project Storefront Community.
Briefly an API gateway is an entry point for all or our services. This allow us to have a single domain for all of our APIs, rather than having a subdomain for each of them. With the subdomains we have the concern about SSL for each API, frontend connecting to several APIs generating more effort to deal with authorization, among others.
The Ocelot is an open source API gateway framework for .NET. Once we have finished implementing our API gateway we will achieve this:
Instead of this (without API gateway):
For authorization we will use the ASP.NET Core Identity, but we will discuss this in a next post.
So, let's start. I'm using .NET Core CLI and I presume that you already have the .NET Core SDK installed.
First create a folder to the project using de command mkdir
and go to it using the command cd
:
mkdir ApiGateway
cd ApiGateway
Inside the ApiGateway
folder let's create an empty web project:
dotnet new web
Then add the Ocelot package to the project:dotnet add package Ocelot
The ApiGateway.csproj
file should look like this:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp2.2</TargetFramework>
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Ocelot" Version="13.5.2" />
</ItemGroup>
</Project>
Still in the root folder of the project let's create the ocelot.json
configuration file with the following content:
{
"GlobalConfiguration": {
"BaseUrl": "http://localhost:5000"
},
"ReRoutes": [
{
"UpstreamPathTemplate": "/mocky/{path}",
"UpstreamHttpMethod": [
"Get",
"Post",
"Put",
"Delete",
"Options"
],
"DownstreamPathTemplate": "/v2/{path}",
"DownstreamScheme": "http",
"DownstreamHostAndPorts": [
{
"Host": "www.mocky.io",
"Port": 80
}
]
}
]
}
I will explain what means each property but you may also refer to Ocelot documentation:
GlobalConfiguration.BaseUrl
: The URL from where our API gateway is running.ReRoutes
: Configuration of all routing of one request to the other APIs.ReRoutes.UpstreamPathTemplate
: The route pattern to match an API.ReRoutes.UpstreamHttpMethod
: Defines the HTTP verbs that will be routed by this configuration.ReRoutes.DownstreamPathTemplate
: The variable we create to pass to the next route. Could be any name and more than one, e.g. /foo/{var1}/data/{var2}
.ReRoutes.DownstreamScheme
: The protocol we are using. In this case http
.ReRoutes.DownstreamHostAndPorts
: The host and port where the target API is running.The result is: every request using the methods GET
, POST
, PUT
, DELETE
and OPTIONS
from http://localhost:5000/mocky/{paht}
will be routed to http://www.mocky.io/v2/{path}
(do not confuse with redirect). Where the path
can be any value and will be passed to the target API.
Now we need our API gateway to read the configuration file ocelot.json
. We will do this through the Program
class and for that, we will replace the content of the Program.cs
file with the following:
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
namespace ApiGateway
{
public sealed class Program
{
public static void Main(string[] args)
{
CreateWebHostBuilder(args).Build().Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((host, config) =>
{
config.AddJsonFile("ocelot.json");
})
.UseStartup<Startup>();
}
}
In order for our API gateway to use Ocelot we need to configure it in the Startup
class. Replace the content of the Startup.cs
file with the following:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Ocelot.DependencyInjection;
using Ocelot.Middleware;
namespace ApiGateway
{
public sealed class Startup
{
public readonly IConfiguration _configuration;
public Startup(IConfiguration configuration)
{
_configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddOcelot(_configuration);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseOcelot().Wait();
}
}
}
Now, let's run our API gateway (by default at http://localhost:5000
):
dotnet run
When you access http://localhost:5000/mocky/5185415ba171ea3a00704eed
from your browser you should get:
{"hello": "world"}
And what is mocky.io? Is an fake RESTful API where we can mock JSON responses.