Split code in respective files.
Resource method name change. Route list func
This commit is contained in:
78
serve.go
Normal file
78
serve.go
Normal file
@@ -0,0 +1,78 @@
|
||||
package mux
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"log"
|
||||
"log/slog"
|
||||
"net"
|
||||
"net/http"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
)
|
||||
|
||||
type ServeCB func(srv *http.Server) error
|
||||
|
||||
const (
|
||||
shutdownDelay = time.Second * 10
|
||||
shutdownHardDelay = time.Second * 5
|
||||
drainDelay = time.Second
|
||||
)
|
||||
|
||||
// Serve with graceful shutdown
|
||||
func (m *Mux) Serve(cb ServeCB) {
|
||||
rootCtx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
|
||||
defer stop()
|
||||
|
||||
// catch all options
|
||||
// lets get it thorugh all middlewares
|
||||
m.OPTIONS("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Length", "0")
|
||||
if r.ContentLength != 0 {
|
||||
// Read up to 4KB of OPTIONS body (as mentioned in the
|
||||
// spec as being reserved for future use), but anything
|
||||
// over that is considered a waste of server resources
|
||||
// (or an attack) and we abort and close the connection,
|
||||
// courtesy of MaxBytesReader's EOF behavior.
|
||||
mb := http.MaxBytesReader(w, r.Body, 4<<10)
|
||||
io.Copy(io.Discard, mb)
|
||||
}
|
||||
})
|
||||
|
||||
srvCtx, cancelSrvCtx := context.WithCancel(context.Background())
|
||||
srv := &http.Server{
|
||||
Handler: m,
|
||||
BaseContext: func(_ net.Listener) context.Context {
|
||||
return srvCtx
|
||||
},
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := cb(srv); !errors.Is(err, http.ErrServerClosed) {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
|
||||
// Wait for interrupt signal
|
||||
<-rootCtx.Done()
|
||||
|
||||
stop()
|
||||
m.IsShuttingDown.Store(true)
|
||||
slog.Info("received interrupt singal, shutting down")
|
||||
time.Sleep(drainDelay)
|
||||
slog.Info("readiness check propagated, now waiting for ongoing requests to finish.")
|
||||
|
||||
shutdownCtx, cancel := context.WithTimeout(context.Background(), shutdownDelay)
|
||||
defer cancel()
|
||||
|
||||
err := srv.Shutdown(shutdownCtx)
|
||||
cancelSrvCtx()
|
||||
if err != nil {
|
||||
log.Println("failed to wait for ongoing requests to finish, waiting for forced cancellation")
|
||||
time.Sleep(shutdownHardDelay)
|
||||
}
|
||||
|
||||
slog.Info("seerver shut down gracefully")
|
||||
}
|
Reference in New Issue
Block a user