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); err != nil {
log.Fatal(err)
}
Custom Address
Configure the listen address via options when creating the app. Default is :8080 for HTTP and :8443 for TLS/mTLS:
// Localhost only
a, err := app.New(
app.WithServiceName("my-api"),
app.WithHost("127.0.0.1"),
app.WithPort(8080),
)
// ...
a.Start(ctx)
// All interfaces (default)
a, err := app.New(
app.WithServiceName("my-api"),
app.WithPort(8080),
)
// ...
a.Start(ctx)
HTTPS Server
Start HTTPS Server
Configure TLS at construction with WithTLS, then start the server (default port 8443; use WithPort(443) to override):
a := app.MustNew(
app.WithServiceName("my-api"),
app.WithTLS("server.crt", "server.key"),
)
// ... register routes ...
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer cancel()
if err := a.Start(ctx); 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
Configure mTLS at construction with WithMTLS, then start the server:
// 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)
a := app.MustNew(
app.WithServiceName("my-api"),
app.WithMTLS(serverCert,
app.WithClientCAs(caCertPool),
app.WithMinVersion(tls.VersionTLS13),
), // default port 8443; use WithPort(443) to override
)
// ... register routes ...
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer cancel()
if err := a.Start(ctx); err != nil {
log.Fatal(err)
}
Client Authorization
Authorize clients based on certificate by adding WithAuthorize to WithMTLS:
a := app.MustNew(
app.WithServiceName("my-api"),
app.WithPort(8443),
app.WithMTLS(serverCert,
app.WithClientCAs(caCertPool),
app.WithAuthorize(func(cert *x509.Certificate) (string, bool) {
principal := cert.Subject.CommonName
if principal == "" {
return "", false
}
return principal, true
}),
),
)
// ...
if err := a.Start(ctx); err != nil { ... }
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); 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); 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() {
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)
a := app.MustNew(
app.WithServiceName("secure-api"),
app.WithMTLS(serverCert,
app.WithClientCAs(caCertPool),
app.WithMinVersion(tls.VersionTLS13),
), // default port 8443
)
a.GET("/", homeHandler)
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer cancel()
log.Println("mTLS server starting on :8443 (default)")
if err := a.Start(ctx); 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.