From d42d1a7ea48850a97f6ab74c181e4348885a4068 Mon Sep 17 00:00:00 2001
From: Ainar Garipov <A.Garipov@AdGuard.COM>
Date: Mon, 10 Oct 2022 18:34:53 +0300
Subject: [PATCH] all: imp chlog; dry; fix races

---
 CHANGELOG.md               |  9 ++++++---
 internal/aghhttp/header.go |  3 +++
 internal/home/control.go   | 30 +++++++++++++++++++++---------
 3 files changed, 30 insertions(+), 12 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index fa81d81f..9f1985df 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,10 +10,7 @@ and this project adheres to
 
 
 ## [Unreleased]
-### Fixed
-- Web UI HTTP/3 not working  [#4986]
 
-[#4986]: https://github.com/AdguardTeam/AdGuardHome/issues/4986
 <!--
 ## [v0.108.0] - TBA (APPROX.)
 -->
@@ -24,7 +21,13 @@ and this project adheres to
   opposed to URL paths ([#3418]).  Note that AdGuard Home checks the server name
   only if the URL does not contain a ClientID.
 
+### Fixed
+
+- Web UI not switching to HTTP/3 ([#4986], [#4993]).
+
 [#3418]: https://github.com/AdguardTeam/AdGuardHome/issues/3418
+[#4986]: https://github.com/AdguardTeam/AdGuardHome/issues/4986
+[#4993]: https://github.com/AdguardTeam/AdGuardHome/issues/4993
 
 [clientid]:  https://github.com/AdguardTeam/AdGuardHome/wiki/Clients#clientid
 
diff --git a/internal/aghhttp/header.go b/internal/aghhttp/header.go
index a0b79425..0bfbcff2 100644
--- a/internal/aghhttp/header.go
+++ b/internal/aghhttp/header.go
@@ -8,11 +8,14 @@ package aghhttp
 const (
 	HdrNameAcceptEncoding           = "Accept-Encoding"
 	HdrNameAccessControlAllowOrigin = "Access-Control-Allow-Origin"
+	HdrNameAltSvc                   = "Alt-Svc"
 	HdrNameContentEncoding          = "Content-Encoding"
 	HdrNameContentType              = "Content-Type"
+	HdrNameOrigin                   = "Origin"
 	HdrNameServer                   = "Server"
 	HdrNameTrailer                  = "Trailer"
 	HdrNameUserAgent                = "User-Agent"
+	HdrNameVary                     = "Vary"
 )
 
 // HTTP header value constants.
diff --git a/internal/home/control.go b/internal/home/control.go
index b3610c87..48ac45f4 100644
--- a/internal/home/control.go
+++ b/internal/home/control.go
@@ -320,14 +320,26 @@ func handleHTTPSRedirect(w http.ResponseWriter, r *http.Request) (ok bool) {
 		return false
 	}
 
-	// Let the browser know that server support HTTP/3
-	// max-age is set to default (24 hourd)
+	var serveHTTP3 bool
+	var portHTTPS int
+	func() {
+		config.RLock()
+		defer config.RUnlock()
+
+		serveHTTP3, portHTTPS = config.DNS.ServeHTTP3, config.TLS.PortHTTPS
+	}()
+
+	respHdr := w.Header()
+
+	// Let the browser know that server supports HTTP/3.
 	//
-	// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Alt-Svc
-	// TODO: take max-age from config and set
-	if config.DNS.ServeHTTP3 {
-		altSvc := fmt.Sprintf(`h3=":%[1]v";`, config.TLS.PortHTTPS)
-		w.Header().Set("Alt-Svc", altSvc)
+	// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Alt-Svc.
+	//
+	// TODO(a.garipov): Consider adding a configurable max-age.  Currently, the
+	// default is 24 hours.
+	if serveHTTP3 {
+		altSvc := fmt.Sprintf(`h3=":%d"`, portHTTPS)
+		respHdr.Set(aghhttp.HdrNameAltSvc, altSvc)
 	}
 
 	if r.TLS == nil && web.forceHTTPS {
@@ -357,8 +369,8 @@ func handleHTTPSRedirect(w http.ResponseWriter, r *http.Request) (ok bool) {
 		Host:   r.Host,
 	}
 
-	w.Header().Set("Access-Control-Allow-Origin", originURL.String())
-	w.Header().Set("Vary", "Origin")
+	respHdr.Set(aghhttp.HdrNameAccessControlAllowOrigin, originURL.String())
+	respHdr.Set(aghhttp.HdrNameVary, aghhttp.HdrNameOrigin)
 
 	return true
 }