116 lines
2.1 KiB
Go
116 lines
2.1 KiB
Go
package httpserver
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"html/template"
|
|
"io"
|
|
"log"
|
|
"mime"
|
|
"net/http"
|
|
"time"
|
|
|
|
"go.uber.org/zap"
|
|
|
|
"go.c3c.cz/cv/app/server/internal/files"
|
|
)
|
|
|
|
func init() {
|
|
err := mime.AddExtensionType(".ico", "image/x-icon")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
err = mime.AddExtensionType(".json", "application/json; charset=utf-8")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
type Options struct {
|
|
Logger *zap.Logger
|
|
BindAddr string
|
|
FrontendConfig string
|
|
RequireIndex bool
|
|
}
|
|
|
|
type server struct{ http.Server }
|
|
|
|
func New(options *Options) (*server, error) {
|
|
handler := &handler{
|
|
frontendConfig: options.FrontendConfig,
|
|
logger: options.Logger,
|
|
}
|
|
|
|
httpSrv := &server{
|
|
http.Server{
|
|
Addr: options.BindAddr,
|
|
Handler: handler,
|
|
},
|
|
}
|
|
|
|
index, err := files.Public.Open("data/public/index.html")
|
|
if err != nil {
|
|
if !options.RequireIndex {
|
|
return httpSrv, nil
|
|
}
|
|
|
|
return nil, fmt.Errorf("could not open index.html: %w", err)
|
|
}
|
|
|
|
fi, err := index.Stat()
|
|
if err != nil || fi.IsDir() {
|
|
if !options.RequireIndex {
|
|
return httpSrv, nil
|
|
}
|
|
|
|
return nil, fmt.Errorf("invalid index.html: %w", err)
|
|
}
|
|
|
|
tb, err := io.ReadAll(index)
|
|
if err != nil {
|
|
if !options.RequireIndex {
|
|
return httpSrv, nil
|
|
}
|
|
|
|
return nil, fmt.Errorf("could not read index.html: %w", err)
|
|
}
|
|
|
|
handler.indexTemplate, err = template.New("index").Parse(string(tb))
|
|
if err != nil {
|
|
if !options.RequireIndex {
|
|
return httpSrv, nil
|
|
}
|
|
|
|
return nil, fmt.Errorf("could not parse index.html: index.html: %w", err)
|
|
}
|
|
|
|
return httpSrv, nil
|
|
}
|
|
|
|
func (s *server) ShutdownWithDelay(delay time.Duration, limit time.Duration) {
|
|
h, ok := s.Handler.(*handler)
|
|
|
|
var logger *zap.Logger
|
|
if ok {
|
|
logger = h.logger
|
|
} else {
|
|
logger = zap.L()
|
|
}
|
|
|
|
if delay > 0 {
|
|
logger.Info(fmt.Sprintf("Waiting %s for incoming requests\n", delay))
|
|
time.Sleep(delay)
|
|
}
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), limit)
|
|
defer cancel()
|
|
|
|
logger.Info("Gracefully shutting down http server")
|
|
if err := s.Shutdown(ctx); err != nil {
|
|
logger.Error("Failed to shutdown http server", zap.Error(err))
|
|
} else {
|
|
logger.Info("Http server was stopped")
|
|
}
|
|
}
|