From 6a62f704e2e8e2f7bebabaf9095ce24f382d2ab2 Mon Sep 17 00:00:00 2001
From: Rahul Somasundaram <Rahul.Somasundaram@checkpt.com>
Date: Tue, 4 Oct 2022 11:01:21 +0530
Subject: [PATCH 1/5] added h3 header

---
 internal/home/control.go | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/internal/home/control.go b/internal/home/control.go
index 54d2efb1..68892436 100644
--- a/internal/home/control.go
+++ b/internal/home/control.go
@@ -346,6 +346,11 @@ func handleHTTPSRedirect(w http.ResponseWriter, r *http.Request) (ok bool) {
 		Scheme: aghhttp.SchemeHTTP,
 		Host:   r.Host,
 	}
+
+	if config.DNS.ServeHTTP3 {
+		w.Header().Set("Alt-Svc", `h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"`)
+	}
+
 	w.Header().Set("Access-Control-Allow-Origin", originURL.String())
 	w.Header().Set("Vary", "Origin")
 

From b7e815483e7fe60d87019f3b64ad557afa5b6814 Mon Sep 17 00:00:00 2001
From: Rahul Somasundaram <Rahul.Somasundaram@checkpt.com>
Date: Wed, 5 Oct 2022 18:27:01 +0530
Subject: [PATCH 2/5] referred https port from config

---
 internal/home/control.go | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/internal/home/control.go b/internal/home/control.go
index 68892436..62a132c2 100644
--- a/internal/home/control.go
+++ b/internal/home/control.go
@@ -348,7 +348,8 @@ func handleHTTPSRedirect(w http.ResponseWriter, r *http.Request) (ok bool) {
 	}
 
 	if config.DNS.ServeHTTP3 {
-		w.Header().Set("Alt-Svc", `h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"`)
+		altSvc := fmt.Sprintf(`h3=":%[1]v"; ma=2592000,h3-29=":%[1]v"; ma=2592000,h3-Q050=":%[1]v";ma=2592000,h3-Q046=":%[1]v"; ma=2592000,h3-Q043=":%[1]v"; ma=2592000,quic=":%[1]v"; ma=2592000; v="46,43"`, config.TLS.PortHTTPS)
+		w.Header().Set("Alt-Svc", altSvc)
 	}
 
 	w.Header().Set("Access-Control-Allow-Origin", originURL.String())

From 0c0340d63e8a67c9c11e0c4df7a7d3d2343851a4 Mon Sep 17 00:00:00 2001
From: Rahul Somasundaram <Rahul.Somasundaram@checkpt.com>
Date: Thu, 6 Oct 2022 20:44:55 +0530
Subject: [PATCH 3/5] changes done based on review

1. set only `h3` header
2. set default max-age
3. support https redirect as well
---
 internal/home/control.go | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/internal/home/control.go b/internal/home/control.go
index 62a132c2..b3610c87 100644
--- a/internal/home/control.go
+++ b/internal/home/control.go
@@ -320,6 +320,16 @@ 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)
+	//
+	// 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)
+	}
+
 	if r.TLS == nil && web.forceHTTPS {
 		hostPort := host
 		if port := web.conf.PortHTTPS; port != defaultPortHTTPS {
@@ -347,11 +357,6 @@ func handleHTTPSRedirect(w http.ResponseWriter, r *http.Request) (ok bool) {
 		Host:   r.Host,
 	}
 
-	if config.DNS.ServeHTTP3 {
-		altSvc := fmt.Sprintf(`h3=":%[1]v"; ma=2592000,h3-29=":%[1]v"; ma=2592000,h3-Q050=":%[1]v";ma=2592000,h3-Q046=":%[1]v"; ma=2592000,h3-Q043=":%[1]v"; ma=2592000,quic=":%[1]v"; ma=2592000; v="46,43"`, config.TLS.PortHTTPS)
-		w.Header().Set("Alt-Svc", altSvc)
-	}
-
 	w.Header().Set("Access-Control-Allow-Origin", originURL.String())
 	w.Header().Set("Vary", "Origin")
 

From 51f426736caad69a9deedc9a37c870e5e4f3b537 Mon Sep 17 00:00:00 2001
From: Rahul Somasundaram <Rahul.Somasundaram@checkpt.com>
Date: Thu, 6 Oct 2022 20:53:23 +0530
Subject: [PATCH 4/5] updated changelog

---
 CHANGELOG.md | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 71b93339..1e5ea687 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,7 +10,10 @@ 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.)
 -->

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 5/5] 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
 }