package proxy import ( "context" "net/http" "sync" "forge.cadoles.com/Cadoles/emissary/internal/proxy" "github.com/getsentry/sentry-go" "github.com/pkg/errors" "gitlab.com/wpetit/goweb/logger" ) type ReverseProxy struct { addr string server *http.Server mutex sync.RWMutex } func (p *ReverseProxy) Start(ctx context.Context, addr string, funcs ...proxy.OptionFunc) error { if p.server != nil { if err := p.Stop(); err != nil { return errors.WithStack(err) } } server := &http.Server{ Addr: addr, } proxy := proxy.New(funcs...) server.Handler = proxy p.mutex.Lock() p.server = server p.addr = addr p.mutex.Unlock() go func() { defer func() { if err := p.Stop(); err != nil { err = errors.WithStack(err) logger.Error(ctx, "error while stopping gateway", logger.E(err)) sentry.CaptureException(err) } }() if err := server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { err = errors.WithStack(err) logger.Error(ctx, "error while listening", logger.E(err)) sentry.CaptureException(err) } }() return nil } func (p *ReverseProxy) Running() bool { p.mutex.RLock() defer p.mutex.RUnlock() return p.server != nil } func (p *ReverseProxy) Stop() error { p.mutex.Lock() defer p.mutex.Unlock() if p.server == nil { return nil } if err := p.server.Close(); err != nil && !errors.Is(err, http.ErrServerClosed) { return errors.WithStack(err) } p.server = nil return nil } func NewReverseProxy() *ReverseProxy { return &ReverseProxy{} }