From ed728f57e06568eb4b618610fd353b4b9fe02a36 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Sat, 2 Oct 2021 15:29:27 +0100 Subject: [PATCH] Remove WriteTimeout from HTTP Golangs built in HTTP server does not allow different HTTP timeout for different types of handlers, so we cannot have a write timeout as we attempt to do long polling (my bad). See linked article. Also removed redundant server declaration --- app.go | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/app.go b/app.go index dc398eb..8be137c 100644 --- a/app.go +++ b/app.go @@ -172,16 +172,18 @@ func (h *Headscale) Serve() error { r.GET("/apple/:platform", h.ApplePlatformConfig) var err error - timeout := 30 * time.Second - go h.watchForKVUpdates(5000) go h.expireEphemeralNodes(5000) s := &http.Server{ - Addr: h.cfg.Addr, - Handler: r, - ReadTimeout: timeout, - WriteTimeout: timeout, + Addr: h.cfg.Addr, + Handler: r, + ReadTimeout: 30 * time.Second, + // Go does not handle timeouts in HTTP very well, and there is + // no good way to handle streaming timeouts, therefore we need to + // keep this at unlimited and be careful to clean up connections + // https://blog.cloudflare.com/the-complete-guide-to-golang-net-http-timeouts/#aboutstreaming + WriteTimeout: 0, } if h.cfg.TLSLetsEncryptHostname != "" { @@ -194,13 +196,9 @@ func (h *Headscale) Serve() error { HostPolicy: autocert.HostWhitelist(h.cfg.TLSLetsEncryptHostname), Cache: autocert.DirCache(h.cfg.TLSLetsEncryptCacheDir), } - s := &http.Server{ - Addr: h.cfg.Addr, - TLSConfig: m.TLSConfig(), - Handler: r, - ReadTimeout: timeout, - WriteTimeout: timeout, - } + + s.TLSConfig = m.TLSConfig() + if h.cfg.TLSLetsEncryptChallengeType == "TLS-ALPN-01" { // Configuration via autocert with TLS-ALPN-01 (https://tools.ietf.org/html/rfc8737) // The RFC requires that the validation is done on port 443; in other words, headscale @@ -211,7 +209,6 @@ func (h *Headscale) Serve() error { // port 80 for the certificate validation in addition to the headscale // service, which can be configured to run on any other port. go func() { - log.Fatal(). Err(http.ListenAndServe(h.cfg.TLSLetsEncryptListen, m.HTTPHandler(http.HandlerFunc(h.redirect)))). Msg("failed to set up a HTTP server")