1
0
Fork 0

httpserver is now better usable to handle multiple domains

BREAKING CHANGE:
Authentication is domain dependend and runs in the site registration.
Dieser Commit ist enthalten in:
Sebastian Tobie 2021-01-24 16:25:58 +01:00
Ursprung c2ca39ec19
Commit dceb47069e
2 geänderte Dateien mit 55 neuen und 38 gelöschten Zeilen

Datei anzeigen

@ -4,4 +4,5 @@ package httpserver
const ( const (
Accounts = "account" Accounts = "account"
Menus = "menu" Menus = "menu"
Domain = "domain"
) )

92
http.go
Datei anzeigen

@ -29,13 +29,17 @@ func (c *Config) MarshalLogObject(e *log.Entry) {
type Server struct { type Server struct {
http *http.Server http *http.Server
conf *Config conf *Config
router *gin.Engine
mrouter map[string]*gin.Engine mrouter map[string]*gin.Engine
config *toml.Tree config *toml.Tree
authhf auth.AuthenticationHandler
sites []Site sites []Site
menus []menus.Menu menu []menus.Menu
NotFoundHandler gin.HandlerFunc NotFoundHandler http.Handler
}
func init() {
gin.DebugPrintRouteFunc = func(httpMethod, absolutePath, handlerName string, nuHandlers int) {
log.Trace().Msgf("%-4s(%02d): %-20s %s", httpMethod, nuHandlers, absolutePath, handlerName)
}
} }
// StartServer starts the server as configured and sends the errormessage to the log. // StartServer starts the server as configured and sends the errormessage to the log.
@ -54,19 +58,32 @@ func (s *Server) StartServer() {
} }
// DomainRouter redirects the requests to the routers of the domains // DomainRouter redirects the requests to the routers of the domains
func (s *Server) DomainRouter(c *gin.Context) { func (s *Server) DomainRouter(w http.ResponseWriter, r *http.Request) {
domain := c.Request.URL.Host var domain string
entry := log.Trace().Str("domain", domain) if r.URL.Host != "" {
domain = r.URL.Host
} else if r.Host != "" {
domain = r.Host
} else if r.Header.Get("X-Original-Host") != "" {
domain = r.Header.Get("X-Original-Host")
}
r.Host = domain
r.URL.Host = domain
for header, value := range map[string][]string(r.Header) {
log.Trace().Strs(header, value).Msg("Headers")
}
if router, found := s.mrouter[domain]; found { if router, found := s.mrouter[domain]; found {
entry.Msg("Found domain") router.NoMethod(gin.WrapH(s.NotFoundHandler))
router.NoMethod(s.NotFoundHandler) router.NoRoute(gin.WrapH(s.NotFoundHandler))
router.NoRoute(s.NotFoundHandler) router.ServeHTTP(w, r)
c.Set("domain", domain)
router.HandleContext(c)
return return
} }
entry.Interface("domains", s.mrouter).Msg("domain not found") var entrys []string
s.NotFoundHandler(c) for d := range s.mrouter {
entrys = append(entrys, d)
}
log.Trace().Strs("reqistred domains", entrys).Msg("domain not found")
s.NotFoundHandler.ServeHTTP(w, r)
} }
// CreateServer creates an server that can be run in a coroutine. // CreateServer creates an server that can be run in a coroutine.
@ -79,19 +96,8 @@ func CreateServer(config *toml.Tree) *Server {
conf: &Config{ conf: &Config{
Addr: "127.0.0.1:8080", Addr: "127.0.0.1:8080",
}, },
router: gin.New(),
mrouter: map[string]*gin.Engine{}, mrouter: map[string]*gin.Engine{},
authhf: &auth.AnonAccountHandler{},
} }
mw := []gin.HandlerFunc{
func(c *gin.Context) {
c.Set(Accounts, server.authhf.Account(c))
c.Set(Menus, server.menus)
},
server.DomainRouter,
}
server.Use(mw...)
server.router.RouterGroup.Handlers = mw
if err := config.Unmarshal(server.conf); err != nil { if err := config.Unmarshal(server.conf); err != nil {
log.Error().Msg("Problem mapping config to Configstruct") log.Error().Msg("Problem mapping config to Configstruct")
} }
@ -99,26 +105,20 @@ func CreateServer(config *toml.Tree) *Server {
server.http = &http.Server{ server.http = &http.Server{
Addr: server.conf.Addr, Addr: server.conf.Addr,
ErrorLog: log.DefaultLogger.Std(log.ErrorLevel, log.Context{}, "", 0), ErrorLog: log.DefaultLogger.Std(log.ErrorLevel, log.Context{}, "", 0),
Handler: server.router, Handler: http.HandlerFunc(server.DomainRouter),
TLSConfig: server.conf.TLSconfig, TLSConfig: server.conf.TLSconfig,
} }
server.NotFoundHandler = gin.WrapH(http.NotFoundHandler()) server.NotFoundHandler = http.NotFoundHandler()
gin.DebugPrintRouteFunc = func(httpMethod, absolutePath, handlerName string, nuHandlers int) { server.menu = []menus.Menu{}
log.Trace().Msgf("%-4s(%02d): %-20s %s", httpMethod, nuHandlers-len(mw), absolutePath, handlerName)
}
server.menus = []menus.Menu{}
return server return server
} }
// Use installs the middleware into the router. // Use installs the middleware into the router.
// The Middleware must be able to detect multiple calls byy itself. Deduplication is not performed. // The Middleware must be able to detect multiple calls byy itself. Deduplication is not performed.
func (s *Server) Use(m ...gin.HandlerFunc) { func (s *Server) Use(m ...gin.HandlerFunc) {
s.router.Use(m...) for _, router := range s.mrouter {
} router.Use(m...)
}
// UseAuthBackend is the funćtion that sets the Handler for the authentication
func (s *Server) UseAuthBackend(a auth.AuthenticationHandler) {
s.authhf = a
} }
// Stop Shuts the Server down // Stop Shuts the Server down
@ -136,12 +136,28 @@ type Site interface {
Teardown() Teardown()
} }
func (s *Server) menus() []menus.Menu {
return s.menu
}
// RegisterSite adds an site to the engine as its own grouo // RegisterSite adds an site to the engine as its own grouo
func (s *Server) RegisterSite(domain, path string, site Site) { func (s *Server) RegisterSite(domain, path string, site Site) {
var router *gin.Engine var router *gin.Engine
var found bool var found bool
if router, found = s.mrouter[domain]; !found { if router, found = s.mrouter[domain]; !found {
var authhf auth.AuthenticationHandler
router = gin.New() router = gin.New()
mw := []gin.HandlerFunc{
func(c *gin.Context) {
c.Set(Menus, s.menus)
c.Set(Domain, domain)
},
}
if authhf, found = site.(auth.AuthenticationHandler); !found {
authhf = &auth.AnonAccountHandler{}
}
mw = append(mw, func(c *gin.Context) { authhf.Account(c) })
router.Use(mw...)
s.mrouter[domain] = router s.mrouter[domain] = router
} }
site.Init(router.Group(path)) site.Init(router.Group(path))
@ -149,7 +165,7 @@ func (s *Server) RegisterSite(domain, path string, site Site) {
if ms, ok := site.(menus.MenuSite); ok { if ms, ok := site.(menus.MenuSite); ok {
menus := ms.Menu(domain) menus := ms.Menu(domain)
log.Debug().Msgf("%d menus are added", len(menus)) log.Debug().Msgf("%d menus are added", len(menus))
s.menus = append(s.menus, menus...) s.menu = append(s.menu, menus...)
} }
return return
} }