package gateway import ( "context" "net/http" "net/http/httputil" "net/url" "github.com/pkg/errors" "gitlab.com/wpetit/goweb/logger" ) type ReverseProxy struct { addr string target string server *http.Server } func (p *ReverseProxy) Start(ctx context.Context, addr, target string) error { alreadyRunning := p.server != nil && target == p.target && addr == p.target if alreadyRunning { return nil } if p.server != nil { if err := p.Stop(); err != nil { return errors.WithStack(err) } } server := &http.Server{ Addr: addr, } url, err := url.Parse(target) if err != nil { return errors.WithStack(err) } proxy := httputil.NewSingleHostReverseProxy(url) server.Handler = proxy p.server = server p.addr = addr p.target = target go func() { if err := server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) { logger.Error(ctx, "error while listening", logger.E(errors.WithStack(err))) } if err := p.Stop(); err != nil { logger.Error(ctx, "error while stopping gateway", logger.E(errors.WithStack(err))) } }() return nil } func (p *ReverseProxy) Stop() error { 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{} }