# ============================================================
# Nginx 动态路由配置示例
# ============================================================
#
# 功能说明:
# - 基于路径和请求头的动态路由分发
# - 灰度发布支持
# - 多后端服务选择
#
# Lolly 对应配置:
# lolly 内置 Lua 沙箱支持，可通过 lua_scripts 嵌入路由逻辑
# 相关文档: docs/lua-nginx-module/08-balancer.md
# ============================================================

http {
    # 共享字典: 存储路由配置
    lua_shared_dict router_config 5m;

    # Lua 模块路径
    lua_package_path "/usr/local/nginx/lua/?.lua;;";

    # 初始化路由配置
    init_by_lua_block {
        local router_config = ngx.shared.router_config
        local cjson = require "cjson.safe"

        -- 定义路由规则
        local rules = {
            -- 路径路由
            path = {
                { prefix = "/api/v2",    upstream = "api_v2" },
                { prefix = "/api",       upstream = "api_default" },
                { prefix = "/static",    upstream = "static_server" },
                { prefix = "/ws",        upstream = "websocket_server" },
            },
            -- 默认上游
            default = "web_default",
        }

        router_config:set("rules", cjson.encode(rules))

        ngx.log(ngx.INFO, "Dynamic routing initialized")
    }

    # ---- 上游服务定义 ----

    upstream api_v2 {
        server 10.0.1.10:8080;
        server 10.0.1.11:8080;
    }

    upstream api_default {
        server 10.0.2.10:8080;
        server 10.0.2.11:8080;
    }

    upstream api_v2_canary {
        server 10.0.3.10:8080;
    }

    upstream static_server {
        server 10.0.4.10:80;
    }

    upstream websocket_server {
        server 10.0.5.10:9000;
    }

    upstream web_default {
        server 10.0.6.10:8080;
        server 10.0.6.11:8080;
    }

    # ---- 主服务 ----

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

        # 动态路由分发
        location / {
            set $target_upstream "";

            access_by_lua_block {
                local router = require "router"
                local upstream_name = router.select(ngx)

                if not upstream_name then
                    ngx.log(ngx.ERR, "No matching upstream found")
                    return ngx.exit(503)
                end

                -- 将选中的上游保存到变量
                ngx.var.target_upstream = upstream_name
            }

            proxy_pass http://$target_upstream;
            proxy_set_header Host              $host;
            proxy_set_header X-Real-IP         $remote_addr;
            proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;

            # 添加路由调试头（可选）
            add_header X-Selected-Upstream $target_upstream always;
        }

        # WebSocket 专用 location
        location /ws {
            set $target_upstream "websocket_server";

            proxy_pass http://$target_upstream;
            proxy_http_version 1.1;
            proxy_set_header Upgrade    $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_set_header Host       $host;
        }

        # 路由管理接口（仅内网访问）
        location /admin/routes {
            allow 127.0.0.1;
            deny all;

            content_by_lua_block {
                local router = require "router"
                local cjson = require "cjson.safe"

                local method = ngx.req.get_method()

                if method == "GET" then
                    local rules = router.get_rules()
                    ngx.header["Content-Type"] = "application/json"
                    ngx.say(cjson.encode(rules))

                elseif method == "POST" then
                    ngx.req.read_body()
                    local body = ngx.req.get_body_data()
                    local ok, err = router.update_rules(body)

                    if not ok then
                        ngx.status = 400
                        ngx.say(cjson.encode({ error = err }))
                        ngx.exit(400)
                    end

                    ngx.say(cjson.encode({ success = true }))
                else
                    ngx.status = 405
                    ngx.exit(405)
                end
            }
        }

        # 健康检查端点
        location /health {
            access_log off;
            return 200 "ok";
        }
    }
}

# 路由配置说明:
#
# 1. upstream 定义:
#    - api_v2:        API v2 服务
#    - api_default:   API 默认版本
#    - api_v2_canary: API v2 灰度实例
#    - static_server: 静态资源服务
#    - websocket_server: WebSocket 服务
#    - web_default:   默认 Web 服务
#
# 2. 路由选择流程:
#    a) 检查 X-Service 请求头 -> 直接使用指定 upstream
#    b) 检查 X-Canary 头       -> 选择灰度 upstream
#    c) 按路径前缀匹配         -> 选择对应 upstream
#    d) 回退到默认 upstream
#
# 3. 动态更新:
#    POST /admin/routes 可热更新路由规则
