1
0
Fork 0
httpserver/http.go

117 Zeilen
3.4 KiB
Go

2021-01-09 20:39:05 +00:00
package httpserver
import (
"context"
2021-01-09 20:39:05 +00:00
"crypto/tls"
"net/http"
"github.com/gin-gonic/gin"
"github.com/pelletier/go-toml"
"github.com/phuslu/log"
"go.sebtobie.de/httpserver/auth"
)
// Config that is used to map the toml config to the settings that are used.
type Config struct {
Addr string
TLSconfig *tls.Config
Certfile string
Keyfile string
}
// MarshalLogObject adds the information over the object to the *log.Entry
func (c *Config) MarshalLogObject(e *log.Entry) {
e.Str("Address", c.Addr).Bool("TLS", c.TLSconfig != nil).Strs("Cert", []string{c.Certfile, c.Keyfile})
}
// Server is an wrapper for the *http.Server and *gin.Engine
type Server struct {
http *http.Server
conf *Config
router *gin.Engine
config *toml.Tree
authhf auth.AuthenticationHandler
sites []Site
2021-01-09 20:39:05 +00:00
}
// StartServer starts the server as configured and sends the errormessage to the log.
func (s *Server) StartServer() {
log.Info().Msg("Starting server")
var err error
if s.conf.Certfile != "" && s.conf.Keyfile != "" {
err = s.http.ListenAndServeTLS(s.conf.Certfile, s.conf.Keyfile)
} else {
err = s.http.ListenAndServe()
}
if err != http.ErrServerClosed {
log.Error().Err(err).Msg("Server unexpected exited")
}
}
// CreateServer creates an server that can be run in a coroutine.
func CreateServer(config *toml.Tree) *Server {
log.Info().Msg("Redirect logging output to phuslu/log")
gin.DefaultErrorWriter = log.DefaultLogger.Std(log.ErrorLevel, log.Context{}, "GIN", 0).Writer()
gin.DefaultWriter = log.DefaultLogger.Std(log.DebugLevel, log.Context{}, "GIN", 0).Writer()
log.Info().Msg("Creating HTTP-Server")
var server = &Server{
conf: &Config{
Addr: "127.0.0.1:8080",
},
router: gin.New(),
authhf: &auth.AnonAccountHandler{},
}
server.Use(func(c *gin.Context) {
2021-01-09 20:39:05 +00:00
c.Set("account", server.authhf.Account(c))
})
if err := config.Unmarshal(server.conf); err != nil {
log.Error().Msg("Problem mapping config to Configstruct")
}
log.Debug().EmbedObject(server.conf).Msg("Config")
server.http = &http.Server{
Addr: server.conf.Addr,
ErrorLog: log.DefaultLogger.Std(log.ErrorLevel, log.Context{}, "", 0),
Handler: server.router,
TLSConfig: server.conf.TLSconfig,
}
server.router.NoRoute(gin.WrapH(http.NotFoundHandler()))
gin.DebugPrintRouteFunc = func(httpMethod, absolutePath, handlerName string, nuHandlers int) {
log.Trace().Msgf("%-4s(%02d): %-20s %s", httpMethod, nuHandlers-1, absolutePath, handlerName)
}
return server
}
// Use installs the middleware into the router.
// The Middleware must be able to detect multiple calls byy itself. Deduplication is not performed.
func (s *Server) Use(m ...gin.HandlerFunc) {
s.router.Use(m...)
}
2021-01-09 20:39:05 +00:00
// 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
func (s *Server) Stop(ctx context.Context) {
2021-01-12 18:29:25 +00:00
log.Info().Err(s.http.Shutdown(ctx)).Msg("Server Shut down.")
for _, site := range s.sites {
site.Teardown()
}
}
2021-01-09 20:39:05 +00:00
// Site is an Interface to abstract the modularized group of pages.
// The Middleware must be able to detect multiple calls byy itself. Deduplication is not performed.
type Site interface {
Init(*gin.RouterGroup)
Teardown()
2021-01-09 20:39:05 +00:00
}
// RegisterSite adds an site to the engine as its own grouo
func (s *Server) RegisterSite(path string, site Site) {
site.Init(s.router.Group(path))
s.sites = append(s.sites, site)
2021-01-09 20:39:05 +00:00
return
}