Pull request: 2343 http server
Merge in DNS/adguard-home from 2343-http-server to master
Closes #2343.
Squashed commit of the following:
commit f4ebfc129484fc3489409069b3580eb70d71cc74
Merge: b13ec7002 36c7735b8
Author: Eugene Burkov <e.burkov@adguard.com>
Date: Wed Nov 25 15:37:27 2020 +0300
Merge branch 'master' into 2343-http-server
commit b13ec70024f24f6b68b13a1ec6f27c89535feaf8
Author: Eugene Burkov <e.burkov@adguard.com>
Date: Wed Nov 25 15:31:36 2020 +0300
all: record changes
commit ce44aac9d43e32db3f68746dec7a4f21b0a9dea4
Author: Eugene Burkov <e.burkov@adguard.com>
Date: Wed Nov 25 14:00:45 2020 +0300
home: set http servers timeouts
commit 7f3e7385d1df39b39713b8ec443da5d9374d0bc8
Author: Eugene Burkov <e.burkov@adguard.com>
Date: Tue Nov 24 19:58:56 2020 +0300
home: replace default ServeMux with custom one.
This commit is contained in:
parent
36c7735b85
commit
b4a35fa887
@ -23,12 +23,14 @@ and this project adheres to
|
||||
|
||||
### Changed
|
||||
|
||||
- Improved HTTP requests handling and timeouts. ([#2343]).
|
||||
- Our snap package now uses the `core20` image as its base [#2306].
|
||||
- Various internal improvements ([#2271], [#2297]).
|
||||
|
||||
[#2271]: https://github.com/AdguardTeam/AdGuardHome/issues/2271
|
||||
[#2297]: https://github.com/AdguardTeam/AdGuardHome/issues/2297
|
||||
[#2306]: https://github.com/AdguardTeam/AdGuardHome/issues/2306
|
||||
[#2343]: https://github.com/AdguardTeam/AdGuardHome/issues/2343
|
||||
|
||||
### Fixed
|
||||
|
||||
|
@ -360,7 +360,7 @@ func handleLogout(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// RegisterAuthHandlers - register handlers
|
||||
func RegisterAuthHandlers() {
|
||||
http.Handle("/control/login", postInstallHandler(ensureHandler("POST", handleLogin)))
|
||||
Context.mux.Handle("/control/login", postInstallHandler(ensureHandler("POST", handleLogin)))
|
||||
httpRegister("GET", "/control/logout", handleLogout)
|
||||
}
|
||||
|
||||
|
@ -107,24 +107,24 @@ func registerControlHandlers() {
|
||||
httpRegister(http.MethodGet, "/control/status", handleStatus)
|
||||
httpRegister(http.MethodPost, "/control/i18n/change_language", handleI18nChangeLanguage)
|
||||
httpRegister(http.MethodGet, "/control/i18n/current_language", handleI18nCurrentLanguage)
|
||||
http.HandleFunc("/control/version.json", postInstall(optionalAuth(handleGetVersionJSON)))
|
||||
Context.mux.HandleFunc("/control/version.json", postInstall(optionalAuth(handleGetVersionJSON)))
|
||||
httpRegister(http.MethodPost, "/control/update", handleUpdate)
|
||||
httpRegister(http.MethodGet, "/control/profile", handleGetProfile)
|
||||
|
||||
// No auth is necessary for DOH/DOT configurations
|
||||
http.HandleFunc("/apple/doh.mobileconfig", postInstall(handleMobileConfigDoh))
|
||||
http.HandleFunc("/apple/dot.mobileconfig", postInstall(handleMobileConfigDot))
|
||||
Context.mux.HandleFunc("/apple/doh.mobileconfig", postInstall(handleMobileConfigDoh))
|
||||
Context.mux.HandleFunc("/apple/dot.mobileconfig", postInstall(handleMobileConfigDot))
|
||||
RegisterAuthHandlers()
|
||||
}
|
||||
|
||||
func httpRegister(method string, url string, handler func(http.ResponseWriter, *http.Request)) {
|
||||
if len(method) == 0 {
|
||||
// "/dns-query" handler doesn't need auth, gzip and isn't restricted by 1 HTTP method
|
||||
http.HandleFunc(url, postInstall(handler))
|
||||
Context.mux.HandleFunc(url, postInstall(handler))
|
||||
return
|
||||
}
|
||||
|
||||
http.Handle(url, postInstallHandler(optionalAuthHandler(gziphandler.GzipHandler(ensureHandler(method, handler)))))
|
||||
Context.mux.Handle(url, postInstallHandler(optionalAuthHandler(gziphandler.GzipHandler(ensureHandler(method, handler)))))
|
||||
}
|
||||
|
||||
// ----------------------------------
|
||||
@ -201,7 +201,6 @@ func preInstallHandler(handler http.Handler) http.Handler {
|
||||
// it also enforces HTTPS if it is enabled and configured
|
||||
func postInstall(handler func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
if Context.firstRun &&
|
||||
!strings.HasPrefix(r.URL.Path, "/install.") &&
|
||||
!strings.HasPrefix(r.URL.Path, "/assets/") {
|
||||
|
@ -372,7 +372,7 @@ func (web *Web) handleInstallConfigure(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (web *Web) registerInstallHandlers() {
|
||||
http.HandleFunc("/control/install/get_addresses", preInstall(ensureGET(web.handleInstallGetAddresses)))
|
||||
http.HandleFunc("/control/install/check_config", preInstall(ensurePOST(web.handleInstallCheckConfig)))
|
||||
http.HandleFunc("/control/install/configure", preInstall(ensurePOST(web.handleInstallConfigure)))
|
||||
Context.mux.HandleFunc("/control/install/get_addresses", preInstall(ensureGET(web.handleInstallGetAddresses)))
|
||||
Context.mux.HandleFunc("/control/install/check_config", preInstall(ensurePOST(web.handleInstallCheckConfig)))
|
||||
Context.mux.HandleFunc("/control/install/configure", preInstall(ensurePOST(web.handleInstallConfigure)))
|
||||
}
|
||||
|
@ -12,7 +12,8 @@ import (
|
||||
)
|
||||
|
||||
func testStartFilterListener() net.Listener {
|
||||
http.HandleFunc("/filters/1.txt", func(w http.ResponseWriter, r *http.Request) {
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/filters/1.txt", func(w http.ResponseWriter, r *http.Request) {
|
||||
content := `||example.org^$third-party
|
||||
# Inline comment example
|
||||
||example.com^$third-party
|
||||
@ -26,7 +27,7 @@ func testStartFilterListener() net.Listener {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
go func() { _ = http.Serve(listener, nil) }()
|
||||
go func() { _ = http.Serve(listener, mux) }()
|
||||
return listener
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,9 @@ type homeContext struct {
|
||||
|
||||
ipDetector *ipDetector
|
||||
|
||||
// mux is our custom http.ServeMux.
|
||||
mux *http.ServeMux
|
||||
|
||||
// Runtime properties
|
||||
// --
|
||||
|
||||
@ -187,6 +190,8 @@ func setupContext(args options) {
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
|
||||
Context.mux = http.NewServeMux()
|
||||
}
|
||||
|
||||
func setupConfig(args options) {
|
||||
@ -306,6 +311,10 @@ func run(args options) {
|
||||
firstRun: Context.firstRun,
|
||||
BindHost: config.BindHost,
|
||||
BindPort: config.BindPort,
|
||||
|
||||
ReadTimeout: ReadTimeout,
|
||||
ReadHeaderTimeout: ReadHeaderTimeout,
|
||||
WriteTimeout: WriteTimeout,
|
||||
}
|
||||
Context.web = CreateWeb(&webConf)
|
||||
if Context.web == nil {
|
||||
|
@ -2,7 +2,6 @@ package home
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghio"
|
||||
|
||||
@ -41,19 +40,3 @@ func limitRequestBody(h http.Handler) (limited http.Handler) {
|
||||
h.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
// TODO(a.garipov): We currently have to use this, because everything registers
|
||||
// its HTTP handlers in http.DefaultServeMux. In the future, refactor our HTTP
|
||||
// API initialization process and stop using the gosh darn http.DefaultServeMux
|
||||
// for anything at all. Gosh darn global variables.
|
||||
func filterPProf(h http.Handler) (filtered http.Handler) {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if strings.HasPrefix(r.URL.Path, "/debug/pprof") {
|
||||
http.NotFound(w, r)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
h.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/util"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
@ -15,11 +16,37 @@ import (
|
||||
"github.com/gobuffalo/packr"
|
||||
)
|
||||
|
||||
const (
|
||||
// ReadTimeout is the maximum duration for reading the entire request,
|
||||
// including the body.
|
||||
ReadTimeout = 10 * time.Second
|
||||
|
||||
// ReadHeaderTimeout is the amount of time allowed to read request
|
||||
// headers.
|
||||
ReadHeaderTimeout = 10 * time.Second
|
||||
|
||||
// WriteTimeout is the maximum duration before timing out writes of the
|
||||
// response.
|
||||
WriteTimeout = 10 * time.Second
|
||||
)
|
||||
|
||||
type WebConfig struct {
|
||||
firstRun bool
|
||||
BindHost string
|
||||
BindPort int
|
||||
PortHTTPS int
|
||||
|
||||
// ReadTimeout is an option to pass to http.Server for setting an
|
||||
// appropriate field.
|
||||
ReadTimeout time.Duration
|
||||
|
||||
// ReadHeaderTimeout is an option to pass to http.Server for setting an
|
||||
// appropriate field.
|
||||
ReadHeaderTimeout time.Duration
|
||||
|
||||
// WriteTimeout is an option to pass to http.Server for setting an
|
||||
// appropriate field.
|
||||
WriteTimeout time.Duration
|
||||
}
|
||||
|
||||
// HTTPSServer - HTTPS Server
|
||||
@ -66,12 +93,12 @@ func CreateWeb(conf *WebConfig) *Web {
|
||||
box := packr.NewBox("../../build/static")
|
||||
|
||||
// if not configured, redirect / to /install.html, otherwise redirect /install.html to /
|
||||
http.Handle("/", postInstallHandler(optionalAuthHandler(gziphandler.GzipHandler(http.FileServer(box)))))
|
||||
Context.mux.Handle("/", postInstallHandler(optionalAuthHandler(gziphandler.GzipHandler(http.FileServer(box)))))
|
||||
|
||||
// add handlers for /install paths, we only need them when we're not configured yet
|
||||
if conf.firstRun {
|
||||
log.Info("This is the first launch of AdGuard Home, redirecting everything to /install.html ")
|
||||
http.Handle("/install.html", preInstallHandler(http.FileServer(box)))
|
||||
Context.mux.Handle("/install.html", preInstallHandler(http.FileServer(box)))
|
||||
w.registerInstallHandlers()
|
||||
} else {
|
||||
registerControlHandlers()
|
||||
@ -139,9 +166,12 @@ func (web *Web) Start() {
|
||||
// we need to have new instance, because after Shutdown() the Server is not usable
|
||||
address := net.JoinHostPort(web.conf.BindHost, strconv.Itoa(web.conf.BindPort))
|
||||
web.httpServer = &http.Server{
|
||||
ErrorLog: web.errLogger,
|
||||
Addr: address,
|
||||
Handler: withMiddlewares(http.DefaultServeMux, filterPProf, limitRequestBody),
|
||||
ErrorLog: web.errLogger,
|
||||
Addr: address,
|
||||
Handler: withMiddlewares(Context.mux, limitRequestBody),
|
||||
ReadTimeout: web.conf.ReadTimeout,
|
||||
ReadHeaderTimeout: web.conf.ReadHeaderTimeout,
|
||||
WriteTimeout: web.conf.WriteTimeout,
|
||||
}
|
||||
err := web.httpServer.ListenAndServe()
|
||||
if err != http.ErrServerClosed {
|
||||
@ -198,6 +228,10 @@ func (web *Web) tlsServerLoop() {
|
||||
RootCAs: Context.tlsRoots,
|
||||
CipherSuites: Context.tlsCiphers,
|
||||
},
|
||||
Handler: Context.mux,
|
||||
ReadTimeout: web.conf.ReadTimeout,
|
||||
ReadHeaderTimeout: web.conf.ReadHeaderTimeout,
|
||||
WriteTimeout: web.conf.WriteTimeout,
|
||||
}
|
||||
|
||||
printHTTPAddresses("https")
|
||||
|
Loading…
Reference in New Issue
Block a user