Server
Start HTTP, HTTPS, and mTLS servers with graceful shutdown.
3 minute read
HTTP Server
Basic HTTP Server
Start an HTTP server:
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer cancel()
if err := a.Start(ctx, ":8080"); err != nil {
log.Fatal(err)
}
Custom Address
Bind to specific interface:
a.Start(ctx, "127.0.0.1:8080") // Localhost only
a.Start(ctx, "0.0.0.0:8080") // All interfaces
HTTPS Server
Start HTTPS Server
Start with TLS certificates:
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer cancel()
if err := a.StartTLS(ctx, ":8443", "server.crt", "server.key"); err != nil {
log.Fatal(err)
}
Generate Self-Signed Certificate
For development:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes
mTLS Server
Start mTLS Server
Mutual TLS with client certificate verification:
// Load server certificate
serverCert, err := tls.LoadX509KeyPair("server.crt", "server.key")
if err != nil {
log.Fatal(err)
}
// Load CA certificate for client validation
caCert, err := os.ReadFile("ca.crt")
if err != nil {
log.Fatal(err)
}
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
// Start mTLS server
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer cancel()
err = a.StartMTLS(ctx, ":8443", serverCert,
app.WithClientCAs(caCertPool),
app.WithMinVersion(tls.VersionTLS13),
)
Client Authorization
Authorize clients based on certificate:
err = a.StartMTLS(ctx, ":8443", serverCert,
app.WithClientCAs(caCertPool),
app.WithAuthorize(func(cert *x509.Certificate) (string, bool) {
// Extract principal from certificate
principal := cert.Subject.CommonName
// Check if authorized
if principal == "" {
return "", false
}
return principal, true
}),
)
Graceful Shutdown
Signal-Based Shutdown
Use signal.NotifyContext for graceful shutdown:
ctx, cancel := signal.NotifyContext(
context.Background(),
os.Interrupt,
syscall.SIGTERM,
)
defer cancel()
if err := a.Start(ctx, ":8080"); err != nil {
log.Fatal(err)
}
Shutdown Process
When context is canceled:
- Server stops accepting new connections
- OnShutdown hooks execute (LIFO order)
- Server waits for in-flight requests (up to shutdown timeout)
- Observability components shut down (metrics, tracing)
- OnStop hooks execute (best-effort)
- Process exits
Shutdown Timeout
Configure shutdown timeout:
a, err := app.New(
app.WithServer(
app.WithShutdownTimeout(30 * time.Second),
),
)
Default: 30 seconds
Complete Examples
HTTP with Graceful Shutdown
package main
import (
"context"
"log"
"os"
"os/signal"
"syscall"
"rivaas.dev/app"
)
func main() {
a := app.MustNew(
app.WithServiceName("api"),
)
a.GET("/", homeHandler)
ctx, cancel := signal.NotifyContext(
context.Background(),
os.Interrupt,
syscall.SIGTERM,
)
defer cancel()
log.Println("Server starting on :8080")
if err := a.Start(ctx, ":8080"); err != nil {
log.Fatal(err)
}
}
HTTPS with mTLS
package main
import (
"context"
"crypto/tls"
"crypto/x509"
"log"
"os"
"os/signal"
"syscall"
"rivaas.dev/app"
)
func main() {
a := app.MustNew(app.WithServiceName("secure-api"))
// Load certificates
serverCert, err := tls.LoadX509KeyPair("server.crt", "server.key")
if err != nil {
log.Fatal(err)
}
caCert, err := os.ReadFile("ca.crt")
if err != nil {
log.Fatal(err)
}
caCertPool := x509.NewCertPool()
caCertPool.AppendCertsFromPEM(caCert)
// Register routes
a.GET("/", homeHandler)
// Start mTLS server
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer cancel()
log.Println("mTLS server starting on :8443")
err = a.StartMTLS(ctx, ":8443", serverCert,
app.WithClientCAs(caCertPool),
app.WithMinVersion(tls.VersionTLS13),
)
if err != nil {
log.Fatal(err)
}
}
Next Steps
- Lifecycle - Use lifecycle hooks for initialization and cleanup
- Health Endpoints - Configure health checks
- Configuration - Configure server timeouts and limits
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.