mirror of
https://github.com/pomerium/pomerium.git
synced 2025-04-28 18:06:34 +02:00
46 lines
1.2 KiB
Go
46 lines
1.2 KiB
Go
// Package httputil contains additional functionality for working with http.
|
|
package httputil
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"net"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
// ServeWithGracefulStop serves the HTTP listener until ctx.Done(), and then gracefully stops and waits for gracefulTimeout
|
|
// before definitively stopping.
|
|
func ServeWithGracefulStop(ctx context.Context, handler http.Handler, li net.Listener, gracefulTimeout time.Duration) error {
|
|
// create a context that will be used for the http requests
|
|
// it will only be cancelled when baseCancel is called but will
|
|
// preserve the values from ctx
|
|
baseCtx, baseCancel := context.WithCancelCause(context.WithoutCancel(ctx))
|
|
|
|
srv := http.Server{
|
|
Handler: handler,
|
|
BaseContext: func(_ net.Listener) context.Context {
|
|
return baseCtx
|
|
},
|
|
}
|
|
|
|
go func() {
|
|
<-ctx.Done()
|
|
|
|
// create a context that will cancel after the graceful timeout
|
|
timeoutCtx, clearTimeout := context.WithTimeout(context.Background(), gracefulTimeout)
|
|
defer clearTimeout()
|
|
|
|
// shut the http server down
|
|
_ = srv.Shutdown(timeoutCtx)
|
|
|
|
// cancel the base context used for http requests
|
|
baseCancel(ctx.Err())
|
|
}()
|
|
|
|
err := srv.Serve(li)
|
|
if errors.Is(err, http.ErrServerClosed) {
|
|
err = nil
|
|
}
|
|
return err
|
|
}
|