core: fix graceful stop (#4866)

core: fix graceful stop (#4865)

* core/grpc: fix graceful stop

* core/http: add graceful stop serve

Co-authored-by: Caleb Doxsey <cdoxsey@pomerium.com>
This commit is contained in:
backport-actions-token[bot] 2023-12-29 10:24:21 -07:00 committed by GitHub
parent 33b4662187
commit 15ebb4dba2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 311 additions and 48 deletions

48
pkg/httputil/serve.go Normal file
View file

@ -0,0 +1,48 @@
// Package httputil contains additional functionality for working with http.
package httputil
import (
"context"
"errors"
"net"
"net/http"
"time"
"github.com/pomerium/pomerium/pkg/contextutil"
)
// 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(contextutil.OnlyValues(ctx))
srv := http.Server{
Handler: handler,
BaseContext: func(l 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
}