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
|
### Changed
|
||||||
|
|
||||||
|
- Improved HTTP requests handling and timeouts. ([#2343]).
|
||||||
- Our snap package now uses the `core20` image as its base [#2306].
|
- Our snap package now uses the `core20` image as its base [#2306].
|
||||||
- Various internal improvements ([#2271], [#2297]).
|
- Various internal improvements ([#2271], [#2297]).
|
||||||
|
|
||||||
[#2271]: https://github.com/AdguardTeam/AdGuardHome/issues/2271
|
[#2271]: https://github.com/AdguardTeam/AdGuardHome/issues/2271
|
||||||
[#2297]: https://github.com/AdguardTeam/AdGuardHome/issues/2297
|
[#2297]: https://github.com/AdguardTeam/AdGuardHome/issues/2297
|
||||||
[#2306]: https://github.com/AdguardTeam/AdGuardHome/issues/2306
|
[#2306]: https://github.com/AdguardTeam/AdGuardHome/issues/2306
|
||||||
|
[#2343]: https://github.com/AdguardTeam/AdGuardHome/issues/2343
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
|
|
@ -360,7 +360,7 @@ func handleLogout(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
// RegisterAuthHandlers - register handlers
|
// RegisterAuthHandlers - register handlers
|
||||||
func RegisterAuthHandlers() {
|
func RegisterAuthHandlers() {
|
||||||
http.Handle("/control/login", postInstallHandler(ensureHandler("POST", handleLogin)))
|
Context.mux.Handle("/control/login", postInstallHandler(ensureHandler("POST", handleLogin)))
|
||||||
httpRegister("GET", "/control/logout", handleLogout)
|
httpRegister("GET", "/control/logout", handleLogout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -107,24 +107,24 @@ func registerControlHandlers() {
|
||||||
httpRegister(http.MethodGet, "/control/status", handleStatus)
|
httpRegister(http.MethodGet, "/control/status", handleStatus)
|
||||||
httpRegister(http.MethodPost, "/control/i18n/change_language", handleI18nChangeLanguage)
|
httpRegister(http.MethodPost, "/control/i18n/change_language", handleI18nChangeLanguage)
|
||||||
httpRegister(http.MethodGet, "/control/i18n/current_language", handleI18nCurrentLanguage)
|
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.MethodPost, "/control/update", handleUpdate)
|
||||||
httpRegister(http.MethodGet, "/control/profile", handleGetProfile)
|
httpRegister(http.MethodGet, "/control/profile", handleGetProfile)
|
||||||
|
|
||||||
// No auth is necessary for DOH/DOT configurations
|
// No auth is necessary for DOH/DOT configurations
|
||||||
http.HandleFunc("/apple/doh.mobileconfig", postInstall(handleMobileConfigDoh))
|
Context.mux.HandleFunc("/apple/doh.mobileconfig", postInstall(handleMobileConfigDoh))
|
||||||
http.HandleFunc("/apple/dot.mobileconfig", postInstall(handleMobileConfigDot))
|
Context.mux.HandleFunc("/apple/dot.mobileconfig", postInstall(handleMobileConfigDot))
|
||||||
RegisterAuthHandlers()
|
RegisterAuthHandlers()
|
||||||
}
|
}
|
||||||
|
|
||||||
func httpRegister(method string, url string, handler func(http.ResponseWriter, *http.Request)) {
|
func httpRegister(method string, url string, handler func(http.ResponseWriter, *http.Request)) {
|
||||||
if len(method) == 0 {
|
if len(method) == 0 {
|
||||||
// "/dns-query" handler doesn't need auth, gzip and isn't restricted by 1 HTTP method
|
// "/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
|
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
|
// it also enforces HTTPS if it is enabled and configured
|
||||||
func postInstall(handler func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {
|
func postInstall(handler func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
if Context.firstRun &&
|
if Context.firstRun &&
|
||||||
!strings.HasPrefix(r.URL.Path, "/install.") &&
|
!strings.HasPrefix(r.URL.Path, "/install.") &&
|
||||||
!strings.HasPrefix(r.URL.Path, "/assets/") {
|
!strings.HasPrefix(r.URL.Path, "/assets/") {
|
||||||
|
|
|
@ -372,7 +372,7 @@ func (web *Web) handleInstallConfigure(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (web *Web) registerInstallHandlers() {
|
func (web *Web) registerInstallHandlers() {
|
||||||
http.HandleFunc("/control/install/get_addresses", preInstall(ensureGET(web.handleInstallGetAddresses)))
|
Context.mux.HandleFunc("/control/install/get_addresses", preInstall(ensureGET(web.handleInstallGetAddresses)))
|
||||||
http.HandleFunc("/control/install/check_config", preInstall(ensurePOST(web.handleInstallCheckConfig)))
|
Context.mux.HandleFunc("/control/install/check_config", preInstall(ensurePOST(web.handleInstallCheckConfig)))
|
||||||
http.HandleFunc("/control/install/configure", preInstall(ensurePOST(web.handleInstallConfigure)))
|
Context.mux.HandleFunc("/control/install/configure", preInstall(ensurePOST(web.handleInstallConfigure)))
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func testStartFilterListener() net.Listener {
|
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
|
content := `||example.org^$third-party
|
||||||
# Inline comment example
|
# Inline comment example
|
||||||
||example.com^$third-party
|
||example.com^$third-party
|
||||||
|
@ -26,7 +27,7 @@ func testStartFilterListener() net.Listener {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() { _ = http.Serve(listener, nil) }()
|
go func() { _ = http.Serve(listener, mux) }()
|
||||||
return listener
|
return listener
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,9 @@ type homeContext struct {
|
||||||
|
|
||||||
ipDetector *ipDetector
|
ipDetector *ipDetector
|
||||||
|
|
||||||
|
// mux is our custom http.ServeMux.
|
||||||
|
mux *http.ServeMux
|
||||||
|
|
||||||
// Runtime properties
|
// Runtime properties
|
||||||
// --
|
// --
|
||||||
|
|
||||||
|
@ -187,6 +190,8 @@ func setupContext(args options) {
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Context.mux = http.NewServeMux()
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupConfig(args options) {
|
func setupConfig(args options) {
|
||||||
|
@ -306,6 +311,10 @@ func run(args options) {
|
||||||
firstRun: Context.firstRun,
|
firstRun: Context.firstRun,
|
||||||
BindHost: config.BindHost,
|
BindHost: config.BindHost,
|
||||||
BindPort: config.BindPort,
|
BindPort: config.BindPort,
|
||||||
|
|
||||||
|
ReadTimeout: ReadTimeout,
|
||||||
|
ReadHeaderTimeout: ReadHeaderTimeout,
|
||||||
|
WriteTimeout: WriteTimeout,
|
||||||
}
|
}
|
||||||
Context.web = CreateWeb(&webConf)
|
Context.web = CreateWeb(&webConf)
|
||||||
if Context.web == nil {
|
if Context.web == nil {
|
||||||
|
|
|
@ -2,7 +2,6 @@ package home
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/aghio"
|
"github.com/AdguardTeam/AdGuardHome/internal/aghio"
|
||||||
|
|
||||||
|
@ -41,19 +40,3 @@ func limitRequestBody(h http.Handler) (limited http.Handler) {
|
||||||
h.ServeHTTP(w, r)
|
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"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/util"
|
"github.com/AdguardTeam/AdGuardHome/internal/util"
|
||||||
"github.com/AdguardTeam/golibs/log"
|
"github.com/AdguardTeam/golibs/log"
|
||||||
|
@ -15,11 +16,37 @@ import (
|
||||||
"github.com/gobuffalo/packr"
|
"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 {
|
type WebConfig struct {
|
||||||
firstRun bool
|
firstRun bool
|
||||||
BindHost string
|
BindHost string
|
||||||
BindPort int
|
BindPort int
|
||||||
PortHTTPS 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
|
// HTTPSServer - HTTPS Server
|
||||||
|
@ -66,12 +93,12 @@ func CreateWeb(conf *WebConfig) *Web {
|
||||||
box := packr.NewBox("../../build/static")
|
box := packr.NewBox("../../build/static")
|
||||||
|
|
||||||
// if not configured, redirect / to /install.html, otherwise redirect /install.html to /
|
// 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
|
// add handlers for /install paths, we only need them when we're not configured yet
|
||||||
if conf.firstRun {
|
if conf.firstRun {
|
||||||
log.Info("This is the first launch of AdGuard Home, redirecting everything to /install.html ")
|
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()
|
w.registerInstallHandlers()
|
||||||
} else {
|
} else {
|
||||||
registerControlHandlers()
|
registerControlHandlers()
|
||||||
|
@ -141,7 +168,10 @@ func (web *Web) Start() {
|
||||||
web.httpServer = &http.Server{
|
web.httpServer = &http.Server{
|
||||||
ErrorLog: web.errLogger,
|
ErrorLog: web.errLogger,
|
||||||
Addr: address,
|
Addr: address,
|
||||||
Handler: withMiddlewares(http.DefaultServeMux, filterPProf, limitRequestBody),
|
Handler: withMiddlewares(Context.mux, limitRequestBody),
|
||||||
|
ReadTimeout: web.conf.ReadTimeout,
|
||||||
|
ReadHeaderTimeout: web.conf.ReadHeaderTimeout,
|
||||||
|
WriteTimeout: web.conf.WriteTimeout,
|
||||||
}
|
}
|
||||||
err := web.httpServer.ListenAndServe()
|
err := web.httpServer.ListenAndServe()
|
||||||
if err != http.ErrServerClosed {
|
if err != http.ErrServerClosed {
|
||||||
|
@ -198,6 +228,10 @@ func (web *Web) tlsServerLoop() {
|
||||||
RootCAs: Context.tlsRoots,
|
RootCAs: Context.tlsRoots,
|
||||||
CipherSuites: Context.tlsCiphers,
|
CipherSuites: Context.tlsCiphers,
|
||||||
},
|
},
|
||||||
|
Handler: Context.mux,
|
||||||
|
ReadTimeout: web.conf.ReadTimeout,
|
||||||
|
ReadHeaderTimeout: web.conf.ReadHeaderTimeout,
|
||||||
|
WriteTimeout: web.conf.WriteTimeout,
|
||||||
}
|
}
|
||||||
|
|
||||||
printHTTPAddresses("https")
|
printHTTPAddresses("https")
|
||||||
|
|
Loading…
Reference in New Issue