Simplify configuration initialization

This commit is contained in:
Jan-Lukas Else 2020-08-04 19:42:09 +02:00
parent e3b346acf7
commit 31591d694c
7 changed files with 60 additions and 93 deletions

View File

@ -13,7 +13,7 @@ func cacheMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
requestUrl, _ := url.ParseRequestURI(r.RequestURI)
path := slashTrimmedPath(r)
if appConfig.cache.enable &&
if appConfig.Cache.Enable &&
// check bypass query
!(requestUrl != nil && requestUrl.Query().Get("cache") == "0") {
cacheTime, header, body := getCache(r.Context(), path)
@ -27,7 +27,7 @@ func cacheMiddleware(next http.Handler) http.Handler {
w.Header()[k] = v
}
now := time.Now()
setCacheHeaders(w, now.Format(time.RFC1123), time.Unix(now.Unix()+appConfig.cache.expiration, 0).Format(time.RFC1123))
setCacheHeaders(w, now.Format(time.RFC1123), time.Unix(now.Unix()+appConfig.Cache.Expiration, 0).Format(time.RFC1123))
w.Header().Set("GoBlog-Cache", "MISS")
w.WriteHeader(code)
_, _ = w.Write(recorder.Body.Bytes())
@ -38,7 +38,7 @@ func cacheMiddleware(next http.Handler) http.Handler {
return
}
cacheTimeString := time.Unix(cacheTime, 0).Format(time.RFC1123)
expiresTimeString := time.Unix(cacheTime+appConfig.cache.expiration, 0).Format(time.RFC1123)
expiresTimeString := time.Unix(cacheTime+appConfig.Cache.Expiration, 0).Format(time.RFC1123)
// check conditional request
ifModifiedSinceHeader := r.Header.Get("If-Modified-Since")
if ifModifiedSinceHeader != "" && ifModifiedSinceHeader == cacheTimeString {
@ -70,7 +70,7 @@ func setCacheHeaders(w http.ResponseWriter, cacheTimeString string, expiresTimeS
func getCache(context context.Context, path string) (creationTime int64, header map[string][]string, body []byte) {
var headerBytes []byte
allowedTime := time.Now().Unix() - appConfig.cache.expiration
allowedTime := time.Now().Unix() - appConfig.Cache.Expiration
row := appDb.QueryRowContext(context, "select COALESCE(time, 0), header, body from cache where path=? and time>=?", path, allowedTime)
_ = row.Scan(&creationTime, &headerBytes, &body)
header = make(map[string][]string)
@ -85,7 +85,7 @@ func saveCache(path string, now time.Time, header map[string][]string, body []by
if err != nil {
return
}
_, _ = tx.Exec("delete from cache where time<?;", now.Unix()-appConfig.cache.expiration)
_, _ = tx.Exec("delete from cache where time<?;", now.Unix()-appConfig.Cache.Expiration)
_, _ = tx.Exec("insert or replace into cache (path, time, header, body) values (?, ?, ?, ?);", path, now.Unix(), headerBytes, body)
_ = tx.Commit()
finishWritingToDb()

113
config.go
View File

@ -5,52 +5,46 @@ import (
)
type config struct {
server *configServer
db *configDb
cache *configCache
blog *configBlog
user *configUser
Server *configServer `mapstructure:"server"`
Db *configDb `mapstructure:"database"`
Cache *configCache `mapstructure:"cache"`
Blog *configBlog `mapstructure:"blog"`
User *configUser `mapstructure:"user"`
}
type configServer struct {
logging bool
port int
domain string
publicHttps bool
letsEncryptMail string
localHttps bool
Logging bool `mapstructure:"logging"`
Port int `mapstructure:"port"`
Domain string `mapstructure:"domain"`
PublicHttps bool `mapstructure:"publicHttps"`
LetsEncryptMail string `mapstructure:"letsEncryptMail"`
LocalHttps bool `mapstructure:"localHttps"`
}
type configDb struct {
file string
File string `mapstructure:"file"`
}
type configCache struct {
enable bool
expiration int64
Enable bool `mapstructure:"enable"`
Expiration int64 `mapstructure:"expiration"`
}
// exposed to templates via function "blog"
type configBlog struct {
// Language of the blog, e.g. "en" or "de"
Lang string
Lang string `mapstructure:"lang"`
// Title of the blog, e.g. "My blog"
Title string
Title string `mapstructure:"title"`
}
type configUser struct {
nick string
name string
password string
Nick string `mapstructure:"nick"`
Name string `mapstructure:"name"`
Password string `mapstructure:"password"`
}
var appConfig = &config{
server: &configServer{},
db: &configDb{},
cache: &configCache{},
blog: &configBlog{},
user: &configUser{},
}
var appConfig = &config{}
func initConfig() error {
viper.SetConfigName("config")
@ -59,52 +53,25 @@ func initConfig() error {
if err != nil {
return err
}
// Server
serverLogging := "server.logging"
viper.SetDefault(serverLogging, false)
appConfig.server.logging = viper.GetBool(serverLogging)
serverPort := "server.port"
viper.SetDefault(serverPort, 8080)
appConfig.server.port = viper.GetInt(serverPort)
serverDomain := "server.domain"
viper.SetDefault(serverDomain, "example.com")
appConfig.server.domain = viper.GetString(serverDomain)
serverPublicHttps := "server.publicHttps"
viper.SetDefault(serverPublicHttps, false)
appConfig.server.publicHttps = viper.GetBool(serverPublicHttps)
serverLetsEncryptMail := "server.letsEncryptMail"
viper.SetDefault(serverLetsEncryptMail, "mail@example.com")
appConfig.server.letsEncryptMail = viper.GetString(serverLetsEncryptMail)
serverLocalHttps := "server.localHttps"
viper.SetDefault(serverLocalHttps, false)
appConfig.server.localHttps = viper.GetBool(serverLocalHttps)
// Database
databaseFile := "database.file"
viper.SetDefault(databaseFile, "data/db.sqlite")
appConfig.db.file = viper.GetString(databaseFile)
// Caching
cacheEnable := "cache.enable"
viper.SetDefault(cacheEnable, true)
appConfig.cache.enable = viper.GetBool(cacheEnable)
cacheExpiration := "cache.expiration"
viper.SetDefault(cacheExpiration, 600)
appConfig.cache.expiration = viper.GetInt64(cacheExpiration)
// Blog meta
blogLang := "blog.lang"
viper.SetDefault(blogLang, "en")
appConfig.blog.Lang = viper.GetString(blogLang)
blogTitle := "blog.title"
viper.SetDefault(blogTitle, "My blog")
appConfig.blog.Title = viper.GetString(blogTitle)
// User
userNick := "user.nick"
viper.SetDefault(userNick, "admin")
appConfig.user.nick = viper.GetString(userNick)
userName := "user.name"
viper.SetDefault(userName, "Admin")
appConfig.user.name = viper.GetString(userName)
userPassword := "user.password"
viper.SetDefault(userPassword, "secret")
appConfig.user.password = viper.GetString(userPassword)
// Defaults
viper.SetDefault("server.logging", false)
viper.SetDefault("server.port", 8080)
viper.SetDefault("server.domain", "example.com")
viper.SetDefault("server.publicHttps", false)
viper.SetDefault("server.letsEncryptMail", "mail@example.com")
viper.SetDefault("server.localHttps", false)
viper.SetDefault("database.file", "data/db.sqlite")
viper.SetDefault("cache.enable", true)
viper.SetDefault("cache.expiration", 600)
viper.SetDefault("blog.lang", "en")
viper.SetDefault("blog.title", "My blog")
viper.SetDefault("user.nick", "admin")
viper.SetDefault("user.name", "Admin")
viper.SetDefault("user.password", "secret")
// Unmarshal config
err = viper.Unmarshal(appConfig)
if err != nil {
return err
}
return nil
}

View File

@ -10,7 +10,7 @@ var appDb *sql.DB
var appDbWriteMutex = &sync.Mutex{}
func initDatabase() (err error) {
appDb, err = sql.Open("sqlite3", appConfig.db.file+"?cache=shared&mode=rwc&_journal_mode=WAL")
appDb, err = sql.Open("sqlite3", appConfig.Db.File+"?cache=shared&mode=rwc&_journal_mode=WAL")
if err != nil {
return err
}

4
go.mod
View File

@ -20,7 +20,7 @@ require (
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/pelletier/go-toml v1.8.0 // indirect
github.com/smartystreets/assertions v1.1.1 // indirect
github.com/spf13/afero v1.3.2 // indirect
github.com/spf13/afero v1.3.3 // indirect
github.com/spf13/cast v1.3.1 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/viper v1.7.1
@ -30,7 +30,7 @@ require (
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de // indirect
golang.org/x/net v0.0.0-20200707034311-ab3426394381 // indirect
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 // indirect
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1 // indirect
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642 // indirect
golang.org/x/text v0.3.3 // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/ini.v1 v1.57.0 // indirect

8
go.sum
View File

@ -357,8 +357,8 @@ github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4k
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.3.2 h1:GDarE4TJQI52kYSbSAmLiId1Elfj+xgSDqrUZxFhxlU=
github.com/spf13/afero v1.3.2/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
github.com/spf13/afero v1.3.3 h1:p5gZEKLYoL7wh8VrJesMaYeNxdEd1v3cb4irOk9zB54=
github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
@ -540,8 +540,8 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1 h1:sIky/MyNRSHTrdxfsiUSS4WIAMvInbeXljJz+jDjeYE=
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642 h1:B6caxRw+hozq68X2MY7jEpZh/cr4/aHLv9xU8Kkadrw=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=

14
http.go
View File

@ -21,11 +21,11 @@ func startServer() (err error) {
return
}
d.swapHandler(h)
localAddress := ":" + strconv.Itoa(appConfig.server.port)
if appConfig.server.publicHttps {
localAddress := ":" + strconv.Itoa(appConfig.Server.Port)
if appConfig.Server.PublicHttps {
initPublicHTTPS()
err = certmagic.HTTPS([]string{appConfig.server.domain}, d)
} else if appConfig.server.localHttps {
err = certmagic.HTTPS([]string{appConfig.Server.Domain}, d)
} else if appConfig.Server.LocalHttps {
err = http.ListenAndServeTLS(localAddress, "https/server.crt", "https/server.key", d)
} else {
err = http.ListenAndServe(localAddress, d)
@ -36,7 +36,7 @@ func startServer() (err error) {
func initPublicHTTPS() {
certmagic.Default.Storage = &certmagic.FileStorage{Path: "certmagic"}
certmagic.DefaultACME.Agreed = true
certmagic.DefaultACME.Email = appConfig.server.letsEncryptMail
certmagic.DefaultACME.Email = appConfig.Server.LetsEncryptMail
certmagic.DefaultACME.CA = certmagic.LetsEncryptProductionCA
}
@ -52,7 +52,7 @@ func reloadRouter() error {
func buildHandler() (http.Handler, error) {
r := chi.NewRouter()
if appConfig.server.logging {
if appConfig.Server.Logging {
r.Use(middleware.RealIP)
r.Use(middleware.Logger)
}
@ -62,7 +62,7 @@ func buildHandler() (http.Handler, error) {
r.Route("/api", func(apiRouter chi.Router) {
apiRouter.Use(middleware.BasicAuth("API", map[string]string{
appConfig.user.nick: appConfig.user.password,
appConfig.User.Nick: appConfig.User.Password,
}))
apiRouter.Post("/post", apiPostCreate)
apiRouter.Delete("/post", apiPostDelete)

View File

@ -18,7 +18,7 @@ var templateFunctions template.FuncMap
func initRendering() {
templateFunctions = template.FuncMap{
"blog": func() *configBlog {
return appConfig.blog
return appConfig.Blog
},
"md": func(content string) template.HTML {
htmlContent, err := renderMarkdown(content)