Skip to content

Commit db29b3b

Browse files
Bryan C. Millscodebien
Bryan C. Mills
authored andcommitted
internal/https: wait for both handlers in ListenAndServe
Fixes golang/go#29941 Change-Id: I15a50983bb8c52b4f55bfbfb4ebe5aee1b10c73a Reviewed-on: https://go-review.googlesource.com/c/build/+/159701 Run-TryBot: Bryan C. Mills <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Brad Fitzpatrick <[email protected]>
1 parent 41d0125 commit db29b3b

File tree

1 file changed

+48
-18
lines changed

1 file changed

+48
-18
lines changed

internal/https/https.go

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -47,22 +47,39 @@ func ListenAndServe(handler http.Handler, opt *Options) error {
4747
if err != nil {
4848
return fmt.Errorf(`net.Listen("tcp", %q): %v`, opt.Addr, err)
4949
}
50+
defer ln.Close()
51+
52+
if opt.AutocertCacheBucket == "" {
53+
err := http.Serve(ln, handler)
54+
ln.Close()
55+
return fmt.Errorf("http.Serve = %v", err)
56+
}
5057

58+
// handler is served primarily via HTTPS, so just redirect HTTP to HTTPS.
59+
redirect := &http.Server{
60+
Addr: ln.Addr().String(),
61+
Handler: http.HandlerFunc(redirectToHTTPS),
62+
}
5163
errc := make(chan error)
5264
go func() {
53-
var h http.Handler
54-
if opt.AutocertCacheBucket != "" {
55-
// handler is served primarily via HTTPS, so just redirect HTTP to HTTPS.
56-
h = http.HandlerFunc(redirectToHTTPS)
57-
} else {
58-
h = handler
59-
}
60-
errc <- fmt.Errorf("http.Serve = %v", http.Serve(ln, h))
65+
err := redirect.Serve(ln)
66+
errc <- fmt.Errorf("http.Serve = %v", err)
6167
}()
62-
if opt.AutocertCacheBucket != "" {
63-
go func() { errc <- serveAutocertTLS(handler, opt.AutocertCacheBucket) }()
64-
}
65-
return <-errc
68+
69+
ctx, cancel := context.WithCancel(context.TODO())
70+
go func() {
71+
errc <- serveAutocertTLS(ctx, handler, opt.AutocertCacheBucket)
72+
}()
73+
74+
// Wait for the first error.
75+
err = <-errc
76+
77+
// Stop the other handler (whichever it may be) and wait for it to return.
78+
redirect.Close()
79+
cancel()
80+
<-errc
81+
82+
return err
6683
}
6784

6885
// redirectToHTTPS will redirect to the https version of the URL requested. If
@@ -80,13 +97,30 @@ func redirectToHTTPS(w http.ResponseWriter, r *http.Request) {
8097
// for its autocert cache. It will only serve on domains of the form *.golang.org.
8198
//
8299
// serveAutocertTLS always returns a non-nil error.
83-
func serveAutocertTLS(h http.Handler, bucket string) error {
100+
func serveAutocertTLS(ctx context.Context, h http.Handler, bucket string) error {
84101
ln, err := net.Listen("tcp", ":443")
85102
if err != nil {
86103
return err
87104
}
88105
defer ln.Close()
89-
sc, err := storage.NewClient(context.Background())
106+
107+
ctx, cancel := context.WithCancel(ctx)
108+
server := &http.Server{
109+
Addr: ln.Addr().String(),
110+
Handler: h,
111+
}
112+
done := make(chan struct{})
113+
go func() {
114+
<-ctx.Done()
115+
server.Close()
116+
close(done)
117+
}()
118+
defer func() {
119+
cancel()
120+
<-done
121+
}()
122+
123+
sc, err := storage.NewClient(ctx)
90124
if err != nil {
91125
return fmt.Errorf("storage.NewClient: %v", err)
92126
}
@@ -107,10 +141,6 @@ func serveAutocertTLS(h http.Handler, bucket string) error {
107141
NextProtos: []string{"h2", "http/1.1"},
108142
}
109143
tlsLn := tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, config)
110-
server := &http.Server{
111-
Addr: ln.Addr().String(),
112-
Handler: h,
113-
}
114144
if err := http2.ConfigureServer(server, nil); err != nil {
115145
return fmt.Errorf("http2.ConfigureServer: %v", err)
116146
}

0 commit comments

Comments
 (0)