Skip to main content

Implementing API Gateway Patterns

1. Routing API Requests

Directive Description Example
location Defines how to handle requests based on URI location /api/ { proxy_pass http://backend; }
proxy_pass Specifies the backend server to forward requests to proxy_pass http://upstream_backend;
rewrite Modifies the URI before forwarding rewrite ^/api/(.*)$ /$1 break;

Example: Basic API Route

server {
    listen 80;
    location /api/users {
        proxy_pass http://user_service;
    }
}

Example: Rewrite and Forward

location /api/v1/ {
    rewrite ^/api/v1/(.*)$ /v1/$1 break;
    proxy_pass http://backend_v1;
}
Note: The location block matches the URI path and can use regex patterns or prefix matching.

2. Implementing API Versioning

Version Strategy Description Implementation
URL Path Versioning Version specified in the URL path (e.g., /api/v1/users)
location /api/v1/ {
    proxy_pass http://backend_v1;
}
Header Versioning Version specified in a custom header (e.g., X-API-Version)
location /api/ {
    if ($http_x_api_version = "v1") {
        proxy_pass http://backend_v1;
    }
    if ($http_x_api_version = "v2") {
        proxy_pass http://backend_v2;
    }
}
Query Parameter Versioning Version specified as a query parameter (e.g., /api/users?version=v1)
location /api/ {
    if ($arg_version = "v1") {
        proxy_pass http://backend_v1;
    }
}

Example: URL Path Versioning

server {
    listen 80;
    server_name example.com;

    location /api/v1/users {
        proxy_pass http://backend_v1;
    }

    location /api/v2/users {
        proxy_pass http://backend_v2;
    }
}
Note: URL path versioning is the most commonly used and recommended method for API versioning in Nginx.

3. Rate Limiting API Endpoints

Directive Description Values Notes
limit_req_zone Defines a shared memory zone for storing rate limit state zone=name:size, rate=rate Required for rate limiting configuration
limit_req Applies rate limiting to a location or server block zone=name, burst=number, nodelay Enables rate limiting based on the zone defined

Example: Basic Rate Limiting Configuration

http {
    limit_req_zone $binary_remote_addr zone=api:10m rate=10r/m;

    server {
        listen 80;
        location /api/ {
            limit_req zone=api burst=5 nodelay;
            proxy_pass http://backend;
        }
    }
}

Example: Rate Limiting with Burst and Delay

http {
    limit_req_zone $binary_remote_addr zone=api:10m rate=10r/m;

    server {
        listen 80;
        location /api/ {
            limit_req zone=api burst=10 nodelay;
            proxy_pass http://backend;
        }
    }
}
Note: The rate parameter is in requests per second (r/s) or per minute (r/m). For example, rate=10r/m allows 10 requests per minute.
Warning: If nodelay is not specified, burst requests will be delayed until the rate limit allows them.

Rate Limiting Configuration Summary

  • limit_req_zone creates a shared memory zone to track rate limits.
  • limit_req applies the rate limit to specific locations or servers.
  • Burst allows temporary overuse of the rate limit without delay.
  • Use nodelay to avoid delays for burst requests.

4. Authenticating API Requests

Directive Description Example
auth_jwt Enables JWT-based authentication for API requests. auth_jwt "API" token=$jwt_token;
auth_jwt_key_file Specifies the file containing the public key for JWT verification. auth_jwt_key_file /etc/nginx/jwt_keys/public.key;
auth_jwt_claim Defines the claim to be used for authentication (e.g., sub, aud). auth_jwt_claim sub;

Example: JWT Authentication Setup

location /api/ {
    auth_jwt "API";
    auth_jwt_key_file /etc/nginx/jwt_keys/public.key;
    proxy_pass http://backend;
}
Note: Ensure the JWT token is passed in the Authorization header as Bearer <token>.
Claim Description Required
sub Subject identifier (e.g., user ID or client ID). Yes
aud Audience claim to verify the token is intended for this API. Yes
exp Expiration time of the token. Yes
iss Issuer of the token (e.g., identity provider). No

5. Implementing API Key Validation

Directive Description Example
auth_jwt Enables JWT-based authentication for API requests auth_jwt "API Gateway" token=$jwt_token;
auth_jwt_key_file Specifies the file containing public keys for JWT validation auth_jwt_key_file /etc/nginx/jwt-keys.pem;
auth_jwt_claim Defines the claim to extract from the JWT for validation auth_jwt_claim api_key $jwt_api_key;

Example: Basic API Key Validation Setup

server {
    listen 80;
    server_name api.example.com;

    location /api/ {
        auth_jwt "API Gateway";
        auth_jwt_key_file /etc/nginx/jwt-keys.pem;
        auth_jwt_claim api_key $jwt_api_key;

        proxy_pass http://backend;
    }
}

Example: Validating API Key from Header

server {
    listen 443 ssl;
    server_name api.example.com;

    location /api/v1/ {
        auth_jwt "API Gateway";
        auth_jwt_key_file /etc/nginx/jwt-keys.pem;

        # Extract API key from Authorization header
        auth_jwt_claim api_key $jwt_api_key;
        proxy_pass http://backend;
    }
}
Note: Ensure that the JWT keys are securely stored and only accessible to the Nginx process.

6. Configuring Request Transformation

Directive Description Example
proxy_set Sets a header to be sent to the upstream server proxy_set X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_hide_header Hides a header from the response proxy_hide_header X-Powered-By;
proxy_pass_request_headers Controls whether request headers are passed to the upstream server proxy_pass_request_headers on;

Example: Transforming Request Headers

location /api/ {
    proxy_pass http://backend;
    proxy_set X-Original-URI $request_uri;
    proxy_hide_header Server;
}
Note: Use proxy_set to modify or add headers, and proxy_hide_header to remove them before forwarding the request.

7. Implementing Response Transformation

Directive Description Example
proxy_hide_header Hides a response header from the client proxy_hide_header X-Powered-By;
proxy_set_header Sets a header to be sent to the upstream server proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass Specifies the address of the upstream server proxy_pass http://backend;
rewrite Modifies the URI of a request rewrite ^/api/(.*)$ /$1 break;

Example: Transforming Response Headers

location /api/ {
    proxy_pass http://backend;
    proxy_hide_header X-Powered-By;
    proxy_set_header X-Forwarded-Proto $scheme;
}

Example: Rewriting URI for Response Transformation

location /api/v1/ {
    rewrite ^/api/v1/(.*)$ /v2/$1 break;
    proxy_pass http://backend;
}
Note: Response transformation directives like rewrite and proxy_set_header can be used to modify the response before it reaches the client.

8. Handling CORS for APIs

Directive Description Example
add_header Adds custom headers to the response add_header Access-Control-Allow-Origin *;
add_header Allows specific headers in preflight requests add_header Access-Control-Allow-Headers "Content-Type, Authorization";
add_header Specifies allowed HTTP methods add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE";

Example: Basic CORS Configuration

location /api/ {
    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE";
    add_header Access-Control-Allow-Headers "Content-Type, Authorization";

    proxy_pass http://backend;
}
Note: Using * for Access-Control-Allow-Origin allows any domain to access the API. For production, specify domains explicitly.

Example: Handling Preflight Requests

location /api/ {
    if ($request_method = "OPTIONS") {
        add_header Access-Control-Allow-Origin *;
        add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE";
        add_header Access-Control-Allow-Headers "Content-Type, Authorization";
        add_header Access-Control-Max-Age 86400;
        return 204;
    }

    proxy_pass http://backend;
}

9. Implementing Request Routing by Header

Directive Description Example
location Defines a location block to match requests based on URI or header location /api/ { ... }
if Conditionally routes requests based on header values if ($http_user_agent ~* "Mobile") { ... }
map Maps header values to variables for use in routing logic map $http_user_agent $mobile { default 0; ~* "Mobile" 1; }

Example: Route by User-Agent Header

server {
    listen 80;

    location /api/ {
        if ($http_user_agent ~* "Mobile") {
            proxy_pass http://mobile_backend;
        }

        if ($http_user_agent ~* "Desktop") {
            proxy_pass http://desktop_backend;
        }

        proxy_pass http://default_backend;
    }
}

Example: Using Map for Header-Based Routing

http {
    map $http_user_agent $backend {
        default "default_backend";
        ~* "Mobile" "mobile_backend";
        ~* "Desktop" "desktop_backend";
    }

    server {
        listen 80;

        location /api/ {
            proxy_pass http://$backend;
        }
    }
}
Note: The if directive can lead to performance issues and is generally discouraged in favor of map or location blocks for routing logic.

10. Using Upstream Groups for Microservices

Directive Description Example
upstream Defines a group of servers (upstreams) to which requests can be forwarded
upstream api_backend {
    server 127.0.0.1:8080;
    server 127.0.0.1:8081;
}
server Defines a server within an upstream block server 192.168.1.10:8080 weight=3;
keepalive Enables persistent connections to upstream servers keepalive 32;

Example: Load Balancing with Upstream Groups

upstream api_backend {
    server 127.0.0.1:8080 weight=3;
    server 127.0.0.1:8081 weight=2;
    server 127.0.0.1:8082 backup;
}

server {
    listen 80;
    location /api/ {
        proxy_pass http://api_backend/;
    }
}
Note: The weight parameter controls how many requests each server receives. Servers marked as backup only receive traffic when all other servers are unavailable.

Upstream Group Configuration Summary

  • upstream defines a group of backend servers
  • server specifies individual servers with optional parameters
  • weight allows for weighted load balancing
  • backup designates failover servers
  • keepalive enables persistent connections to upstreams

11. Implementing Circuit Breaker

Directive Description Default Notes
circuit_breaker Enables circuit breaker logic for upstream servers Off Requires ngx_http_upstream_module
circuit_breaker_error_codes Defines error codes that trigger circuit breaker 500, 502, 503, 504 Can be extended with custom codes
circuit_breaker_timeout Timeout for circuit breaker logic 30s Used to reset circuit state

Example: Basic Circuit Breaker Configuration

upstream api_backend {
    server 192.168.1.10:8080;
    server 192.168.1.11:8080;

    # Enable circuit breaker
    circuit_breaker error_codes=500,502,503,504 timeout=30s;
}

server {
    listen 80;

    location /api/ {
        proxy_pass http://api_backend;
    }
}
Note: The circuit breaker will trip if the specified error codes are returned more than a defined threshold within a given time window.
Warning: Ensure that the circuit_breaker directive is used in conjunction with proper error handling to avoid unexpected behavior.

Key Features of Circuit Breaker in Nginx

  • Triggers on specific HTTP error codes (500, 502, 503, 504 by default)
  • Automatically resets after a timeout period
  • Prevents cascading failures in API gateways

12. Logging API Metrics

Directive Description Example
access_log Defines the file to which access logs are written access_log /var/log/nginx/access.log;
error_log Defines the file to which error logs are written error_log /var/log/nginx/error.log;
log_format Defines custom log formats for access logs log_format main '$remote_addr - $remote_user [$time_local] "$request" ...';

Example: Custom Log Format for API Metrics

log_format api_metrics '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for" $request_time';

Example: Using Custom Log Format

server {
    listen 80;
    location /api/ {
        access_log /var/log/nginx/api_access.log api_metrics;
        proxy_pass http://backend;
    }
}
Note: The $request_time variable includes the time taken to process the request, useful for performance monitoring.

Key Metrics to Track

  • Request Count - Total number of API calls
  • Response Time - Average and max response times
  • Status Codes - 2xx, 4xx, 5xx counts for error tracking
  • Bandwidth Usage - Bytes sent and received

Steps to Implement API Metrics Logging

  1. Create a custom log format tailored for API metrics
  2. Apply the format to relevant location blocks or servers
  3. Ensure log rotation is configured to prevent disk overflow
  4. Use a log aggregation tool (e.g., ELK stack) to analyze logs

Was this article helpful?