# Implementing an API Gateway For Microservices With YARP

> A client application shouldn't need to know about every service in your system. An API gateway acts as a reverse proxy, accepting API calls and forwarding them to the appropriate service. I'll show you how to build one with YARP, including authentication and rate limiting.

Published: 2023-07-08. Author: Milan Jovanović.

Canonical: https://milanjovanovic.tech/blog/implementing-an-api-gateway-for-microservices-with-yarp

An API gateway is a single entry point that accepts client calls and forwards them to the right microservice.
YARP is Microsoft's open source reverse proxy library, and you configure its routes and clusters from application settings.
Because the gateway is an ASP.NET Core application, you can also apply authentication and rate limiting there.

Large **Microservice-based** systems can consist of tens or even hundreds of individual services.
A client application needs to have all of this information to be able to make requests to the relevant **microservice** directly.

However, this has numerous issues, such as security concerns, increased complexity, and coupling.

We can solve this by introducing an **API gateway** that acts as a **reverse proxy** to accept API calls from the client application and forward them to the appropriate service.

The **API gateway** also enforces security and ensures scalability and high availability.

In this week's newsletter, I'll show you how to implement an **API gateway** for your **microservices system** using the **YARP reverse proxy**.

Here's what we will cover:

- Difference between **API gateway** and **reverse proxy**
- Installing and configuring **YARP**
- Creating an **API gateway** with **YARP**
- **Authentication** and **rate limiting** on the **API gateway**

Let's dive in.

## What's The Difference Between an API Gateway And a Reverse Proxy?

A **reverse proxy** and an **API gateway** are similar concepts, but they serve different purposes.

A **reverse proxy** acts as an intermediary between clients and servers.
The clients can only call the backend servers through the **reverse proxy**, which forwards the request to the appropriate server.
It hides the implementation details of individual servers inside the internal network.

A **reverse proxy** is commonly used for:

- Load balancing
- Caching
- Security
- SSL termination

![Reverse proxy routing web and mobile client requests to multiple application servers](https://milanjovanovic.tech/blogs/mnw_045/reverse_proxy.png)

An **API gateway** is a specific type of **reverse proxy** designed for managing APIs.
It acts as a single entry point for API consumers to the various backend services.

The key characteristics of an **API gateway** are:

- Request routing and composition
- Request/response transformations
- Authentication and authorization
- Rate limiting
- Monitoring

Also, note that an **API gateway** can perform [**load balancing**](https://milanjovanovic.tech/blog/horizontally-scaling-aspnetcore-apis-with-yarp-load-balancing) and other functionalities mentioned for reverse proxies.

Now let's see how to use a **reverse proxy** to implement an **API gateway**.

## Installing And Configuring YARP

**YARP** (Yet Another Reverse Proxy) is a library developed by Microsoft to address the needs of various teams needing to build a **reverse proxy**.
It's open source and built with .NET, so it integrates nicely with the existing ecosystem.

Let's install `Yarp.ReverseProxy` **NuGet** package to get started:

```powershell
Install-Package Yarp.ReverseProxy
```

Next, we're going to call:

- `AddReverseProxy` to add the required services for **YARP**
- `LoadFromConfig` to load the **reverse proxy** configuration from application settings
- `MapReverseProxy` to introduce the **reverse proxy** middleware

```csharp {3-4,8}
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddReverseProxy()
    .LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));

var app = builder.Build();

app.MapReverseProxy();

app.Run();
```

We need to tell the **YARP** reverse proxy how to route the incoming requests to the individual microservices.

**YARP** uses the concept of `Routes` to represent request patterns for the proxy and `Clusters` to represent the services to forward those requests.

```json {3,6}
{
    "ReverseProxy": {
        "Routes": {
            ...
        },
        "Clusters": {
            ...
        }
    }
}
```

Here's an example **YARP configuration** with a `{**catch-all}` pattern that will route all incoming requests to the one destination server.

```json
{
  "ReverseProxy": {
    "Routes": {
      "ROUTE_NAME": {
        "ClusterId": "CLUSTER_NAME",
        "Match": {
          "Path": "{**catch-all}"
        }
      }
    },
    "Clusters": {
      "CLUSTER_NAME": {
        "Destinations": {
          "destination1": {
            "Address": "https://www.milanjovanovic.tech/"
          }
        }
      }
    }
  }
}
```

## Implementing an API Gateway With YARP

We can use **YARP** to build an **API gateway** by providing the configuration for the services we want to route traffic to.

I created a sample [API gateway implementation with YARP](https://github.com/m-jovanovic/yarp-api-gateway-sample) on GitHub, so you can give it a try.
The system has two services, the `Users.Api` and `Products.Api`, which are .NET 7 applications.

If a request comes in matching the `/users-service/{**catch-all}`, for example `/users-service/users`, it will be routed to the `users-cluster`.
The same logic applies for the `products-cluster`. We can apply more advanced transformations through the `Transforms` section.

```json
{
  "ReverseProxy": {
    "Routes": {
      "users-route": {
        "ClusterId": "users-cluster",
        "Match": {
          "Path": "/users-service/{**catch-all}"
        },
        "Transforms": [{ "PathPattern": "{**catch-all}" }]
      },
      "products-route": {
        "ClusterId": "products-cluster",
        "Match": {
          "Path": "/products-service/{**catch-all}"
        },
        "Transforms": [{ "PathPattern": "{**catch-all}" }]
      }
    },
    "Clusters": {
      "users-cluster": {
        "Destinations": {
          "destination1": {
            "Address": "https://localhost:5201/"
          }
        }
      },
      "products-cluster": {
        "Destinations": {
          "destination1": {
            "Address": "https://localhost:5101/"
          }
        }
      }
    }
  }
}
```

We now have a functioning **API gateway** built with **YARP**, routing requests to two individual services.

But what else can we do with **YARP**?

## Adding Authentication

The **API gateway** can enforce [**authentication**](https://milanjovanovic.tech/blog/implementing-api-gateway-authentication-with-yarp) and **authorization** at the entry point to the system before letting authenticated requests proceed.

And **YARP** supports integrating with the existing authentication & authorization middleware.

You first need to define an **authorization policy**:

```csharp
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("authenticated", policy =>
        policy.RequireAuthenticatedUser());
});
```

And call `UseAuthentication` and `UseAuthorization` to add the respective middleware to the request pipeline.
It's important to add them before calling `MapReverseProxy`.

```csharp {1,3}
app.UseAuthentication();

app.UseAuthorization();

app.MapReverseProxy();
```

Now all you have to do is add the `AuthorizationPolicy` section to the reverse proxy configuration:

```json {3}
"users-route": {
  "ClusterId": "users-cluster",
  "AuthorizationPolicy": "authenticated",
  "Match": {
    "Path": "/users-service/{**catch-all}"
  },
  "Transforms": [
    { "PathPattern": "{**catch-all}" }
  ]
}
```

**YARP** will forward most credentials to the proxied services, such as cookies or bearer tokens because it might be important to identify the user in the individual microservices.

## Adding Rate Limiting

You can also use an **API gateway** to introduce **rate limiting** to your system.
It's a technique to limit the number of requests to your API to **improve security** and reduce the load on the servers.

You can learn more about [how to use rate limiting in .NET here.](https://milanjovanovic.tech/blog/how-to-use-rate-limiting-in-aspnet-core)

As you can already guess, **YARP** supports the native **rate limiting** mechanism added in .NET 7.

All you need to do is define a **rate limit policy**:

```csharp
builder.Services.AddRateLimiter(rateLimiterOptions =>
{
    rateLimiterOptions.AddFixedWindowLimiter("fixed", options =>
    {
        options.Window = TimeSpan.FromSeconds(10);
        options.PermitLimit = 5;
    });
});
```

Then you need to call `UseRateLimiter` to add the rate limiter middleware to the request pipeline.
It's important to do it before calling `MapReverseProxy`.

```csharp {1}
app.UseRateLimiter();

app.MapReverseProxy();
```

And then, you can apply rate limiting to the desired route using the `RateLimiterPolicy` section in the reverse proxy configuration:

```json {3}
"products-route": {
  "ClusterId": "products-cluster",
  "RateLimiterPolicy": "fixed",
  "Match": {
    "Path": "/products-service/{**catch-all}"
  },
  "Transforms": [
    { "PathPattern": "{**catch-all}" }
  ]
}
```

## In Summary

An **API gateway** is a critical component for a robust **microservices system** implementation.

And **YARP** is an excellent option if you want to build an **API gateway** with .NET.

I created a sample API gateway implementation with YARP, which you can find [here.](https://github.com/m-jovanovic/yarp-api-gateway-sample)
The system consists of two APIs, and the API gateway is configured to route requests between them.
It also implements:

- [Authentication](https://microsoft.github.io/reverse-proxy/articles/authn-authz.html)
- [Rate limiting](https://milanjovanovic.tech/blog/how-to-use-rate-limiting-in-aspnet-core)

In this newsletter, we only scratched the surface of what's possible with **YARP**.

Here are some useful resources if you want to learn more:

- [YARP docs](https://microsoft.github.io/reverse-proxy/articles/index.html)
- [Load balancing](https://microsoft.github.io/reverse-proxy/articles/load-balancing.html)
- [Session affinity](https://microsoft.github.io/reverse-proxy/articles/session-affinity.html)
- [Request/response transformations](https://microsoft.github.io/reverse-proxy/articles/transforms.html)

That's all for today.

Hope it was helpful.

**Today's action step:**
Download the [source code](https://github.com/m-jovanovic/yarp-api-gateway-sample) for the sample application implementing an API gateway with YARP, and take it for a spin.
You can challenge yourself by creating multiple instances of a single service and configuring load balancing with the various load balancing algorithms.

---

## Frequently asked questions

### What is YARP in .NET?

YARP (Yet Another Reverse Proxy) is an open-source reverse proxy library developed by Microsoft and built with .NET. You add it to an ASP.NET Core application as a NuGet package and configure routing through application settings, so it integrates nicely with the existing ecosystem.

### What is the difference between an API gateway and a reverse proxy?

A reverse proxy is an intermediary between clients and backend servers, commonly used for load balancing, caching, security, and SSL termination. An API gateway is a specific type of reverse proxy designed for managing APIs, adding request routing and composition, transformations, authentication, rate limiting, and monitoring.

### Why do microservices need an API gateway?

Without one, client applications must know about every individual service to call it directly, which creates security concerns, complexity, and coupling. An API gateway gives clients a single entry point, forwards traffic to the appropriate service, and enforces security at the edge.

### How do you configure YARP in ASP.NET Core?

Install the Yarp.ReverseProxy package, call AddReverseProxy with LoadFromConfig to read configuration from application settings, then call MapReverseProxy. The configuration defines Routes, which match request path patterns, and Clusters, which list the destination services those requests are forwarded to.

### Can YARP handle authentication and authorization?

Yes. YARP integrates with the standard ASP.NET Core authentication and authorization middleware. You define an authorization policy, add UseAuthentication and UseAuthorization before MapReverseProxy, and reference the policy on a route with the AuthorizationPolicy setting. YARP forwards credentials like cookies and bearer tokens to the proxied services.

### Can you add rate limiting to a YARP API gateway?

Yes. YARP supports the native rate limiting mechanism that .NET 7 added. Define a policy with AddRateLimiter, call UseRateLimiter before MapReverseProxy, and apply it to a route with the RateLimiterPolicy setting in the reverse proxy configuration.
