Redmage/server/server.go

81 lines
1.8 KiB
Go

package server
import (
"context"
"errors"
"io/fs"
"net"
"net/http"
"github.com/go-chi/chi/v5"
"github.com/tigorlazuardi/redmage/api"
"github.com/tigorlazuardi/redmage/config"
"github.com/tigorlazuardi/redmage/pkg/caller"
"github.com/tigorlazuardi/redmage/pkg/errs"
"github.com/tigorlazuardi/redmage/pkg/log"
"github.com/tigorlazuardi/redmage/server/routes"
)
type Server struct {
server *http.Server
config *config.Config
PublicDir fs.FS
}
func (srv *Server) Start(exit <-chan struct{}) error {
errch := make(chan error, 1)
caller := caller.New(3)
go func() {
log.New(context.Background()).Caller(caller).Info(
"starting http server", "address", "http://"+srv.server.Addr,
"outbound_ip", "http://"+GetOutboundIP().String()+":"+srv.config.String("http.port"),
)
errch <- srv.server.ListenAndServe()
}()
select {
case <-exit:
log.New(context.Background()).Caller(caller).Info("received exit signal. shutting down server")
ctx, cancel := context.WithTimeout(context.Background(), srv.config.Duration("http.shutdown_timeout"))
defer cancel()
return srv.server.Shutdown(ctx)
case err := <-errch:
if errors.Is(err, http.ErrServerClosed) {
return nil
}
return errs.Wrap(err)
}
}
func New(cfg *config.Config, api *api.API, publicDir fs.FS) *Server {
router := chi.NewRouter()
routes := routes.Routes{
API: api,
Config: cfg,
PublicDir: publicDir,
}
routes.Register(router)
server := &http.Server{
Handler: router,
Addr: cfg.String("http.host") + ":" + cfg.String("http.port"),
}
return &Server{server: server, config: cfg}
}
// Get preferred outbound ip of this machine
func GetOutboundIP() net.IP {
conn, err := net.Dial("udp", "8.8.8.8:80")
if err != nil {
panic(err)
}
defer conn.Close()
localAddr := conn.LocalAddr().(*net.UDPAddr)
return localAddr.IP
}