1
0
Fork 0
mirror of https://github.com/restic/restic.git synced 2024-12-23 16:26:11 +00:00

serve: Properly shut down the server

This commit is contained in:
Alexander Neumann 2024-04-26 19:21:32 +02:00
parent 8a5ac6dc13
commit d463996ce9

View file

@ -2,7 +2,10 @@ package main
import ( import (
"context" "context"
"fmt"
"net"
"net/http" "net/http"
"time"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -35,6 +38,8 @@ func init() {
cmdFlags.StringVarP(&serveOptions.Listen, "listen", "l", "localhost:3080", "set the listen host name and `address`") cmdFlags.StringVarP(&serveOptions.Listen, "listen", "l", "localhost:3080", "set the listen host name and `address`")
} }
const serverShutdownTimeout = 30 * time.Second
func runWebServer(ctx context.Context, opts ServeOptions, gopts GlobalOptions, args []string) error { func runWebServer(ctx context.Context, opts ServeOptions, gopts GlobalOptions, args []string) error {
if len(args) > 0 { if len(args) > 0 {
return errors.Fatal("this command does not accept additional arguments") return errors.Fatal("this command does not accept additional arguments")
@ -57,10 +62,42 @@ func runWebServer(ctx context.Context, opts ServeOptions, gopts GlobalOptions, a
return err return err
} }
srv := server.New(repo, snapshotLister, TimeFormat) srv := http.Server{
BaseContext: func(l net.Listener) context.Context {
// just return the global context
return ctx
},
Handler: server.New(repo, snapshotLister, TimeFormat),
}
listener, err := net.Listen("tcp", opts.Listen)
if err != nil {
return fmt.Errorf("start listener: %v", err)
}
// wait until context is cancelled, then close listener
go func() {
<-ctx.Done()
Printf("gracefully shutting down server\n")
ctxTimeout, cancel := context.WithTimeout(context.Background(), serverShutdownTimeout)
defer cancel()
_ = srv.Shutdown(ctxTimeout)
}()
Printf("Now serving the repository at http://%s\n", opts.Listen) Printf("Now serving the repository at http://%s\n", opts.Listen)
Printf("When finished, quit with Ctrl-c here.\n") Printf("When finished, quit with Ctrl-c here.\n")
return http.ListenAndServe(opts.Listen, srv) err = srv.Serve(listener)
if errors.Is(err, http.ErrServerClosed) {
err = nil
}
if err != nil {
return fmt.Errorf("serve: %v", err)
}
return nil
} }