chore: initial commit of Go API gateway
Baseline for the Kong replacement on api.riotpiao.com. Brings the working tree under version control for the first time: gateway source, the task board that drives the agent runs, test fixtures, and K8s manifests. Anchor the gateway ignore rule to the repo root. Unanchored, "gateway" also matched the cmd/gateway/ source directory, so the program entrypoint was excluded from every commit. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Server wraps an HTTP server with graceful shutdown support.
|
||||
type Server struct {
|
||||
httpServer *http.Server
|
||||
shutdownTimeout time.Duration
|
||||
listener net.Listener
|
||||
listenerMu sync.RWMutex
|
||||
healthChecker *HealthChecker
|
||||
}
|
||||
|
||||
// New creates a new Server with the given configuration.
|
||||
func New(listenAddr string, shutdownTimeout time.Duration, handler http.Handler) *Server {
|
||||
return &Server{
|
||||
httpServer: &http.Server{
|
||||
Addr: listenAddr,
|
||||
Handler: handler,
|
||||
ReadTimeout: 15 * time.Second,
|
||||
WriteTimeout: 15 * time.Second,
|
||||
IdleTimeout: 60 * time.Second,
|
||||
},
|
||||
shutdownTimeout: shutdownTimeout,
|
||||
healthChecker: NewHealthChecker(false, false),
|
||||
}
|
||||
}
|
||||
|
||||
// ListenAndServe starts the HTTP server and blocks until it exits.
|
||||
// It returns the error from the server (if any), which will be
|
||||
// http.ErrServerClosed if Shutdown was called.
|
||||
func (s *Server) ListenAndServe() error {
|
||||
listener, err := net.Listen("tcp", s.httpServer.Addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.listenerMu.Lock()
|
||||
s.listener = listener
|
||||
s.listenerMu.Unlock()
|
||||
return s.httpServer.Serve(listener)
|
||||
}
|
||||
|
||||
// Shutdown gracefully shuts down the server. It stops accepting new
|
||||
// connections and waits for in-flight requests to complete, with a
|
||||
// bounded deadline. If the deadline is exceeded, it returns an error.
|
||||
func (s *Server) Shutdown(ctx context.Context) error {
|
||||
// Create a new context with the shutdown timeout
|
||||
shutdownCtx, cancel := context.WithTimeout(ctx, s.shutdownTimeout)
|
||||
defer cancel()
|
||||
|
||||
return s.httpServer.Shutdown(shutdownCtx)
|
||||
}
|
||||
|
||||
// Addr returns the network address the server is listening on.
|
||||
func (s *Server) Addr() string {
|
||||
s.listenerMu.RLock()
|
||||
defer s.listenerMu.RUnlock()
|
||||
if s.listener != nil {
|
||||
return s.listener.Addr().String()
|
||||
}
|
||||
return s.httpServer.Addr
|
||||
}
|
||||
|
||||
// HealthChecker returns the server's health checker.
|
||||
func (s *Server) HealthChecker() *HealthChecker {
|
||||
return s.healthChecker
|
||||
}
|
||||
|
||||
// SetHealthChecker sets the server's health checker.
|
||||
func (s *Server) SetHealthChecker(hc *HealthChecker) {
|
||||
s.healthChecker = hc
|
||||
}
|
||||
|
||||
// SetHandler sets the server's HTTP handler.
|
||||
func (s *Server) SetHandler(handler http.Handler) {
|
||||
s.httpServer.Handler = handler
|
||||
}
|
||||
Reference in New Issue
Block a user