Skip to content
levkovichm edited this page Aug 6, 2026 · 2 revisions

Overview

Easy-Gateway is a Python-based API Gateway that acts as a reverse proxy for your microservices. It exposes a unified entry point, applies middleware (logging, rate limiting), routes requests based on path prefixes, and optionally caches responses using Redis.

Key capabilities:

  • Declarative YAML configuration – no code changes needed to add routes or middleware.
  • Prefix-based routing with automatic path handling.
  • Per-route response caching (Redis-backed) with automatic invalidation on non-GET requests.
  • Built-in rate limiting and request logging.
  • CORS support.
  • Admin panel with Basic Auth for inspecting cache health and gateway status.

Quick Start

  1. Install Easy-Gateway:
uv tool install easy-gateway (recommended)
# or
pip install easy-gateway
  1. Create a minimal configuration file (e.g. gateway.yaml, by default easy_conf.yaml):
server:
  host: "0.0.0.0"
  port: 8000

routes:
  - path: "/bin/*"
    target: "https://httpbin.org/"
  - path: "/users"
    target: "https://api.example.com"

middlewares:
  - name: "LoggingMiddleware"
    enabled: true
  1. Run the gateway:
easy-gateway -c gateway.yaml

Requests to http://localhost:8000/bin/anything will be forwarded to https://httpbin.org/anything, and /users will go to https://api.example.com/users.


Installation

Easy-Gateway requires Python 3.12 or later.

uv tool install easy-gateway (recommended)
# or
pip install easy-gateway

No additional dependencies are required for basic operation. Redis support is optional and enabled only when you configure it.


Configuration Reference

The entire gateway is driven by a single YAML file (default name: easy_conf.yaml if not specified). Below is the complete reference.

Server Settings

server:
  host: "0.0.0.0"   # Bind address
  port: 8000         # Listening port

Redis & Caching

Caching is powered by Redis. Enable it globally, then opt-in per route.

redis:
  enabled: true                # false disables all caching
  url: "redis://localhost:6379"
  expire_time: 300             # Cache TTL in seconds (default: 180)

If you don't have Redis running locally, start it quickly with Docker:

docker run -d --name my-redis -p 6379:6379 redis

How caching works:

  • Only GET requests are cached, and only responses with a 2xx status code.
  • The cache key is constructed as: cache:<path>:<METHOD>:<md5(query_params)>. Different query parameters never collide.
  • The TTL is controlled by redis.expire_time.
  • Any non-GET request (POST, PUT, DELETE, PATCH, etc.) to a cached route automatically invalidates all cache entries for that route prefix. This ensures fresh data after mutations.
  • Cache health is exposed via the /health endpoint.

Enabling cache for a route:

Add cache: true to the route definition:

routes:
  - path: "/pets/*"
    target: "https://petstore.swagger.io/"
    cache: true

Routes

Each route maps an incoming path pattern to a backend service.

routes:
  # Prefix route – matches /bin/anything, /bin/ip, etc.
  - path: "/bin/*"
    target: "https://httpbin.org/"

  # Exact route – matches only /users
  - path: "/users"
    target: "https://api.example.com"

  # Route with caching enabled
  - path: "/pets/*"
    target: "https://petstore.swagger.io/"
    description: "Pets service"
    cache: true

Important routing rules:

  • path: "/prefix/*"prefix route: forwards any request starting with /prefix/ to the target. The target must be a full URL including the protocol (e.g., https://httpbin.org/). The requested path is appended to the target as-is.
  • path: "/exact"exact route: matches only that specific URL. The target must be a base URL without the trailing path. The route path is appended automatically (/users + https://api.example.comhttps://api.example.com/users).
  • description is optional and used for documentation purposes.
  • cache is optional (default false). Enable to cache responses for this route (requires Redis).

Middleware

Middleware adds cross-cutting concerns. Enable them in the middlewares list.

middlewares:
  - name: "LoggingMiddleware"
    enabled: true

  - name: "RateLimitMiddleware"
    enabled: true
    requests_per_minute: 30

Currently available middleware:

Middleware Description Configurable options
LoggingMiddleware Logs every incoming request (method, path, status code, latency). enabled
RateLimitMiddleware Limits the number of requests per minute from a single client IP. enabled, requests_per_minute

CORS

Control Cross-Origin Resource Sharing by listing allowed origins.

cors:
  allow_origins:
    - "https://myfront.com"
    - "https://testreact.space"

If no origins are specified, CORS headers are not added.

Admin Panel

The gateway includes a built-in admin interface protected by HTTP Basic Authentication. Access it at /admin after starting the server.

admin:
  username: "admin"   # default: admin
  password: "admin"   # change in production!

Through the admin panel you can:

  • View route statistics and cache status.
  • Manually flush the cache.
  • Check gateway health.

Running the Gateway

Launch the gateway with the easy-gateway command:

easy-gateway -c /path/to/config.yaml

If your config is named easy_conf.yaml and located in the current working directory, you can simply run:

easy-gateway

Health Check

The gateway exposes a /health endpoint that returns JSON with service status and cache connectivity:

{
    "status": health/degraded,
    "time": time,
    "checks": checks,
}

Example: Full Production Configuration

server:
  host: "0.0.0.0"
  port: 8000

redis:
  enabled: true
  url: "redis://redis:6379"
  expire_time: 300

routes:
  - path: "/api/v1/*"
    target: "https://backend.internal/"
    cache: true
  - path: "/auth/*"
    target: "https://auth.internal/"
  - path: "/health"
    target: "https://monitoring.internal/"

middlewares:
  - name: "LoggingMiddleware"
    enabled: true
  - name: "RateLimitMiddleware"
    enabled: true
    requests_per_minute: 60

cors:
  allow_origins:
    - "https://app.example.com"

admin:
  username: "ops"
  password: "strong-password-here"