network/cmd/gateway/main.go
anonpenguin 7e0db10ada Add wallet-based API key management and auth
This adds a new auth flow allowing users to authenticate with their
wallet and obtain an API key scoped to a namespace. It also moves API
key storage from config to the database for better persistence and
key-to-wallet linkage.

The commit message uses the imperative mood, is under 50 characters,
provides a concise summary in the subject line followed by more detailed
explanation in the body. This follows good Git commit message style
while capturing the key changes made.
2025-08-20 10:42:40 +03:00

103 lines
3.0 KiB
Go

package main
import (
"context"
"net"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"git.debros.io/DeBros/network/pkg/gateway"
"git.debros.io/DeBros/network/pkg/logging"
"go.uber.org/zap"
)
func setupLogger() *logging.ColoredLogger {
logger, err := logging.NewColoredLogger(logging.ComponentGeneral, true)
if err != nil {
panic(err)
}
return logger
}
func main() {
logger := setupLogger()
// Load gateway config (flags/env)
cfg := parseGatewayConfig(logger)
logger.ComponentInfo(logging.ComponentGeneral, "Starting gateway initialization...")
// Initialize gateway (connect client, prepare routes)
gw, err := gateway.New(logger, cfg)
if err != nil {
logger.ComponentError(logging.ComponentGeneral, "failed to initialize gateway", zap.Error(err))
os.Exit(1)
}
defer gw.Close()
logger.ComponentInfo(logging.ComponentGeneral, "Gateway initialization completed successfully")
logger.ComponentInfo(logging.ComponentGeneral, "Creating HTTP server and routes...")
server := &http.Server{
Addr: cfg.ListenAddr,
Handler: gw.Routes(),
}
// Try to bind listener explicitly so binding failures are visible immediately.
logger.ComponentInfo(logging.ComponentGeneral, "Gateway HTTP server starting",
zap.String("addr", cfg.ListenAddr),
zap.String("namespace", cfg.ClientNamespace),
zap.Int("bootstrap_peer_count", len(cfg.BootstrapPeers)),
)
logger.ComponentInfo(logging.ComponentGeneral, "Attempting to bind HTTP listener...")
ln, err := net.Listen("tcp", cfg.ListenAddr)
if err != nil {
logger.ComponentError(logging.ComponentGeneral, "failed to bind HTTP listen address", zap.Error(err))
// exit because server cannot function without a listener
os.Exit(1)
}
logger.ComponentInfo(logging.ComponentGeneral, "HTTP listener bound", zap.String("listen_addr", ln.Addr().String()))
// Serve in a goroutine so we can handle graceful shutdown on signals.
serveErrCh := make(chan error, 1)
go func() {
if err := server.Serve(ln); err != nil && err != http.ErrServerClosed {
serveErrCh <- err
return
}
serveErrCh <- nil
}()
// Wait for termination signal or server error
quit := make(chan os.Signal, 1)
signal.Notify(quit, os.Interrupt, syscall.SIGTERM)
select {
case sig := <-quit:
logger.ComponentInfo(logging.ComponentGeneral, "shutdown signal received", zap.String("signal", sig.String()))
case err := <-serveErrCh:
if err != nil {
logger.ComponentError(logging.ComponentGeneral, "HTTP server error", zap.Error(err))
// continue to shutdown path so we close resources cleanly
} else {
logger.ComponentInfo(logging.ComponentGeneral, "HTTP server exited normally")
}
}
logger.ComponentInfo(logging.ComponentGeneral, "Shutting down gateway HTTP server...")
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := server.Shutdown(ctx); err != nil {
logger.ComponentError(logging.ComponentGeneral, "HTTP server shutdown error", zap.Error(err))
} else {
logger.ComponentInfo(logging.ComponentGeneral, "Gateway shutdown complete")
}
}