64 lines
1.3 KiB
Go

package http
import (
"context"
"log/slog"
"net/http"
"github.com/pkg/errors"
sloghttp "github.com/samber/slog-http"
httpCtx "forge.cadoles.com/wpetit/clearcase/internal/http/context"
)
type Server struct {
handler http.Handler
opts *Options
}
func (s *Server) Run(ctx context.Context) error {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
handler := sloghttp.Recovery(s.handler)
handler = sloghttp.New(slog.Default())(handler)
handler = func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
ctx = httpCtx.SetBaseURL(ctx, s.opts.BaseURL)
ctx = httpCtx.SetCurrentURL(ctx, r.URL)
r = r.WithContext(ctx)
next.ServeHTTP(w, r)
})
}(handler)
server := http.Server{
Addr: s.opts.Address,
Handler: handler,
}
go func() {
<-ctx.Done()
if err := server.Close(); err != nil {
slog.ErrorContext(ctx, "could not close server", slog.Any("error", errors.WithStack(err)))
}
}()
if err := server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
return errors.WithStack(err)
}
return nil
}
func NewServer(handler http.Handler, funcs ...OptionFunc) *Server {
opts := NewOptions(funcs...)
return &Server{
handler: handler,
opts: opts,
}
}