package main import ( "flag" "fmt" "log" "net/http" "aijianzhan/gateway/internal/config" "aijianzhan/gateway/internal/jwtmw" "aijianzhan/gateway/internal/proxy" "aijianzhan/gateway/internal/ratelimit" "github.com/zeromicro/go-zero/core/conf" ) var configFile = flag.String("f", "etc/gateway.yaml", "config file") func main() { flag.Parse() var c config.Config conf.MustLoad(*configFile, &c) dir, err := proxy.New(c.PlatformURL, c.AIURL, c.ProxyTimeoutSec) if err != nil { log.Fatal(err) } limiter := ratelimit.New(c.RateLimitPerMin) h := limiter.Middleware(dir.Handler()) if c.JWTEnable { secret := c.JWTSecret if secret == "" { secret = "dev-only-change-me" } public := []string{ "/gateway/health", "/api/v1/auth/login", "/api/v1/auth/register", "/api/v1/auth/token", "/api/v1/auth/agent/register", "/api/v1/meta/", "/api/v1/public/", "/ai/", "/ai", } h = jwtmw.Middleware(secret, public)(h) } mux := http.NewServeMux() mux.HandleFunc("/gateway/health", dir.Health) mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { if c.CorsEnable { origin := r.Header.Get("Origin") if origin == "" { origin = "*" } w.Header().Set("Access-Control-Allow-Origin", origin) w.Header().Set("Access-Control-Allow-Headers", "Authorization, Content-Type, X-Request-Id, X-Tenant-Id, X-User-Id, X-Role") w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, PATCH, DELETE, OPTIONS") w.Header().Set("Access-Control-Allow-Credentials", "true") if r.Method == http.MethodOptions { w.WriteHeader(http.StatusNoContent) return } } if r.URL.Path == "/gateway/health" { dir.Health(w, r) return } h(w, r) }) addr := fmt.Sprintf("%s:%d", c.Host, c.Port) limitDesc := fmt.Sprintf("%d/min (loopback exempt)", c.RateLimitPerMin) if c.RateLimitPerMin <= 0 { limitDesc = "disabled" } fmt.Printf("gateway listening %s jwt=%v rate=%s → platform=%s ai=%s\n", addr, c.JWTEnable, limitDesc, c.PlatformURL, c.AIURL) log.Fatal(http.ListenAndServe(addr, mux)) }