-
Notifications
You must be signed in to change notification settings - Fork 0
server_en.md
The server package is the network layer core of the HypGo framework, responsible for listening on ports, handling connections, and coordinating between underlying protocols and the upper-layer router. It supports automatic switching and simultaneous operation of multiple protocols, and provides Graceful Restart for zero-downtime deployment.
-
Multi-Protocol Support: Supports plain HTTP/1.1, transparent HTTP/2 via
h2c, and HTTP/3 based on UDP QUIC protocol. -
Auto Protocol Mode: When TLS is enabled and Auto mode is selected (or
server.protocol: autois configured), HTTP/1.1, HTTP/2, and HTTP/3 services start simultaneously, automatically negotiating the best protocol with browsers. -
Graceful Shutdown: Upon receiving
SIGINTorSIGTERM, the server rejects new connections while ensuring in-flight requests complete before exiting, with timeout-based forced shutdown support. HTTP/1+2 and HTTP/3 servers shut down in parallel. -
Graceful Restart (Unix only): By sending a custom signal (default
SIGUSR2), a new process is forked to take over listening on the same port, then the old process exits after completing in-flight requests, achieving zero downtime. - Automatic PID Management: Automatically writes PID files on startup for easy process tracking by scripts or monitoring systems.
-
AutoSync Automatic Synchronization:
Start()automatically generates a.hyp/context.yamlmanifest, ensuring AI always has access to the latest project structure.
Initialize and start the server using config:
package main import ( "log" "github.com/maoxiaoyue/hypgo/pkg/config" "github.com/maoxiaoyue/hypgo/pkg/logger" "github.com/maoxiaoyue/hypgo/pkg/server" ) func main() { // 1. Load configuration cfg, _ := config.LoadConfig("config.yaml") // 2. Initialize Logger logInstance, _ := logger.New("info", "stdout", nil, true) // 3. Create server instance srv := server.New(cfg, logInstance) // 4. Define routes (get the built-in Router) r := srv.Router() r.GET("/api/ping", func(c *context.Context) { c.String(200, "pong") }) // 5. Start the server (blocks until shutdown signal received) if err := srv.Start(); err != nil { log.Fatalf("Server error: %v", err) } }
Control Protocol and TLS behavior in config.yaml:
server: addr: ":443" protocol: "auto" # Supports http1, http2, http3, auto graceful_restart: true # Listen for restart signals (Unix only) tls: enabled: true # Must be true for http3 or auto cert_file: "/path/to/cert.pem" key_file: "/path/to/key.pem"
server.New() already instantiates a router.Router. Access all Router functionality via srv.Router():
r := srv.Router() // Mount global middleware r.Use(middleware.Logger(middleware.LoggerConfig{})) // Mount static files r.Static("/public", "./assets") // Custom 404 handler (delegates to Router) srv.NotFound(func(c *context.Context) { c.String(404, "Page Not Found!") }) // Custom 405 handler (delegates to Router) srv.MethodNotAllowed(func(c *context.Context) { c.String(405, "Method Not Allowed!") })
- Standard TCP listener
- TLS support (using unified cipher suites)
- Optional Keep-Alive
- Cleartext HTTP/2 via
h2c.NewHandler(development environment) - TLS mode with automatic ALPN negotiation for
h2/http/1.1 - HTTP/2 configuration validation:
-
MaxReadFrameSize: Limited to 16KB~16MB (HTTP/2 spec requirement) -
MaxConcurrentStreams: Default 250 -
IdleTimeout: Configurable
-
- Based on QUIC (UDP), requires TLS 1.3
- Uses the
quic-go/http3package - Automatically sets
Alt-Svcheader to guide browsers to upgrade
Starts HTTP/3 (UDP goroutine) + HTTP/2+1.1 (TCP main thread) simultaneously:
Client -> TCP -> HTTP/1.1 or HTTP/2 (via ALPN)
Client -> UDP -> HTTP/3 (via Alt-Svc header upgrade)
All three protocols share strongCipherSuites, ensuring consistent security levels:
var strongCipherSuites = []uint16{ tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, tls.TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256, tls.TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, }
- HTTP/1.1 + HTTP/2:
MinVersion = TLS 1.2 - HTTP/3:
MinVersion = TLS 1.3(required by QUIC)
TLS 1.3's 0-RTT resumption uses a protected SessionCache:
// SessionCache features: // - maxSize = 10,000 entries (prevents memory exhaustion DoS) // - TTL = 24 hours (expired entries auto-evicted) // - LRU eviction: removes oldest entries when size limit exceeded // - GetAndDelete atomic operation: prevents race window replay attack
| Operation | Security Guarantee |
|---|---|
Put() |
Check size limit -> evict expired -> evict oldest -> store |
GetAndDelete() |
Atomically get and delete, each session can only be used once |
loadCertificate() returns (tls.Certificate, error) instead of panicking, ensuring production environments don't crash due to certificate issues.
HTTP/1+2 and HTTP/3 servers shut down simultaneously, sharing the context timeout:
// Shutdown internal behavior: // 1. shuttingDown.Store(true) <- atomic, no race // 2. listener.Close() <- stop accepting new connections // 3. Parallel: httpServer.Shutdown(ctx) + h3Server.Close() // 4. close(shutdownChan) <- notify graceful restart goroutine to exit
1. Receive SIGUSR2
2. Fork new process (passing listener FD)
3. Poll-wait for new process readiness (every 200ms x 15 = 3 seconds)
4. Old process Shutdown (30 second timeout)
5. Remove PID file -> Exit
Security fixes:
-
signal.Stopensures signal subscription is cleaned up -
file.Close()prevents FD leaks -
getInheritedListenervalidates that FD 3 is actually a TCP socket
Uses atomic.Bool instead of bool, ensuring no data race between Shutdown() writes and Health() reads:
// Write (during Shutdown) s.shuttingDown.Store(true) // Read (Health check) if s.shuttingDown.Load() { ... }
Server provides a Manifest() method that automatically scans registered routes, configuration, and schema metadata to produce a machine-readable project description:
m := srv.Manifest() manifest.WriteYAML(os.Stdout, m) manifest.SaveToFile(".hyp/manifest.yaml", m, "yaml")
Output example:
version: "1.0" framework: HypGo server: addr: ":8080" protocol: http2 tls: true routes: - method: POST path: /api/users handler_names: [controllers.CreateUser] summary: "Create user" tags: [users] input_type: CreateUserRequest output_type: UserResponse database: driver: postgres has_replicas: true
Also available via CLI:
hyp context # YAML to stdout hyp context -f json # JSON format hyp context -o manifest.yaml # Save to file
Server.Start() automatically calls autosync.SyncSafe() on startup, generating .hyp/context.yaml:
-
Atomic writes: Uses temp file +
os.Rename()to prevent mid-write corruption - Secure: Does not include passwords, tokens, DSN, or other sensitive information
- Automatic: Updates on every Server startup, no additional commands needed
| Fix | Severity | Description |
|---|---|---|
| SessionCache LRU + TTL | HIGH | Prevents DoS memory exhaustion, added size limit and expiry eviction |
atomic.Bool replaces isShuttingDown
|
HIGH | Eliminates data race between Shutdown/Health |
| FD leak fix | HIGH |
defer Close after tcpListener.File() in forkNewProcess
|
getInheritedListener validation |
HIGH | Validates FD 3 is TCP socket, safe fallback on failure |
loadCertificate no panic |
HIGH | Returns error instead, production won't crash on cert issues |
| Unified Cipher Suites | HIGH | HTTP/1 previously lacked cipher suites, now consistent across protocols |
0-RTT GetAndDelete atomic operation |
HIGH | Prevents race window replay attack |
| Shutdown parallelization | MEDIUM | HTTP/1+2 and HTTP/3 shut down simultaneously |
| HTTP/2 configuration validation | MEDIUM | MaxReadFrameSize limited to 16KB~16MB |
| NotFound/MethodNotAllowed implementation | MEDIUM | Changed from stub to delegating to router.NotFound()
|
| Signal cleanup | MEDIUM | Added signal.Stop + shutdownChan listener |
| Restart wait changed to poll | MEDIUM | Changed from sleep 2s to poll approach |
設計文件
套件
- config — 設定
- context — 請求上下文
- router — 路由器
- server — 伺服器
- middleware — 中介層
- websocket — WebSocket
- hidb — 資料庫 ORM
- hidb/cassandra — Cassandra
- logger — 日誌
- json — JSON 處理
- grpc — gRPC
AI 協作工具鏈
- schema — Schema-first 路由
- manifest — 專案 Manifest
- contract — Contract Testing
- errors — Typed Error Catalog
- migrate — Migration Diff
- scaffold — 智慧 Scaffold
- airules — AI Rules
CLI 命令
- hyp 總覽
- hyp new
- hyp api
- hyp run
- hyp restart
- hyp generate
- hyp migrate
- hyp context
- hyp ai-rules
- hyp chkcomment
- hyp impact
- hyp docker
- hyp health
- hyp version
- hyp difflog
Design Docs
Packages
- config — Configuration
- context — Request Context
- router — Router
- server — Server
- middleware — Middleware
- websocket — WebSocket
- hidb — Database ORM
- hidb/cassandra - Cassandra 5.0
- logger — Logger
- json — JSON
- grpc — gRPC
AI Collaboration Toolchain
- schema — Schema-first Routing
- manifest — Project Manifest
- contract — Contract Testing
- errors — Typed Error Catalog
- migrate — Migration Diff
- scaffold — Smart Scaffold
- airules — AI Rules
CLI Commands