2021-07-19 17:59:47 +02:00
|
|
|
/*
|
|
|
|
Package web implements common functionality for web APIs using Gin and Gorm.
|
|
|
|
|
|
|
|
Modules
|
|
|
|
|
|
|
|
Modules provide functionality for a web server. A module is a function executed
|
|
|
|
before starting a server, accessing the Service and the Gin Engine. Each Service
|
|
|
|
maintains a list of modules. When it runs, it executes all of its modules.
|
|
|
|
*/
|
2021-06-01 10:51:35 +02:00
|
|
|
package web
|
|
|
|
|
|
|
|
import (
|
2021-10-25 12:56:47 +02:00
|
|
|
"net/http"
|
|
|
|
|
2021-06-01 10:51:35 +02:00
|
|
|
"github.com/gin-gonic/gin"
|
2021-09-29 13:08:43 +02:00
|
|
|
"go.uber.org/zap"
|
2021-07-19 17:59:08 +02:00
|
|
|
|
2021-06-01 10:51:35 +02:00
|
|
|
// acme
|
|
|
|
"github.com/gin-gonic/autotls"
|
|
|
|
"golang.org/x/crypto/acme/autocert"
|
2021-07-19 17:59:08 +02:00
|
|
|
|
2021-06-21 16:30:34 +02:00
|
|
|
// internal
|
|
|
|
"dev.sum7.eu/genofire/golang-lib/mailer"
|
|
|
|
"gorm.io/gorm"
|
2021-06-01 10:51:35 +02:00
|
|
|
)
|
|
|
|
|
2021-07-19 17:59:47 +02:00
|
|
|
// A Service stores configuration of a server.
|
2021-06-01 10:51:35 +02:00
|
|
|
type Service struct {
|
|
|
|
// config
|
2022-08-14 16:50:52 +02:00
|
|
|
Listen string `config:"listen" toml:"listen"`
|
|
|
|
AccessLog bool `config:"access_log" toml:"access_log"`
|
|
|
|
WebrootIndexDisable bool `config:"webroot_index_disable" toml:"webroot_index_disable"`
|
|
|
|
Webroot string `config:"webroot" toml:"webroot"`
|
|
|
|
WebrootFS http.FileSystem `config:"-" toml:"-"`
|
2022-06-06 01:55:57 +02:00
|
|
|
ACME struct {
|
2022-08-14 16:50:52 +02:00
|
|
|
Enable bool `config:"enable" toml:"enable"`
|
|
|
|
Domains []string `config:"domains" toml:"domains"`
|
|
|
|
Cache string `config: "cache" toml:"cache"`
|
|
|
|
} `config:"acme" toml:"acme"`
|
2021-06-01 10:51:35 +02:00
|
|
|
Session struct {
|
2022-08-14 16:50:52 +02:00
|
|
|
Name string `config:"name" toml:"name"`
|
|
|
|
Secret string `config: "secret" toml:"secret"`
|
|
|
|
} `config:"session" toml:"session"`
|
2021-06-01 10:51:35 +02:00
|
|
|
// internal
|
2022-08-14 16:50:52 +02:00
|
|
|
DB *gorm.DB `config:"-" toml:"-"`
|
|
|
|
Mailer *mailer.Service `config:"-" toml:"-"`
|
2021-07-19 17:59:08 +02:00
|
|
|
|
2021-09-29 13:08:43 +02:00
|
|
|
log *zap.Logger
|
2021-07-19 17:59:08 +02:00
|
|
|
modules []ModuleRegisterFunc
|
2021-06-01 10:51:35 +02:00
|
|
|
}
|
|
|
|
|
2021-09-29 14:30:17 +02:00
|
|
|
// SetLog - set new logger
|
|
|
|
func (s *Service) SetLog(l *zap.Logger) {
|
|
|
|
s.log = l
|
|
|
|
}
|
|
|
|
|
2021-09-29 13:08:43 +02:00
|
|
|
// Log - get current logger
|
|
|
|
func (s *Service) Log() *zap.Logger {
|
|
|
|
return s.log
|
|
|
|
}
|
|
|
|
|
2021-07-19 17:59:47 +02:00
|
|
|
// Run creates, configures, and runs a new gin.Engine using its registered
|
|
|
|
// modules.
|
2021-09-29 13:08:43 +02:00
|
|
|
func (s *Service) Run(log *zap.Logger) error {
|
|
|
|
s.log = log
|
2021-06-01 10:51:35 +02:00
|
|
|
gin.EnableJsonDecoderDisallowUnknownFields()
|
|
|
|
gin.SetMode(gin.ReleaseMode)
|
|
|
|
r := gin.New()
|
|
|
|
// catch crashed
|
|
|
|
r.Use(gin.Recovery())
|
|
|
|
|
2021-07-19 17:59:47 +02:00
|
|
|
if s.AccessLog {
|
2021-06-01 10:51:35 +02:00
|
|
|
r.Use(gin.Logger())
|
2021-09-29 13:08:43 +02:00
|
|
|
s.log.Debug("request logging enabled")
|
2021-06-01 10:51:35 +02:00
|
|
|
}
|
2021-07-19 17:59:47 +02:00
|
|
|
s.LoadSession(r)
|
|
|
|
s.Bind(r)
|
2021-06-01 10:51:35 +02:00
|
|
|
|
2021-07-19 17:59:47 +02:00
|
|
|
if s.ACME.Enable {
|
|
|
|
if s.Listen != "" {
|
2021-09-29 13:08:43 +02:00
|
|
|
s.log.Panic("For ACME / Let's Encrypt it is not possible to set `listen`")
|
2021-06-01 10:51:35 +02:00
|
|
|
}
|
|
|
|
m := autocert.Manager{
|
|
|
|
Prompt: autocert.AcceptTOS,
|
2021-07-19 17:59:47 +02:00
|
|
|
HostPolicy: autocert.HostWhitelist(s.ACME.Domains...),
|
|
|
|
Cache: autocert.DirCache(s.ACME.Cache),
|
2021-06-01 10:51:35 +02:00
|
|
|
}
|
|
|
|
return autotls.RunWithManager(r, &m)
|
|
|
|
}
|
2021-07-19 17:59:47 +02:00
|
|
|
return r.Run(s.Listen)
|
2021-06-01 10:51:35 +02:00
|
|
|
}
|