Add a timeout middleware to the server
This commit is contained in:
parent
d53afa4903
commit
bfdf7bf7d2
24
cmd/start.go
24
cmd/start.go
@ -3,6 +3,7 @@ package cmd
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"git.coopcloud.tech/wiki-cafe/member-console/internal/auth"
|
||||
"git.coopcloud.tech/wiki-cafe/member-console/internal/middleware"
|
||||
@ -36,18 +37,23 @@ var startCmd = &cobra.Command{
|
||||
|
||||
// Create middleware stack
|
||||
stack := middleware.CreateStack(
|
||||
middleware.Recovery(), // Add recovery middleware first to catch all panics
|
||||
middleware.RequestID(), // Add request ID middleware for tracing
|
||||
middleware.SecureHeaders,
|
||||
middleware.Logging,
|
||||
middleware.MaxBodySize(1024*1024), // 1MB size limit
|
||||
authConfig.Middleware(),
|
||||
middleware.Recovery(), // Catch all panics
|
||||
middleware.TimeoutMiddleware(32*time.Second), // Set request timeout
|
||||
middleware.RequestID(), // Generate a unique request ID
|
||||
middleware.MaxBodySize(1024*1024), // 1MB size limit
|
||||
middleware.SecureHeaders, // Set secure headers
|
||||
middleware.Logging, // Log requests
|
||||
authConfig.Middleware(), // OIDC authentication middleware
|
||||
)
|
||||
|
||||
// Create HTTP server
|
||||
server := http.Server{
|
||||
Addr: ":" + port,
|
||||
Handler: stack(httpRequestRouter),
|
||||
Addr: ":" + port,
|
||||
Handler: stack(httpRequestRouter),
|
||||
ReadTimeout: 2 * time.Second,
|
||||
WriteTimeout: 4 * time.Second,
|
||||
IdleTimeout: 8 * time.Second,
|
||||
MaxHeaderBytes: 1024 * 1024, // 1MB
|
||||
}
|
||||
|
||||
// Serve the components directory
|
||||
@ -76,4 +82,4 @@ func init() {
|
||||
|
||||
// Add the command to the root command
|
||||
rootCmd.AddCommand(startCmd)
|
||||
}
|
||||
}
|
||||
|
46
internal/middleware/timeout.go
Normal file
46
internal/middleware/timeout.go
Normal file
@ -0,0 +1,46 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TimeoutMiddleware is necessary in addition to http.Server's ReadTimeout,
|
||||
// WriteTimeout, and IdleTimeout. http.Server's timeouts are network-level
|
||||
// timeouts, while this middleware's timeout is at the application level.
|
||||
// TODO: Verify this statement
|
||||
|
||||
// TimeoutMiddleware sets a timeout for each request
|
||||
func TimeoutMiddleware(duration time.Duration) Middleware {
|
||||
return func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Create a context with a timeout
|
||||
ctx, cancel := context.WithTimeout(r.Context(), duration)
|
||||
defer cancel()
|
||||
|
||||
// Create a channel to signal when the request is done
|
||||
done := make(chan struct{})
|
||||
|
||||
// Create a new request with the timeout context
|
||||
r = r.WithContext(ctx)
|
||||
|
||||
// Use a goroutine to run the next handler
|
||||
go func() {
|
||||
next.ServeHTTP(w, r)
|
||||
close(done)
|
||||
}()
|
||||
|
||||
// Wait for the handler to finish or the context to timeout
|
||||
select {
|
||||
case <-done:
|
||||
// Request finished within the timeout
|
||||
return
|
||||
case <-ctx.Done():
|
||||
// Timeout occurred, respond with a timeout error
|
||||
http.Error(w, "Request timed out", http.StatusGatewayTimeout)
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user