Exemples Kong Gateway

Exemples de configuration Kong API Gateway incluant services, routes, plugins, authentification, load balancing et configuration de monitoring

⚙️ Configuration de Base Kong Gateway

🟡 intermediate ⭐⭐⭐

Configuration essentielle de Kong Gateway incluant services, routes, plugins et gestion d'API de base

⏱️ 35 min 🏷️ kong, api-gateway, infrastructure, microservices
Prerequisites: Docker, PostgreSQL, API concepts, Microservices architecture
# Kong Gateway Basic Configuration
# Complete setup for API Gateway with services, routes, and plugins

# 1. Docker Compose Setup
# docker-compose.yml
version: '3.8'

services:
  kong-database:
    image: postgres:13
    restart: always
    environment:
      POSTGRES_USER: kong
      POSTGRES_PASSWORD: kongpass
      POSTGRES_DB: kong
    ports:
      - "5432:5432"
    volumes:
      - kong_data:/var/lib/postgresql/data
    networks:
      - kong-net

  kong-migration:
    image: kong/kong-gateway:3.4
    command: kong migrations bootstrap
    environment:
      KONG_DATABASE: postgres
      KONG_PG_HOST: kong-database
      KONG_PG_USER: kong
      KONG_PG_PASSWORD: kongpass
      KONG_PG_DATABASE: kong
    depends_on:
      - kong-database
    networks:
      - kong-net

  kong:
    image: kong/kong-gateway:3.4
    restart: on-failure
    environment:
      KONG_DATABASE: postgres
      KONG_PG_HOST: kong-database
      KONG_PG_USER: kong
      KONG_PG_PASSWORD: kongpass
      KONG_PG_DATABASE: kong
      KONG_PROXY_ACCESS_LOG: /dev/stdout
      KONG_ADMIN_ACCESS_LOG: /dev/stdout
      KONG_ADMIN_LISTEN: 0.0.0.0:8001
      KONG_PROXY_LISTEN: 0.0.0.0:8000
    ports:
      - "8000:8000"  # Proxy port
      - "8001:8001"  # Admin API port
    depends_on:
      - kong-migration
    networks:
      - kong-net

  konga:
    image: pantsel/konga:next
    environment:
      NODE_ENV: development
    ports:
      - "1337:1337"
    depends_on:
      - kong
    networks:
      - kong-net

volumes:
  kong_data:

networks:
  kong-net:
    driver: bridge

# 2. Service Configuration - User Service
# Create a service pointing to user microservice
curl -X POST http://localhost:8001/services \
  --data 'name=user-service \
  &url=http://user-service:3001'

# Add route to user service
curl -X POST http://localhost:8001/services/user-service/routes \
  --data 'name=user-api \
  &paths[]=/api/users \
  &methods[]=GET,POST,PUT,DELETE'

# 3. Service Configuration - Product Service with health check
curl -X POST http://localhost:8001/services \
  --data 'name=product-service \
  &url=http://product-service:3002 \
  &connect_timeout=10000 \
  &write_timeout=10000 \
  &read_timeout=10000 \
  &retries=3 \
  &protocol=http'

# Add multiple routes to product service
curl -X POST http://localhost:8001/services/product-service/routes \
  --data 'name=products-api \
  &paths[]=/api/products \
  &methods[]=GET,POST'

curl -X POST http://localhost:8001/services/product-service/routes \
  --data 'name=product-search-api \
  &paths[]=/api/products/search \
  &methods[]=GET

curl -X POST http://localhost:8001/services/product-service/routes \
  --data 'name=product-categories-api \
  &paths[]=/api/products/categories \
  &methods[]=GET'

# 4. Load Balancer Configuration
# Create service with upstream for load balancing
curl -X POST http://localhost:8001/upstreams \
  --data 'name=user-service-upstream \
  &algorithm=round-robin \
  &healthchecks.path=/health \
  &healthchecks.healthy.interval=10 \
  &healthchecks.healthy.http_statuses=200,201 \
  &healthchecks.unhealthy.interval=5 \
  &healthchecks.unhealthy.http_statuses=404,500,502,503 \
  &healthchecks.unhealthy.timeout=5'

# Add targets to upstream (multiple instances)
curl -X POST http://localhost:8001/upstreams/user-service-upstream/targets \
  --data 'target=user-service-1:3001 \
  &weight=100'

curl -X POST http://localhost:8001/upstreams/user-service-upstream/targets \
  --data 'target=user-service-2:3001 \
  &weight=100'

curl -X POST http://localhost:8001/upstreams/user-service-upstream/targets \
  --data 'target=user-service-3:3001 \
  &weight=50 \
  &tags[]=canary'

# Create service pointing to upstream
curl -X POST http://localhost:8001/services \
  --data 'name=user-service-balanced \
  &url=http://user-service-upstream'

# 5. Plugin Configuration - Rate Limiting
# Global rate limiting
curl -X POST http://localhost:8001/plugins \
  --data 'name=rate-limiting \
  &config.minute=100 \
  &config.hour=5000 \
  &config.policy=local'

# Service-specific rate limiting
curl -X POST http://localhost:8001/services/user-service/plugins \
  --data 'name=rate-limiting \
  &config.minute=50 \
  &config.hour=2000 \
  &config.policy=cluster

# Advanced rate limiting with different limits
curl -X POST http://localhost:8001/services/product-service/plugins \
  --data 'name=rate-limiting-advanced \
  &config.limits.minute=100 \
  &config.limits.hour=5000 \
  &config.limits.day=50000 \
  &config.block_duration=60 \
  &config.policy=cluster'

# 6. Authentication and Authorization
# JWT Plugin Configuration
curl -X POST http://localhost:8001/plugins \
  --data 'name=jwt \
  &config.secret_is_base64=false \
  &config.key=secret-key \
  &config.algorithm=HS256 \
  &config.claims_to_verify=exp,iat,nbf \
  &config.header_names=authorization:x-authorization'

# CORS Plugin Configuration
curl -X POST http://localhost:8001/plugins \
  --data 'name=cors \
  &config.origins=* \
  &config.methods=GET,POST,PUT,DELETE,OPTIONS \
  &config.headers=Accept,Accept-Version,Content-Length,Content-MD5,Content-Type,Date,X-Auth-Token \
  &config.exposed_headers=X-Total-Count,X-Pagination-Count,X-Pagination-Limit \
  &config.credentials=true \
  &config.max_age=3600'

# OAuth2 Plugin Configuration
curl -X POST http://localhost:8001/plugins \
  --data 'name=oauth2 \
  &config.scopes=email,profile \
  &config.mandatory_scope=email \
  &config.provision_key=provision-key \
  &config.enable_authorization_code=true \
  &config.enable_client_credentials=true \
  &config.enable_password_grant=true'

# ACL Plugin for Role-Based Access Control
curl -X POST http://localhost:8001/plugins \
  --data 'name=acl \
  &config.hide_groups_header=true \
  &config.whitelist=admin,user,premium'

# 7. Request/Response Transformation
# Request Transformer Plugin
curl -X POST http://localhost:8001/services/user-service/plugins \
  --data 'name=request-transformer \
  &config.add.headers[X-Custom-Header]=custom-value \
  &config.add.headers[X-Request-ID]=uuid \
  &config.remove.headers=authorization \
  &config.replace.headers=Content-Type=application/json'

# Response Transformer Plugin
curl -X POST http://localhost:8001/services/user-service/plugins \
  --data 'name=response-transformer \
  &config.add.headers=X-Service=user-service \
  &config.add.headers=X-Cache-Hit=MISS \
  &config.remove.headers=X-Powered-By \
  &config.replace.headers=Content-Type=application/vnd.api+json'

# Request Size Limiting
curl -X POST http://localhost:8001/plugins \
  --data 'name=request-size-limiting \
  &config.allowed_payload_size=10 \
  &config.size_unit=mb'

# 8. Security Plugins
# IP Restriction Plugin
curl -X POST http://localhost:8001/services/admin-api/plugins \
  --data 'name=ip-restriction \
  &config.whitelist=192.168.1.0/24,10.0.0.0/8 \
  &config.blacklist=10.0.0.100

# Basic Authentication
curl -X POST http://localhost:8001/services/legacy-api/plugins \
  --data 'name=basic-auth \
  & config.hide_credentials=true'

# API Key Authentication
curl -X POST http://localhost:8001/services/external-api/plugins \
  --data 'name=key-auth \
  &config.hide_credentials=false'

# Add API Key
curl -X POST http://localhost:8001/consumers \
  --data 'username=api-consumer'

curl -X POST http://localhost:8001/consumers/api-consumer/key-auth \
  --data 'key=super-secret-api-key'

# 9. Monitoring and Analytics
# Prometheus Metrics Plugin
curl -X POST http://localhost:8001/plugins \
  --data 'name=prometheus \
  &config.per_consumer=true \
  &config.per_service=true \
  &config.per_route=true \
  &config.latency_metrics=true \
  &config.bandwidth_metrics=true'

# DataDog Plugin
curl -X POST http://localhost:8001/plugins \
  --data 'name=datadog \
  &config.host=datadog-agent \
  &config.port=8125 \
  &config.metrics=true \
  &config.host=statsd-exporter'

# Request Logging Plugin
curl -X POST http://localhost:8001/plugins \
  --data 'name=request-termination \
  &config.log_body=true \
  &config.body_bytes=4096'

# 10. Custom Plugin Development
# Custom Plugin Structure (my-plugin/kong/plugins/my-plugin/handler.lua)
local BasePlugin = require "kong.plugins.base_plugin"

local MyPlugin = BasePlugin:extend()

MyPlugin.PRIORITY = 1000
MyPlugin.VERSION = "1.0.0"

function MyPlugin:new()
  MyPlugin.super.new(self, "my-plugin")
  return self
end

function MyPlugin:access(conf)
  -- Add custom headers
  kong.response.add_header("X-Custom-Plugin", "active")

  -- Log request
  kong.log.info("Custom plugin executed")

  -- Custom logic based on request
  local path = kong.request.get_path()
  if string.match(path, "/admin") then
    -- Check custom header for admin access
    local admin_header = kong.request.get_header("X-Admin-Token")
    if not admin_header or admin_header ~= "secret-admin-token" then
      return kong.response.exit(403, "Admin access required")
    end
  end
end

function MyPlugin:body_filter(conf)
  -- Modify response body
  local body = kong.service.response.get_raw_body()
  if body then
    -- Add timestamp to JSON responses
    kong.service.response.set_raw_body(body:gsub("}", ',"timestamp":"' .. os.date() .. '"}'))
  end
end

return MyPlugin

# 11. Service Mesh Integration
# Kubernetes Service Discovery
curl -X POST http://localhost:8001/upstreams \
  --data 'name=k8s-services \
  &algorithm=round-robin \
  &healthchecks.path=/health \
  &healthchecks.healthy.interval=10'

# Add Kubernetes services as targets
curl -X POST http://localhost:8001/upstreams/k8s-services/targets \
  --data 'target=user-service.default.svc.cluster.local:80'

# Consul Service Discovery Plugin
curl -X POST http://localhost:8001/plugins \
  --data 'name=consul \
  &config.host=consul.default.svc.cluster.local \
  &config.port=8500 \
  &config.register=false \
  &config.query_timeout=2000 \
  &config.keepalive=30000 \
  &config.default_target=80'

# 12. Environment-Specific Configurations
# Development Environment (dev-kong.conf)
database = postgres
pg_host = kong-database
pg_user = kong
pg_password = kongpass
pg_database = kong

proxy_access_log = /dev/stdout
admin_access_log = /dev/stdout
log_level = debug

# Development specific plugins
plugins = bundled,cors,request-size-limiting

# Production Environment (prod-kong.conf)
database = postgres
pg_host = prod-kong-db.internal
pg_user = kong
pg_password = ${KONG_PG_PASSWORD}
pg_database = kong

proxy_access_log = /var/log/kong/access.log
admin_access_log = /var/log/kong/admin.log
log_level = warn

# Production plugins with security
plugins = bundled,cors,jwt,acl,ip-restriction,prometheus,rate-limiting

# 13. Kong Declarative Configuration
# kong.yml (declarative configuration format)
_format_version: "1.1"
services:
  - name: user-service
    url: http://user-service:3001
    plugins:
      - name: rate-limiting
        config:
          minute: 100
          hour: 5000
    routes:
      - name: user-api
        paths: ["/api/users"]
        methods: [GET,POST,PUT,DELETE]

  - name: product-service
    url: http://product-service:3002
    plugins:
      - name: jwt
        config:
          secret_is_base64: false
          key: secret-key
    routes:
      - name: products-api
        paths: ["/api/products"]
        methods: [GET,POST]

plugins:
  - name: cors
    config:
      origins: ["*"]
      methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"]
      headers: ["Accept", "Content-Type", "Authorization"]

  - name: prometheus
    config:
      per_consumer: true
      per_service: true

# 14. Admin API Automation Script
# setup-kong.sh
#!/bin/bash

# Wait for Kong to start
until curl -s http://localhost:8001 > /dev/null; do
  echo "Waiting for Kong to start..."
  sleep 2
done

echo "Kong is ready. Setting up services..."

# Create services
for service in user-service:3001 product-service:3002 order-service:3003; do
  name=${service%:*}
  url=http://${service#*:}

  echo "Creating service: $name -> $url"
  curl -s -X POST http://localhost:8001/services \
    --data "name=$name&url=$url" > /dev/null
done

# Create routes
declare -A routes=(
  ["user-service"="/api/users"]
  ["product-service"="/api/products"]
  ["order-service"="/api/orders"]
)

for service in "${!routes[@]}"; do
  name=${routes[$service]}

  echo "Creating route: $name -> $service"
  curl -s -X POST http://localhost:8001/services/$service/routes \
    --data "name=$name-Route&paths[]=$name&methods[]=GET,POST" > /dev/null
done

# Add rate limiting
curl -X POST http://localhost:8001/plugins \
  --data 'name=rate-limiting&config.minute=100&config.hour=5000'

echo "Kong setup completed!"

# 15. Health Check and Monitoring
# health-check.sh
#!/bin/bash

KONG_ADMIN_URL="http://localhost:8001"
KONG_PROXY_URL="http://localhost:8000"

echo "Checking Kong health..."

# Check admin API
if curl -s "$KONG_ADMIN_URL" > /dev/null; then
  echo "✓ Admin API is healthy"
else
  echo "✗ Admin API is not responding"
  exit 1
fi

# Check proxy
if curl -s "$KONG_PROXY_URL" > /dev/null; then
  echo "✓ Proxy is healthy"
else
  echo "✗ Proxy is not responding"
  exit 1
fi

# Check database connection
if curl -s "$KONG_ADMIN_URL/services" > /dev/null; then
  echo "✓ Database connection is working"
else
  echo "✗ Database connection failed"
  exit 1
fi

echo "All Kong health checks passed!"

# Load test configuration
# load-test.js (using Artillery or similar)
{
  "config": {
    "target": "http://localhost:8000",
    "phases": [
      {
        "duration": 60,
        "arrivalRate": 100
      },
      {
        "duration": 120,
        "arrivalRate": 200
      },
      {
        "duration": 60,
        "arrivalRate": 500
      }
    ]
  },
  "scenarios": [
    {
      "name": "User Service Load Test",
      "weight": 50,
      "flow": [
        {
          "get": {
            "url": "/api/users"
          }
        }
      ]
    },
    {
      "name": "Product Service Load Test",
      "weight": 30,
      "flow": [
        {
          "get": {
            "url": "/api/products"
          }
        }
      ]
    },
    {
      "name": "Health Check",
      "weight": 20,
      "flow": [
        {
          "get": {
            "url": "/health"
          }
        }
      ]
    }
  ]
}

⚙️ Fonctionnalités Avancées Kong Gateway

🔴 complex ⭐⭐⭐⭐

Fonctionnalités avancées de Kong Gateway incluant plugins personnalisés, intégration service mesh, monitoring et sécurité entreprise

⏱️ 60 min 🏷️ kong, api-gateway, advanced, enterprise
Prerequisites: Kong basics, Docker, PostgreSQL, Enterprise security, Monitoring
# Kong Gateway Advanced Configuration
# Enterprise-grade features and patterns

# 1. Multi-Region Setup with Active-Active
# Primary Region Configuration
# kong-primary.yml
_format_version: "1.1"

# Service pointing to multi-region upstream
services:
  - name: payment-service
    url: http://payment-balancer
    retries: 3
    connect_timeout: 10000
    write_timeout: 10000
    read_timeout: 10000
    plugins:
      - name: rate-limiting
        config:
          minute: 1000
          hour: 50000
          fault_tolerant: true
      - name: circuit-breaker
        config:
          thresholds:
            memory_usage: 80
            latency: {maximum_ms: 1000, sample_size: 100}
          healthy:
            success_rate: 0.95
    routes:
      - name: payment-api
        paths: ["/api/payments"]
        methods: [POST, GET, PUT]
        plugins:
          - name: request-id
          - name: prometheus
            config:
              per_service: true
              per_route: true
              latency_metrics: true

# Multi-region upstream configuration
upstreams:
  - name: payment-balancer
    algorithm: round-robin
    healthchecks:
      active:
        http_path: /health
        healthy:
          interval: 5
          successes: 3
        unhealthy:
          interval: 5
          http_failures: 3
      passive:
        type: http
        healthy:
          http_statuses: [200, 201, 202, 204]
          success_rate: 0.95
    targets:
      - target: payment-primary.region1.company.com:80
        weight: 1
        tags: [primary, region1]
      - target: payment-secondary.region1.company.com:80
        weight: 1
        tags: [secondary, region1]
      - target: payment-primary.region2.company.com:80
        weight: 1
        tags: [primary, region2]

# 2. Advanced Authentication and Authorization
# OAuth 2.0 with JWT and RBAC
# Create OAuth2 plugin for secure access
curl -X POST http://localhost:8001/plugins \
  --data 'name=oauth2 \
  &config.scopes=read,write,admin \
  &config.mandatory_scope=read \
  &config.provision_key=your-provision-key \
  &config.global_credentials=true \
  &config.enable_authorization_code=true \
  &config.enable_client_credentials=true \
  &config.enable_password_grant=true \
  &config.refresh_token_ttl=7200 \
  &config.access_token_ttl=3600 \
  &config.auth_methods=basic-auth'

# JWT Plugin with custom claims validation
curl -X POST http://localhost:8001/plugins \
  --data 'name=jwt \
  &config.secret_is_base64=false \
  &config.algorithm=RS256 \
  &config.key=your-rsa-public-key \
  &config.private_key=your-rsa-private-key \
  &config.claims_to_verify=exp,iat,nbf,jti \
  &config.claims_to_include=user_id,roles,permissions \
  &config.jwt_header_name=Authorization \
  &config.expired_jwt_claim=exp \
  &config.run_on_preflight=true'

# ACL Plugin for Role-Based Access Control
curl -X POST http://localhost:8001/plugins \
  --data 'name=acl \
  &config.whitelist=admin,user,premium,support \
  &config.hide_groups_header=false \
  &config.log_errors=true'

# Request Transformer for adding user context
curl -X POST http://localhost:8001/plugins \
  --data 'name=request-transformer \
  &config.add.headers=X-Auth-Time=${jwt.claims.iat} \
  &config.add.headers=X-User-Id=${jwt.claims.user_id} \
  &config.add.headers=X-User-Role=${jwt.claims.roles}'

# 3. Advanced Monitoring and Observability
# Comprehensive monitoring setup

# OpenTelemetry Plugin
curl -X POST http://localhost:8001/plugins \
  --data 'name=opentelemetry \
  &config.resource_attributes=service.name=payment-service,service.version=1.0.0 \
  &config.sampler=always_on \
  &config.collect_metrics=false \
  &config.collect_traces=true \
  &config.api_key=your-otel-api-key \
  &config.endpoint=http://otel-collector:4318/v1/traces \
  &config.headers=X-API-Key=your-api-key \
  &config.timeout=10000 \
  &config.batch_count=512 \
  &config.batch_size=1024 \
  &config.compression=gzip'

# DataDog APM Integration
curl -X POST http://localhost:8001/plugins \
  --data 'name=datadog \
  &config.host=datadog-agent.default.svc.cluster.local \
  &config.port=8125 \
  &config.metrics=true \
  &config.tags=environment:production,service:kong-gateway \
  &config.service_name=kong-gateway \
  &config.hostname=kong-gateway-1 \
  &config.constants=service.name:kong,service.version:3.4.0 \
  &config.spans=forbidden_list,external_requests,deadlock,host_latency,jemalloc,ngx_worker_mutex_metrics,os_scheduler_metrics,os_threading_metrics,postgres_query_timing,rpm_os_metrics,rpm_vm_metrics,upload_time_metrics,upload_time_successful,upload_time_failed

# Custom Logging Plugin for Business Metrics
curl -X POST http://localhost:8001/plugins \
  --data 'name=file-log \
  &config.path=/var/log/kong/business-metrics.log \
  &config.reopen=true \
  &config.log_body=false \
  &config.message_template=${time_stamp}[${request.method}] ${request.host}${request.path}: response_time=\{response.time}ms, status=\{response.status}, user=\{headers.X-User-Id}, role=\{headers.X-User-Role}

# 4. Dynamic Configuration with Declarative Config
# Enable declarative config
curl -X PATCH http://localhost:8001/config \
  --data '{"declarative_config": true}'

# Create directory for declarative configs
mkdir -p /etc/kong/declarative

# Environment-specific declarative configs
# /etc/kong/declarative/kong.yml
_format_version: "1.1"

# Common plugins (loaded everywhere)
plugins:
  - name: prometheus
    config:
      per_consumer: true
      per_service: true
      per_route: true
      latency_metrics: true
  - name: request-id
    config: header_name: X-Request-ID
  - name: cors
    config:
      origins: ["*"]
      methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS"]
      headers: ["Accept", "Content-Type", "Authorization"]
      exposed_headers: ["X-Total-Count", "X-Pagination-Count"]
      credentials: true
  - name: rate-limiting
    config:
      minute: 1000
      hour: 50000
      fault_tolerant: true
      skip_on_http_codes: [404, 500, 502, 503]

# Service definitions
services:
  - name: user-service
    url: http://user-service:3001
    plugins:
      - name: acl
        config:
          whitelist: [user, admin]
          hide_groups_header: true
      - name: jwt
        config:
          key: user-service-jwt-secret
          secret_is_base64: false
    routes:
      - name: user-api
        paths: ["/api/users"]
        methods: [GET, POST, PUT, DELETE]
        plugins:
          - name: request-transformer
            config:
              add:
                headers:
                  X-Service: user-service
                  X-Version: v1

# 5. Circuit Breaker and Fault Tolerance
# Circuit Breaker Plugin Configuration
curl -X POST http://localhost:8001/services/critical-service/plugins \
  --data 'name=circuit-breaker \
  &config.provisioning=0 \
  &config.timeout=30 \
  &config.thresholds.latency.maximum_ms=1000 \
  &config.thresholds.latency.sample_size=100 \
  &config.thresholds.memory_usage=80 \
  &config.thresholds.network_errors=10 \
  &config.success_rate.percentage=95 \
  &config.failure_rate.percentage=5 \
  &config.ttl=600 \
  &config.allow_discovery=true \
  &config.load_balancing_policy=least_connections \
  &config.fallback.name=custom-fallback \
  &config.fallback.code=404,500,503,504 \
  &config.fallback.show_error=true

# Custom Fallback Plugin for Circuit Breaker
# custom-fallback/handler.lua
local BasePlugin = require "kong.plugins.base_plugin"

local CustomFallback = BasePlugin:extend()

CustomFallback.PRIORITY = 1000
CustomFallback.VERSION = "1.0.0"

function CustomFallback:new()
  CustomFallback.super.new(self, "custom-fallback")
  return self
end

function CustomFallback:body_filter(conf)
  if kong.response.get_status() >= 500 then
    local fallback_response = {
      error = "Service temporarily unavailable",
      message = "The service is currently experiencing issues. Please try again later.",
      retry_after = 30,
      circuit_breaker_status = "open"
    }

    kong.response.set_status(503)
    kong.response.set_header("Content-Type", "application/json")
    kong.response.set_header("Retry-After", fallback_response.retry_after)
    kong.response.clear_header("X-Powered-By")
    kong.response.clear_header("Server")

    local fallback_json = require("cjson").encode(fallback_response)
    kong.response.set_raw_body(fallback_json)
  end
end

return CustomFallback

# 6. Advanced Request/Response Processing
# Lua Plugin for Request/Response Transformation
# api-gateway-transformer/handler.lua
local BasePlugin = require "kong.plugins.base_plugin"
local cjson = require "cjson"
local json_decode = cjson.decode
local json_encode = cjson.encode

local ApiGatewayTransformer = BasePlugin:extend()

ApiGatewayTransformer.PRIORITY = 1000
ApiGatewayTransformer.VERSION = "1.0.0"

function ApiGatewayTransformer:new()
  ApiGatewayTransformer.super.new(self, "api-gateway-transformer")
  return self
end

function ApiGatewayTransformer:access(conf)
  -- Extract API version from path
  local path = kong.request.get_path()
  local api_version = path:match("/api/v(%d+)/")

  if api_version then
    kong.ctx.shared.api_version = api_version
    kong.log.info("API version detected: " .. api_version)
  end

  -- Add correlation ID if not present
  local correlation_id = kong.request.get_header("X-Correlation-ID")
  if not correlation_id then
    local uuid = require("resty.uuid")
    local new_id = uuid.generate()
    kong.service.request.set_header("X-Correlation-ID", new_id)
    kong.ctx.shared.correlation_id = new_id
  end

  -- Rate limiting based on user tier
  local user_id = kong.request.get_header("X-User-ID")
  if user_id then
    -- In a real implementation, you would query user data
    local user_tier = "standard"
    if user_id == "premium-user-123" then
      user_tier = "premium"
    end

    kong.ctx.shared.user_tier = user_tier
    kong.log.debug("User " .. user_id .. " tier: " .. user_tier)
  end
end

function ApiGatewayTransformer:body_filter(conf)
  local content_type = kong.response.get_header("Content-Type")

  -- Transform JSON responses
  if content_type and content_type:match("application/json") then
    local body = kong.service.response.get_raw_body()
    if body then
      local success, json_body = pcall(json_decode, body)
      if success then
        -- Add metadata
        local metadata = {
          api_version = kong.ctx.shared.api_version or "unknown",
          gateway_version = "1.0.0",
          response_time = kong.ctx.shared.response_time or 0,
          correlation_id = kong.ctx.shared.correlation_id,
          user_tier = kong.ctx.shared.user_tier or "anonymous"
        }

        json_body._metadata = metadata
        json_body.request_id = kong.ctx.shared.correlation_id

        local transformed_body = json_encode(json_body)
        kong.service.response.set_raw_body(transformed_body)
      end
    end
  end

  -- Set standard response headers
  kong.response.set_header("X-API-Version", kong.ctx.shared.api_version or "unknown")
  kong.response.set_header("X-Correlation-ID", kong.ctx.shared.correlation_id)
  kong.response.set_header("X-Response-Time", (kong.ctx.shared.response_time or 0) .. "ms")
  kong.response.set_header("X-Gateway-Version", "1.0.0")
end

return ApiGatewayTransformer

# 7. Security Hardening
# Request Size Limiting by User Tier
curl -X POST http://localhost:8001/plugins \
  --data 'name=request-size-limiting \
  &config.allowed_payload_size=10 \
  &config.size_unit=mb \
  &config.enforce_uppercase=true \
  &config.client_error_msgs=true \
  &config.exclude=api/internal'

# IP Whitelisting for Admin APIs
curl -X POST http://localhost:8001/services/admin-service/plugins \
  --data 'name=ip-restriction \
  &config.whitelist=10.0.0.0/8,192.168.1.0/24 \
  &config.blacklist=0.0.0.0/0 \
  &config.allowed_methods=GET,POST,PUT,DELETE \
  &config.error_default_message=Forbidden: Your IP is not allowed to access this service

# WAF-like Request Validation
curl -X POST http://localhost:8001/plugins \
  --data 'name=request-validator \
  &config.body_schema="{\"type\": \"object\", \"required\": [\"user_id\"], \"additionalProperties\": false}" \
  &config.status_code=400 \
  &config.error_message=Invalid request body \
  &config.version=2

# 8. Analytics and Business Intelligence
# Analytics Plugin with Custom Metrics
curl -X POST http://localhost:8001/plugins \
  --data 'name=http-log \
  &config.timeout=10000 \
  &config.retry_count=3 \
  &config.buffer_size=4096 \
  &config.flush_timeout=2000 \
  &config.endpoint=http://analytics-collector:3000/events \
  &config.method=POST \
  &config.content_type=application/json \
  &config.custom_fields.user_id=X-User-ID \
  &config.custom_fields.user_tier=X-User-Tier \
  &config.custom_fields.api_version=X-API-Version \
  &config.custom_fields.correlation_id=X-Correlation-ID \
  &config.custom_fields.response_time=X-Response-Time

# Business Metrics Collector
curl -X POST http://localhost:8001/plugins \
  --data 'name=custom-metrics \
  &config.prometheus_metric_prefix=kong_business_ \
  config.metrics.user_requests_total={type="counter", description="Total user requests"}, config.metrics.api_latency={type="histogram", unit="ms", buckets="[10, 50, 100, 250, 500, 1000, 2500, 5000]", description="API latency in milliseconds"}, config.metrics.error_rate={type="gauge", description="Error rate as percentage"}

# 9. Performance Optimization
# Optimized Kong Configuration
# optimized-kong.conf
# Performance settings
nginx_worker_processes auto
nginx_worker_connections 4096

# Buffer sizes
client_body_buffer_size 8k
client_header_buffer_size 4k
client_max_body_size 10m

# Connection timeouts
keepalive_timeout 60s
keepalive_requests 1000
proxy_connect_timeout 60s
proxy_send_timeout 60s
proxy_read_timeout 60s

# Performance plugins
plugins = bundled,cors,jwt,acl,prometheus,custom-metrics

# Optimized plugin settings
prometheus:
  per_consumer: false  # Disable per-consumer metrics for performance
  per_service: true
  per_route: true
  latency_metrics: true
  bandwidth_metrics: false

jwt:
  secret_is_base64: false
  cache_ttl: 300
  access_token_ttl: 3600
  refresh_token_ttl: 604800

# 10. Disaster Recovery and Backup
# Database Backup Configuration
# backup-kong.sh
#!/bin/bash

BACKUP_DIR="/backup/kong"
DATE=$(date +%Y%m%d_%H%M%S)
DB_NAME="kong"

# Create backup directory
mkdir -p "$BACKUP_DIR"

# Database backup
echo "Starting database backup..."
pg_dump -h localhost -U kong -d kong > "$BACKUP_DIR/kong_db_$DATE.sql"

# Declarative configuration backup
echo "Backing up declarative configuration..."
if [ -d "/etc/kong/declarative" ]; then
    tar -czf "$BACKUP_DIR/declarative_config_$DATE.tar.gz" -C /etc/kong/declarative .
fi

# Plugin configurations backup
echo "Backing up plugin configurations..."
docker exec kong tar -czf - /tmp/plugins_$DATE.tar.gz /usr/local/kong/plugins
docker cp kong:/tmp/plugins_$DATE.tar.gz "$BACKUP_DIR/"

# Configuration files backup
echo "Backing up configuration files..."
cp /etc/kong/kong.conf "$BACKUP_DIR/kong_$DATE.conf"

# Cleanup old backups (keep 7 days)
find "$BACKUP_DIR" -name "*.sql" -mtime +7 -delete
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +7 -delete

echo "Backup completed: $BACKUP_DIR"
echo "Backup size: $(du -sh $BACKUP_DIR | cut -f1)"