feat(server): Handle creation of a webserver
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Matthieu 'JP' DERASSE 2023-01-09 19:44:29 +00:00
parent adc5055da4
commit 44ff19e779
Signed by: mderasse
GPG Key ID: 55141C777B16A705
5 changed files with 95 additions and 2 deletions

2
commonctx/README.md Normal file
View File

@ -0,0 +1,2 @@
# Common Context
Contain code that will make work with context easier

17
commonctx/logger.go Normal file
View File

@ -0,0 +1,17 @@
package commonctx
import (
"context"
"github.com/sirupsen/logrus"
)
const LoggerKey = "mainLogger"
func AddMainLogger(ctx context.Context, logger *logrus.Logger) context.Context {
return context.WithValue(ctx, LoggerKey, logger)
}
func GetLogger(ctx context.Context) *logrus.Logger {
return ctx.Value(LoggerKey).(*logrus.Logger)
}

2
middleware/README.md Normal file
View File

@ -0,0 +1,2 @@
# Middleware Common
Contain http middlewares that are helpful in the creation of a new webserver

View File

@ -25,11 +25,11 @@ func GetListenAddressFromEnvOrFlags() (string, error) {
pHost := flag.String("host", host, "Host address to listen to")
pPort := flag.String("port", port, "Port to listen to")
if govalidator.IsHost(*pHost) {
if !govalidator.IsHost(*pHost) {
return "", fmt.Errorf("provided 'host' is invalid")
}
if govalidator.IsPort(*pPort) {
if !govalidator.IsPort(*pPort) {
return "", fmt.Errorf("provided 'port' is invalid")
}

72
webserver/webserver.go Normal file
View File

@ -0,0 +1,72 @@
package webserver
import (
"context"
"errors"
"fmt"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"git.dev.m-and-m.ovh/mderasse/gocommon/commonctx"
)
const defaultTimeout = 90 * time.Second
const defaultShutdownTimeout = 10 * time.Second
type cleanupFunc func() error
type ExecuteServerParams struct {
Cleanup cleanupFunc
ShutdownTimeout *time.Duration
}
func ExecuteServer(ctx context.Context, srv *http.Server, params *ExecuteServerParams) error {
log := commonctx.GetLogger(ctx)
if srv == nil {
return fmt.Errorf("missing http.server params")
}
if srv.ReadTimeout == 0 {
srv.ReadTimeout = defaultTimeout
}
if srv.WriteTimeout == 0 {
srv.WriteTimeout = defaultTimeout
}
log.Infof("launching webserver on %s", srv.Addr)
go func() {
if err := srv.ListenAndServe(); !errors.Is(err, http.ErrServerClosed) {
log.WithError(err).Fatalf("HTTP server error: %v", err)
}
log.Info("Stopped serving new connections.")
}()
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
<-sigChan
shutdownCtx, shutdownRelease := context.WithTimeout(ctx, defaultShutdownTimeout)
defer shutdownRelease()
if err := srv.Shutdown(shutdownCtx); err != nil {
log.WithError(err).Warnf("HTTP shutdown error: %v", err)
}
if params.Cleanup != nil {
if err := params.Cleanup(); err != nil {
log.WithError(err).Warnf("Impossible to cleanup correctly after shutdown. error : %v", err)
return nil
}
}
log.Info("Graceful shutdown complete.")
return nil
}