WIP: sneak/next #21
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
/httpd
|
/httpd
|
||||||
debug.log
|
debug.log
|
||||||
/.env
|
/.env
|
||||||
|
/cmd/httpd/httpd
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"git.eeqj.de/sneak/gohttpserver/internal/config"
|
||||||
|
"git.eeqj.de/sneak/gohttpserver/internal/database"
|
||||||
|
"git.eeqj.de/sneak/gohttpserver/internal/globals"
|
||||||
|
"git.eeqj.de/sneak/gohttpserver/internal/handlers"
|
||||||
|
"git.eeqj.de/sneak/gohttpserver/internal/logger"
|
||||||
"git.eeqj.de/sneak/gohttpserver/internal/server"
|
"git.eeqj.de/sneak/gohttpserver/internal/server"
|
||||||
|
"go.uber.org/fx"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -13,5 +17,20 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
os.Exit(server.Run(Appname, Version, Buildarch))
|
globals.Appname = Appname
|
||||||
|
globals.Version = Version
|
||||||
|
globals.Buildarch = Buildarch
|
||||||
|
|
||||||
|
fx.New(
|
||||||
|
fx.Provide(
|
||||||
|
config.New,
|
||||||
|
database.New,
|
||||||
|
globals.New,
|
||||||
|
handlers.New,
|
||||||
|
logger.New,
|
||||||
|
server.New,
|
||||||
|
),
|
||||||
|
fx.Invoke(func(*server.Server) {}),
|
||||||
|
).Run()
|
||||||
|
// os.Exit(server.Run(Appname, Version, Buildarch))
|
||||||
}
|
}
|
||||||
|
5
go.mod
5
go.mod
@ -35,6 +35,11 @@ require (
|
|||||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/subosito/gotenv v1.4.1 // indirect
|
github.com/subosito/gotenv v1.4.1 // indirect
|
||||||
|
go.uber.org/atomic v1.9.0 // indirect
|
||||||
|
go.uber.org/dig v1.15.0 // indirect
|
||||||
|
go.uber.org/fx v1.18.2 // indirect
|
||||||
|
go.uber.org/multierr v1.8.0 // indirect
|
||||||
|
go.uber.org/zap v1.21.0 // indirect
|
||||||
golang.org/x/sys v0.2.0 // indirect
|
golang.org/x/sys v0.2.0 // indirect
|
||||||
golang.org/x/text v0.4.0 // indirect
|
golang.org/x/text v0.4.0 // indirect
|
||||||
google.golang.org/protobuf v1.28.1 // indirect
|
google.golang.org/protobuf v1.28.1 // indirect
|
||||||
|
23
go.sum
23
go.sum
@ -45,6 +45,7 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuy
|
|||||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||||
|
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
@ -279,12 +280,26 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
|||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||||
|
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||||
|
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
|
||||||
|
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||||
|
go.uber.org/dig v1.15.0 h1:vq3YWr8zRj1eFGC7Gvf907hE0eRjPTZ1d3xHadD6liE=
|
||||||
|
go.uber.org/dig v1.15.0/go.mod h1:pKHs0wMynzL6brANhB2hLMro+zalv1osARTviTcqHLM=
|
||||||
|
go.uber.org/fx v1.18.2 h1:bUNI6oShr+OVFQeU8cDNbnN7VFsu+SsjHzUF51V/GAU=
|
||||||
|
go.uber.org/fx v1.18.2/go.mod h1:g0V1KMQ66zIRk8bLu3Ea5Jt2w/cHlOIp4wdRsgh0JaY=
|
||||||
|
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||||
|
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||||
|
go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8=
|
||||||
|
go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
|
||||||
|
go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8=
|
||||||
|
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
|
||||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
@ -326,6 +341,7 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
@ -359,6 +375,7 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY
|
|||||||
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
@ -384,6 +401,7 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@ -423,8 +441,10 @@ golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
@ -497,6 +517,7 @@ golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4f
|
|||||||
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||||
|
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
@ -605,10 +626,12 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
83
internal/config/config.go
Normal file
83
internal/config/config.go
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"git.eeqj.de/sneak/gohttpserver/internal/globals"
|
||||||
|
"git.eeqj.de/sneak/gohttpserver/internal/logger"
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
"go.uber.org/fx"
|
||||||
|
|
||||||
|
// spooky action at a distance!
|
||||||
|
// this populates the environment
|
||||||
|
// from a ./.env file automatically
|
||||||
|
// for development configuration.
|
||||||
|
// .env contents should be things like
|
||||||
|
// `DBURL=postgres://user:pass@.../`
|
||||||
|
// (without the backticks, of course)
|
||||||
|
_ "github.com/joho/godotenv/autoload"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ConfigParams struct {
|
||||||
|
Globals globals.Globals
|
||||||
|
Logger logger.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
DBURL string
|
||||||
|
Debug bool
|
||||||
|
MaintenanceMode bool
|
||||||
|
MetricsPassword string
|
||||||
|
MetricsUsername string
|
||||||
|
Port int
|
||||||
|
SentryDSN string
|
||||||
|
params ConfigParams
|
||||||
|
log *zerolog.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(lc fx.Lifecycle, params ConfigParams) (*Config, error) {
|
||||||
|
log := params.Logger.Get()
|
||||||
|
name := params.Globals.Appname
|
||||||
|
|
||||||
|
viper.SetConfigName(name)
|
||||||
|
viper.SetConfigType("yaml")
|
||||||
|
// path to look for the config file in:
|
||||||
|
viper.AddConfigPath(fmt.Sprintf("/etc/%s", name))
|
||||||
|
// call multiple times to add many search paths:
|
||||||
|
viper.AddConfigPath(fmt.Sprintf("$HOME/.config/%s", name))
|
||||||
|
// viper.SetEnvPrefix(strings.ToUpper(s.appname))
|
||||||
|
viper.AutomaticEnv()
|
||||||
|
|
||||||
|
viper.SetDefault("DEBUG", "false")
|
||||||
|
viper.SetDefault("MAINTENANCE_MODE", "false")
|
||||||
|
viper.SetDefault("PORT", "8080")
|
||||||
|
viper.SetDefault("DBURL", "")
|
||||||
|
viper.SetDefault("SENTRY_DSN", "")
|
||||||
|
viper.SetDefault("METRICS_USERNAME", "")
|
||||||
|
viper.SetDefault("METRICS_PASSWORD", "")
|
||||||
|
|
||||||
|
if err := viper.ReadInConfig(); err != nil {
|
||||||
|
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
|
||||||
|
// Config file not found; ignore error if desired
|
||||||
|
} else {
|
||||||
|
// Config file was found but another error was produced
|
||||||
|
log.Panic().
|
||||||
|
Err(err).
|
||||||
|
Msg("config file malformed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s := &Config{
|
||||||
|
DBURL: viper.GetString("DBURL"),
|
||||||
|
Debug: viper.GetBool("debug"),
|
||||||
|
Port: viper.GetInt("PORT"),
|
||||||
|
SentryDSN: viper.GetString("SENTRY_DSN"),
|
||||||
|
MaintenanceMode: viper.GetBool("MAINTENANCE_MODE"),
|
||||||
|
MetricsUsername: viper.GetString("METRICS_USERNAME"),
|
||||||
|
MetricsPassword: viper.GetString("METRICS_PASSWORD"),
|
||||||
|
log: log,
|
||||||
|
}
|
||||||
|
|
||||||
|
return s, nil
|
||||||
|
}
|
49
internal/database/database.go
Normal file
49
internal/database/database.go
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package database
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"git.eeqj.de/sneak/gohttpserver/internal/config"
|
||||||
|
"git.eeqj.de/sneak/gohttpserver/internal/logger"
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
"go.uber.org/fx"
|
||||||
|
|
||||||
|
// spooky action at a distance!
|
||||||
|
// this populates the environment
|
||||||
|
// from a ./.env file automatically
|
||||||
|
// for development configuration.
|
||||||
|
// .env contents should be things like
|
||||||
|
// `DBURL=postgres://user:pass@.../`
|
||||||
|
// (without the backticks, of course)
|
||||||
|
_ "github.com/joho/godotenv/autoload"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DatabaseParams struct {
|
||||||
|
fx.In
|
||||||
|
Logger logger.Logger
|
||||||
|
Config config.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
type Database struct {
|
||||||
|
URL string
|
||||||
|
log *zerolog.Logger
|
||||||
|
params DatabaseParams
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(lc fx.Lifecycle, params DatabaseParams) (*Database, error) {
|
||||||
|
s.log.Info().Msg("Database instantiated")
|
||||||
|
s := new(Database)
|
||||||
|
s.params = params
|
||||||
|
s.log = params.Logger.Get()
|
||||||
|
|
||||||
|
lc.Append(fx.Hook{
|
||||||
|
OnStart: func(ctx context.Context) error {
|
||||||
|
s.log.Info().Msg("Database OnStart Hook")
|
||||||
|
// FIXME connect to db
|
||||||
|
},
|
||||||
|
OnStop: func(ctx context.Context) error {
|
||||||
|
// FIXME disconnect from db
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return s, nil
|
||||||
|
}
|
27
internal/globals/globals.go
Normal file
27
internal/globals/globals.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package globals
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go.uber.org/fx"
|
||||||
|
)
|
||||||
|
|
||||||
|
// these get populated from main() and copied into the Globals object.
|
||||||
|
var (
|
||||||
|
Appname string
|
||||||
|
Version string
|
||||||
|
Buildarch string
|
||||||
|
)
|
||||||
|
|
||||||
|
type Globals struct {
|
||||||
|
Appname string
|
||||||
|
Version string
|
||||||
|
Buildarch string
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(lc fx.Lifecycle) (*Globals, error) {
|
||||||
|
n := &Globals{
|
||||||
|
Appname: Appname,
|
||||||
|
Buildarch: Buildarch,
|
||||||
|
Version: Version,
|
||||||
|
}
|
||||||
|
return n, nil
|
||||||
|
}
|
@ -1,11 +1,11 @@
|
|||||||
package server
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *server) handleHealthCheck() http.HandlerFunc {
|
func (s *Handlers) handleHealthCheck() http.HandlerFunc {
|
||||||
type response struct {
|
type response struct {
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
Now string `json:"now"`
|
Now string `json:"now"`
|
@ -1,20 +1,19 @@
|
|||||||
package server
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"html/template"
|
"html/template"
|
||||||
"log"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"git.eeqj.de/sneak/gohttpserver/templates"
|
"git.eeqj.de/sneak/gohttpserver/templates"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *server) handleIndex() http.HandlerFunc {
|
func (s *Handlers) HandleIndex() http.HandlerFunc {
|
||||||
indexTemplate := template.Must(template.New("index").Parse(templates.MustString("index.html")))
|
indexTemplate := template.Must(template.New("index").Parse(templates.MustString("index.html")))
|
||||||
|
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
err := indexTemplate.ExecuteTemplate(w, "index", nil)
|
err := indexTemplate.ExecuteTemplate(w, "index", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err.Error())
|
s.log.Println(err.Error())
|
||||||
http.Error(w, http.StatusText(500), 500)
|
http.Error(w, http.StatusText(500), 500)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,11 +1,11 @@
|
|||||||
package server
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *server) handleLogin() http.HandlerFunc {
|
func (s *Handlers) HandleLogin() http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
fmt.Fprintf(w, "hello login")
|
fmt.Fprintf(w, "hello login")
|
||||||
}
|
}
|
@ -1,11 +1,11 @@
|
|||||||
package server
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *server) handleNow() http.HandlerFunc {
|
func (s *Handlers) HandleNow() http.HandlerFunc {
|
||||||
type response struct {
|
type response struct {
|
||||||
Now time.Time `json:"now"`
|
Now time.Time `json:"now"`
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package server
|
package handlers
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -7,7 +7,7 @@ import (
|
|||||||
// CHANGEME you probably want to remove this,
|
// CHANGEME you probably want to remove this,
|
||||||
// this is just a handler/route that throws a panic to test
|
// this is just a handler/route that throws a panic to test
|
||||||
// sentry events.
|
// sentry events.
|
||||||
func (s *server) handlePanic() http.HandlerFunc {
|
func (s *Handlers) HandlePanic() http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
panic("y tho")
|
panic("y tho")
|
||||||
}
|
}
|
61
internal/handlers/handlers.go
Normal file
61
internal/handlers/handlers.go
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.eeqj.de/sneak/gohttpserver/internal/globals"
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
"go.uber.org/fx"
|
||||||
|
"google.golang.org/genproto/googleapis/spanner/admin/database/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
type HandlersParams struct {
|
||||||
|
fx.In
|
||||||
|
Logger *zerolog.Logger
|
||||||
|
Globals globals.Globals
|
||||||
|
Database database.Database
|
||||||
|
}
|
||||||
|
|
||||||
|
type Handlers struct {
|
||||||
|
params HandlersParams
|
||||||
|
log *zerolog.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(lc fx.Lifecycle, params HandlersParams) (*Handlers, error) {
|
||||||
|
s := new(Handlers)
|
||||||
|
s.params = params
|
||||||
|
s.log = params.Logger.Get()
|
||||||
|
lc.Append(fx.Hook{
|
||||||
|
OnStart: func(ctx context.Context) error {
|
||||||
|
// FIXME compile some templates here or something
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Handlers) HandleNow() http.HandlerFunc {
|
||||||
|
type response struct {
|
||||||
|
Now time.Time `json:"now"`
|
||||||
|
}
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
s.respondJSON(w, r, &response{Now: time.Now()}, 200)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Handlers) respondJSON(w http.ResponseWriter, r *http.Request, data interface{}, status int) {
|
||||||
|
w.WriteHeader(status)
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
if data != nil {
|
||||||
|
err := json.NewEncoder(w).Encode(data)
|
||||||
|
if err != nil {
|
||||||
|
s.log.Error().Err(err).Msg("json encode error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Handlers) decodeJSON(w http.ResponseWriter, r *http.Request, v interface{}) error { // nolint
|
||||||
|
return json.NewDecoder(r.Body).Decode(v)
|
||||||
|
}
|
99
internal/logger/logger.go
Normal file
99
internal/logger/logger.go
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.eeqj.de/sneak/gohttpserver/internal/globals"
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
"go.uber.org/fx"
|
||||||
|
"honnef.co/go/tools/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LoggerParams struct {
|
||||||
|
fx.In
|
||||||
|
Globals globals.Globals
|
||||||
|
Config config.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
type Logger struct {
|
||||||
|
log *zerolog.Logger
|
||||||
|
params LoggerParams
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(lc fx.Lifecycle, params LoggerParams) (*Logger, error) {
|
||||||
|
l := new(Logger)
|
||||||
|
|
||||||
|
// always log in UTC
|
||||||
|
zerolog.TimestampFunc = func() time.Time {
|
||||||
|
return time.Now().UTC()
|
||||||
|
}
|
||||||
|
zerolog.SetGlobalLevel(zerolog.InfoLevel)
|
||||||
|
|
||||||
|
tty := false
|
||||||
|
if fileInfo, _ := os.Stdout.Stat(); (fileInfo.Mode() & os.ModeCharDevice) != 0 {
|
||||||
|
tty = true
|
||||||
|
}
|
||||||
|
|
||||||
|
var writers []io.Writer
|
||||||
|
|
||||||
|
if tty {
|
||||||
|
// this does cool colorization for console/dev
|
||||||
|
consoleWriter := zerolog.NewConsoleWriter(
|
||||||
|
func(w *zerolog.ConsoleWriter) {
|
||||||
|
// Customize time format
|
||||||
|
w.TimeFormat = time.RFC3339Nano
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
writers = append(writers, consoleWriter)
|
||||||
|
} else {
|
||||||
|
// log json in prod for the machines
|
||||||
|
writers = append(writers, os.Stdout)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// this is how you log to a file, if you do that
|
||||||
|
// sort of thing still
|
||||||
|
logfile := viper.GetString("Logfile")
|
||||||
|
if logfile != "" {
|
||||||
|
logfileDir := filepath.Dir(logfile)
|
||||||
|
err := goutil.Mkdirp(logfileDir)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Msg("unable to create log dir")
|
||||||
|
}
|
||||||
|
|
||||||
|
hp.logfh, err = os.OpenFile(logfile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
|
||||||
|
if err != nil {
|
||||||
|
panic("unable to open logfile: " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
writers = append(writers, hp.logfh)
|
||||||
|
*/
|
||||||
|
|
||||||
|
multi := zerolog.MultiLevelWriter(writers...)
|
||||||
|
logger := zerolog.New(multi).With().Timestamp().Logger().With().Caller().Logger()
|
||||||
|
|
||||||
|
l.log = &logger
|
||||||
|
// log.Logger = logger
|
||||||
|
|
||||||
|
if l.params.Config.Debug {
|
||||||
|
zerolog.SetGlobalLevel(zerolog.DebugLevel)
|
||||||
|
l.log.Debug().Bool("debug", true).Send()
|
||||||
|
}
|
||||||
|
|
||||||
|
return l, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Logger) Get() *zerolog.Logger {
|
||||||
|
return l.log
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Logger) Identify() {
|
||||||
|
l.log.Info().
|
||||||
|
Str("appname", l.params.Globals.Appname).
|
||||||
|
Str("version", l.params.Globals.Version).
|
||||||
|
Str("buildarch", l.params.Globals.Buildarch).
|
||||||
|
Msg("starting")
|
||||||
|
}
|
@ -45,7 +45,7 @@ func (lrw *loggingResponseWriter) WriteHeader(code int) {
|
|||||||
// type Middleware func(http.Handler) http.Handler
|
// type Middleware func(http.Handler) http.Handler
|
||||||
// this returns a Middleware that is designed to do every request through the
|
// this returns a Middleware that is designed to do every request through the
|
||||||
// mux, note the signature:
|
// mux, note the signature:
|
||||||
func (s *server) LoggingMiddleware() func(http.Handler) http.Handler {
|
func (s *Server) LoggingMiddleware() func(http.Handler) http.Handler {
|
||||||
// FIXME this should use https://github.com/google/go-cloud/blob/master/server/requestlog/requestlog.go
|
// FIXME this should use https://github.com/google/go-cloud/blob/master/server/requestlog/requestlog.go
|
||||||
return func(next http.Handler) http.Handler {
|
return func(next http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -73,7 +73,7 @@ func (s *server) LoggingMiddleware() func(http.Handler) http.Handler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) CORSMiddleware() func(http.Handler) http.Handler {
|
func (s *Server) CORSMiddleware() func(http.Handler) http.Handler {
|
||||||
return cors.Handler(cors.Options{
|
return cors.Handler(cors.Options{
|
||||||
// CHANGEME! these are defaults, change them to suit your needs or
|
// CHANGEME! these are defaults, change them to suit your needs or
|
||||||
// read from environment/viper.
|
// read from environment/viper.
|
||||||
@ -88,7 +88,7 @@ func (s *server) CORSMiddleware() func(http.Handler) http.Handler {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) AuthMiddleware() func(http.Handler) http.Handler {
|
func (s *Server) AuthMiddleware() func(http.Handler) http.Handler {
|
||||||
return func(next http.Handler) http.Handler {
|
return func(next http.Handler) http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
// CHANGEME you'll want to change this to do stuff.
|
// CHANGEME you'll want to change this to do stuff.
|
||||||
@ -98,7 +98,7 @@ func (s *server) AuthMiddleware() func(http.Handler) http.Handler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) MetricsMiddleware() func(http.Handler) http.Handler {
|
func (s *Server) MetricsMiddleware() func(http.Handler) http.Handler {
|
||||||
mdlw := ghmm.New(ghmm.Config{
|
mdlw := ghmm.New(ghmm.Config{
|
||||||
Recorder: metrics.NewRecorder(metrics.Config{}),
|
Recorder: metrics.NewRecorder(metrics.Config{}),
|
||||||
})
|
})
|
||||||
@ -107,7 +107,7 @@ func (s *server) MetricsMiddleware() func(http.Handler) http.Handler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) MetricsAuthMiddleware() func(http.Handler) http.Handler {
|
func (s *Server) MetricsAuthMiddleware() func(http.Handler) http.Handler {
|
||||||
return basicauth.New(
|
return basicauth.New(
|
||||||
"metrics",
|
"metrics",
|
||||||
map[string][]string{
|
map[string][]string{
|
@ -1,13 +1,12 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *server) serveUntilShutdown() {
|
func (s *Server) serveUntilShutdown() {
|
||||||
listenAddr := fmt.Sprintf(":%d", s.port)
|
listenAddr := fmt.Sprintf(":%d", s.port)
|
||||||
s.httpServer = &http.Server{
|
s.httpServer = &http.Server{
|
||||||
Addr: listenAddr,
|
Addr: listenAddr,
|
||||||
@ -30,21 +29,6 @@ func (s *server) serveUntilShutdown() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) respondJSON(w http.ResponseWriter, r *http.Request, data interface{}, status int) {
|
func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
w.WriteHeader(status)
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
if data != nil {
|
|
||||||
err := json.NewEncoder(w).Encode(data)
|
|
||||||
if err != nil {
|
|
||||||
s.log.Error().Err(err).Msg("json encode error")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *server) decodeJSON(w http.ResponseWriter, r *http.Request, v interface{}) error { // nolint
|
|
||||||
return json.NewDecoder(r.Body).Decode(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
||||||
s.router.ServeHTTP(w, r)
|
s.router.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
|
@ -1,269 +0,0 @@
|
|||||||
package server
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
"syscall"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/rs/zerolog"
|
|
||||||
"github.com/rs/zerolog/log"
|
|
||||||
"github.com/spf13/viper"
|
|
||||||
|
|
||||||
"github.com/getsentry/sentry-go"
|
|
||||||
"github.com/go-chi/chi"
|
|
||||||
|
|
||||||
// spooky action at a distance!
|
|
||||||
// this populates the environment
|
|
||||||
// from a ./.env file automatically
|
|
||||||
// for development configuration.
|
|
||||||
// .env contents should be things like
|
|
||||||
// `DBURL=postgres://user:pass@.../`
|
|
||||||
// (without the backticks, of course)
|
|
||||||
_ "github.com/joho/godotenv/autoload"
|
|
||||||
)
|
|
||||||
|
|
||||||
type server struct {
|
|
||||||
appname string
|
|
||||||
version string
|
|
||||||
buildarch string
|
|
||||||
databaseURL string
|
|
||||||
startupTime time.Time
|
|
||||||
port int
|
|
||||||
exitCode int
|
|
||||||
sentryEnabled bool
|
|
||||||
log *zerolog.Logger
|
|
||||||
ctx context.Context
|
|
||||||
cancelFunc context.CancelFunc
|
|
||||||
httpServer *http.Server
|
|
||||||
router *chi.Mux
|
|
||||||
}
|
|
||||||
|
|
||||||
func newServer(options ...func(s *server)) *server {
|
|
||||||
n := new(server)
|
|
||||||
n.startupTime = time.Now()
|
|
||||||
n.version = "unknown"
|
|
||||||
for _, opt := range options {
|
|
||||||
opt(n)
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME change this to use uber/fx DI and an Invoke()
|
|
||||||
// this is where we come in from package main.
|
|
||||||
func Run(appname, version, buildarch string) int {
|
|
||||||
s := newServer(func(i *server) {
|
|
||||||
i.appname = appname
|
|
||||||
if version != "" {
|
|
||||||
i.version = version
|
|
||||||
}
|
|
||||||
i.buildarch = buildarch
|
|
||||||
})
|
|
||||||
|
|
||||||
// this does nothing if SENTRY_DSN is unset in env.
|
|
||||||
|
|
||||||
// TODO remove:
|
|
||||||
if s.sentryEnabled {
|
|
||||||
sentry.CaptureMessage("It works!")
|
|
||||||
}
|
|
||||||
|
|
||||||
s.configure()
|
|
||||||
s.setupLogging()
|
|
||||||
|
|
||||||
// logging before sentry, because sentry logs
|
|
||||||
s.enableSentry()
|
|
||||||
|
|
||||||
s.databaseURL = viper.GetString("DBURL")
|
|
||||||
s.port = viper.GetInt("PORT")
|
|
||||||
|
|
||||||
return s.serve()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *server) enableSentry() {
|
|
||||||
s.sentryEnabled = false
|
|
||||||
|
|
||||||
if viper.GetString("SENTRY_DSN") == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err := sentry.Init(sentry.ClientOptions{
|
|
||||||
Dsn: viper.GetString("SENTRY_DSN"),
|
|
||||||
Release: fmt.Sprintf("%s-%s", s.appname, s.version),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal().Err(err).Msg("sentry init failure")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
s.log.Info().Msg("sentry error reporting activated")
|
|
||||||
s.sentryEnabled = true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *server) serve() int {
|
|
||||||
s.ctx, s.cancelFunc = context.WithCancel(context.Background())
|
|
||||||
|
|
||||||
// signal watcher
|
|
||||||
go func() {
|
|
||||||
c := make(chan os.Signal, 1)
|
|
||||||
signal.Ignore(syscall.SIGPIPE)
|
|
||||||
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
|
||||||
// block and wait for signal
|
|
||||||
sig := <-c
|
|
||||||
s.log.Info().Msgf("signal received: %+v", sig)
|
|
||||||
if s.cancelFunc != nil {
|
|
||||||
// cancelling the main context will trigger a clean
|
|
||||||
// shutdown.
|
|
||||||
s.cancelFunc()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
go s.serveUntilShutdown()
|
|
||||||
|
|
||||||
for range s.ctx.Done() {
|
|
||||||
// aforementioned clean shutdown upon main context
|
|
||||||
// cancellation
|
|
||||||
}
|
|
||||||
s.cleanShutdown()
|
|
||||||
return s.exitCode
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *server) cleanupForExit() {
|
|
||||||
s.log.Info().Msg("cleaning up")
|
|
||||||
// FIXME unimplemented
|
|
||||||
// close database connections or whatever
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *server) cleanShutdown() {
|
|
||||||
// initiate clean shutdown
|
|
||||||
s.exitCode = 0
|
|
||||||
ctxShutdown, shutdownCancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
||||||
if err := s.httpServer.Shutdown(ctxShutdown); err != nil {
|
|
||||||
s.log.Error().
|
|
||||||
Err(err).
|
|
||||||
Msg("server clean shutdown failed")
|
|
||||||
}
|
|
||||||
if shutdownCancel != nil {
|
|
||||||
shutdownCancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
s.cleanupForExit()
|
|
||||||
|
|
||||||
if s.sentryEnabled {
|
|
||||||
sentry.Flush(2 * time.Second)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *server) uptime() time.Duration {
|
|
||||||
return time.Since(s.startupTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *server) maintenance() bool {
|
|
||||||
return viper.GetBool("MAINTENANCE_MODE")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *server) configure() {
|
|
||||||
viper.SetConfigName(s.appname)
|
|
||||||
viper.SetConfigType("yaml")
|
|
||||||
// path to look for the config file in:
|
|
||||||
viper.AddConfigPath(fmt.Sprintf("/etc/%s", s.appname))
|
|
||||||
// call multiple times to add many search paths:
|
|
||||||
viper.AddConfigPath(fmt.Sprintf("$HOME/.config/%s", s.appname))
|
|
||||||
// viper.SetEnvPrefix(strings.ToUpper(s.appname))
|
|
||||||
viper.AutomaticEnv()
|
|
||||||
|
|
||||||
viper.SetDefault("DEBUG", "false")
|
|
||||||
viper.SetDefault("MAINTENANCE_MODE", "false")
|
|
||||||
viper.SetDefault("PORT", "8080")
|
|
||||||
viper.SetDefault("DBURL", "")
|
|
||||||
viper.SetDefault("SENTRY_DSN", "")
|
|
||||||
viper.SetDefault("METRICS_USERNAME", "")
|
|
||||||
viper.SetDefault("METRICS_PASSWORD", "")
|
|
||||||
|
|
||||||
if err := viper.ReadInConfig(); err != nil {
|
|
||||||
if _, ok := err.(viper.ConfigFileNotFoundError); ok {
|
|
||||||
// Config file not found; ignore error if desired
|
|
||||||
} else {
|
|
||||||
// Config file was found but another error was produced
|
|
||||||
log.Panic().
|
|
||||||
Err(err).
|
|
||||||
Msg("config file malformed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if viper.GetBool("DEBUG") {
|
|
||||||
// pp.Print(viper.AllSettings())
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *server) setupLogging() {
|
|
||||||
// always log in UTC
|
|
||||||
zerolog.TimestampFunc = func() time.Time {
|
|
||||||
return time.Now().UTC()
|
|
||||||
}
|
|
||||||
zerolog.SetGlobalLevel(zerolog.InfoLevel)
|
|
||||||
|
|
||||||
tty := false
|
|
||||||
if fileInfo, _ := os.Stdout.Stat(); (fileInfo.Mode() & os.ModeCharDevice) != 0 {
|
|
||||||
tty = true
|
|
||||||
}
|
|
||||||
|
|
||||||
var writers []io.Writer
|
|
||||||
|
|
||||||
if tty {
|
|
||||||
// this does cool colorization for console/dev
|
|
||||||
consoleWriter := zerolog.NewConsoleWriter(
|
|
||||||
func(w *zerolog.ConsoleWriter) {
|
|
||||||
// Customize time format
|
|
||||||
w.TimeFormat = time.RFC3339Nano
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
writers = append(writers, consoleWriter)
|
|
||||||
} else {
|
|
||||||
// log json in prod for the machines
|
|
||||||
writers = append(writers, os.Stdout)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
// this is how you log to a file, if you do that
|
|
||||||
// sort of thing still
|
|
||||||
logfile := viper.GetString("Logfile")
|
|
||||||
if logfile != "" {
|
|
||||||
logfileDir := filepath.Dir(logfile)
|
|
||||||
err := goutil.Mkdirp(logfileDir)
|
|
||||||
if err != nil {
|
|
||||||
log.Error().Err(err).Msg("unable to create log dir")
|
|
||||||
}
|
|
||||||
|
|
||||||
hp.logfh, err = os.OpenFile(logfile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
|
|
||||||
if err != nil {
|
|
||||||
panic("unable to open logfile: " + err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
writers = append(writers, hp.logfh)
|
|
||||||
*/
|
|
||||||
|
|
||||||
multi := zerolog.MultiLevelWriter(writers...)
|
|
||||||
logger := zerolog.New(multi).With().Timestamp().Logger().With().Caller().Logger()
|
|
||||||
|
|
||||||
s.log = &logger
|
|
||||||
// log.Logger = logger
|
|
||||||
|
|
||||||
if viper.GetBool("debug") {
|
|
||||||
zerolog.SetGlobalLevel(zerolog.DebugLevel)
|
|
||||||
s.log.Debug().Bool("debug", true).Send()
|
|
||||||
}
|
|
||||||
|
|
||||||
s.identify()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *server) identify() {
|
|
||||||
s.log.Info().
|
|
||||||
Str("appname", s.appname).
|
|
||||||
Str("version", s.version).
|
|
||||||
Str("buildarch", s.buildarch).
|
|
||||||
Msg("starting")
|
|
||||||
}
|
|
@ -12,7 +12,7 @@ import (
|
|||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *server) routes() {
|
func (s *Server) SetupRoutes() {
|
||||||
s.router = chi.NewRouter()
|
s.router = chi.NewRouter()
|
||||||
|
|
||||||
// the mux .Use() takes a http.Handler wrapper func, like most
|
// the mux .Use() takes a http.Handler wrapper func, like most
|
||||||
|
178
internal/server/server.go
Normal file
178
internal/server/server.go
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
package server
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.eeqj.de/sneak/gohttpserver/internal/globals"
|
||||||
|
"github.com/docker/docker/daemon/logger"
|
||||||
|
"github.com/rs/zerolog"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
"go.uber.org/fx"
|
||||||
|
"honnef.co/go/tools/config"
|
||||||
|
|
||||||
|
"github.com/getsentry/sentry-go"
|
||||||
|
"github.com/go-chi/chi"
|
||||||
|
|
||||||
|
// spooky action at a distance!
|
||||||
|
// this populates the environment
|
||||||
|
// from a ./.env file automatically
|
||||||
|
// for development configuration.
|
||||||
|
// .env contents should be things like
|
||||||
|
// `DBURL=postgres://user:pass@.../`
|
||||||
|
// (without the backticks, of course)
|
||||||
|
_ "github.com/joho/godotenv/autoload"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ServerParams struct {
|
||||||
|
fx.In
|
||||||
|
Logger logger.Logger
|
||||||
|
Globals globals.Globals
|
||||||
|
Config config.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
type Server struct {
|
||||||
|
appname string
|
||||||
|
version string
|
||||||
|
buildarch string
|
||||||
|
startupTime time.Time
|
||||||
|
port int
|
||||||
|
exitCode int
|
||||||
|
sentryEnabled bool
|
||||||
|
log *zerolog.Logger
|
||||||
|
ctx context.Context
|
||||||
|
cancelFunc context.CancelFunc
|
||||||
|
httpServer *http.Server
|
||||||
|
router *chi.Mux
|
||||||
|
params ServerParams
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(lc fx.Lifecycle, params ServerParams) (*Server, error) {
|
||||||
|
s := new(Server)
|
||||||
|
s.params = params
|
||||||
|
s.log = params.Logger.Get()
|
||||||
|
|
||||||
|
lc.Append(fx.Hook{
|
||||||
|
OnStart: func(ctx context.Context) error {
|
||||||
|
s.startupTime = time.Now()
|
||||||
|
s.version = params.Globals.Version
|
||||||
|
s.Run()
|
||||||
|
},
|
||||||
|
OnStop: func(ctx context.Context) error {
|
||||||
|
// FIXME do server shutdown here
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME change this to use uber/fx DI and an Invoke()
|
||||||
|
// this is where we come in from package main.
|
||||||
|
func (s *Server) Run() {
|
||||||
|
// this does nothing if SENTRY_DSN is unset in env.
|
||||||
|
// TODO remove:
|
||||||
|
if s.sentryEnabled {
|
||||||
|
sentry.CaptureMessage("It works!")
|
||||||
|
}
|
||||||
|
|
||||||
|
s.configure()
|
||||||
|
|
||||||
|
// logging before sentry, because sentry logs
|
||||||
|
s.enableSentry()
|
||||||
|
|
||||||
|
return s.serve()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) enableSentry() {
|
||||||
|
s.sentryEnabled = false
|
||||||
|
|
||||||
|
if s.Config.SentryDSN == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err := sentry.Init(sentry.ClientOptions{
|
||||||
|
Dsn: viper.GetString("SENTRY_DSN"),
|
||||||
|
Release: fmt.Sprintf("%s-%s", s.params.Globals.Appname, s.params.Globals.Version),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal().Err(err).Msg("sentry init failure")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.log.Info().Msg("sentry error reporting activated")
|
||||||
|
s.sentryEnabled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) serve() int {
|
||||||
|
// FIXME fx will handle this for us
|
||||||
|
s.ctx, s.cancelFunc = context.WithCancel(context.Background())
|
||||||
|
|
||||||
|
// signal watcher
|
||||||
|
go func() {
|
||||||
|
c := make(chan os.Signal, 1)
|
||||||
|
signal.Ignore(syscall.SIGPIPE)
|
||||||
|
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
||||||
|
// block and wait for signal
|
||||||
|
sig := <-c
|
||||||
|
s.log.Info().Msgf("signal received: %+v", sig)
|
||||||
|
if s.cancelFunc != nil {
|
||||||
|
// cancelling the main context will trigger a clean
|
||||||
|
// shutdown.
|
||||||
|
s.cancelFunc()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
go s.serveUntilShutdown()
|
||||||
|
|
||||||
|
for range s.ctx.Done() {
|
||||||
|
// aforementioned clean shutdown upon main context
|
||||||
|
// cancellation
|
||||||
|
}
|
||||||
|
s.cleanShutdown()
|
||||||
|
return s.exitCode
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) cleanupForExit() {
|
||||||
|
s.log.Info().Msg("cleaning up")
|
||||||
|
// FIXME unimplemented
|
||||||
|
// close database connections or whatever
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) cleanShutdown() {
|
||||||
|
// initiate clean shutdown
|
||||||
|
s.exitCode = 0
|
||||||
|
ctxShutdown, shutdownCancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
|
if err := s.httpServer.Shutdown(ctxShutdown); err != nil {
|
||||||
|
s.log.Error().
|
||||||
|
Err(err).
|
||||||
|
Msg("server clean shutdown failed")
|
||||||
|
}
|
||||||
|
if shutdownCancel != nil {
|
||||||
|
shutdownCancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
s.cleanupForExit()
|
||||||
|
|
||||||
|
if s.sentryEnabled {
|
||||||
|
sentry.Flush(2 * time.Second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) uptime() time.Duration {
|
||||||
|
return time.Since(s.startupTime)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) maintenance() bool {
|
||||||
|
return s.params.Config.MaintenanceMode
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) configure() {
|
||||||
|
// FIXME move most of this to dedicated places
|
||||||
|
// if viper.GetBool("DEBUG") {
|
||||||
|
// pp.Print(viper.AllSettings())
|
||||||
|
// }
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user