github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/pkg/baseurl/server.go (about)

     1  package baseurl
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"net/http"
     7  	"net/http/httputil"
     8  	"net/url"
     9  	"strings"
    10  	"time"
    11  
    12  	"github.com/pyroscope-io/pyroscope/pkg/config"
    13  	"github.com/sirupsen/logrus"
    14  )
    15  
    16  var upstream string
    17  var baseURL string
    18  var listenAddr string
    19  
    20  // newProxy takes target host and creates a reverse proxy
    21  func newProxy(targetHost string) (http.Handler, error) {
    22  	target, err := url.Parse(targetHost)
    23  	if err != nil {
    24  		return nil, err
    25  	}
    26  
    27  	p := httputil.NewSingleHostReverseProxy(target)
    28  	p.Director = func(r *http.Request) {
    29  		logrus.Info("before: ", r.URL.String())
    30  		r.URL.Scheme = target.Scheme
    31  		r.URL.Host = target.Host
    32  		logrus.Info("target.Host", target.Host)
    33  		r.URL.Path = strings.ReplaceAll(r.URL.Path, target.Path, "")
    34  		r.URL.RawPath = strings.ReplaceAll(r.URL.RawPath, target.Path, "")
    35  		logrus.Info("after: ", r.URL.String())
    36  	}
    37  
    38  	f := func(w http.ResponseWriter, r *http.Request) {
    39  		if !strings.HasPrefix(r.URL.Path, target.Path) {
    40  			w.WriteHeader(http.StatusNotFound)
    41  			w.Write([]byte(fmt.Sprintf("Please visit pyroscope at %s", target.Path)))
    42  			return
    43  		}
    44  		p.ServeHTTP(w, r)
    45  	}
    46  	return http.HandlerFunc(f), nil
    47  }
    48  
    49  func Start(cfg *config.Server) {
    50  	proxy, err := newProxy("http://localhost" + cfg.APIBindAddr + cfg.BaseURL)
    51  
    52  	if err != nil {
    53  		panic(err)
    54  	}
    55  
    56  	logger := logrus.New()
    57  	w := logger.Writer()
    58  	server := &http.Server{
    59  		Addr:           cfg.BaseURLBindAddr,
    60  		Handler:        proxy,
    61  		ReadTimeout:    10 * time.Second,
    62  		WriteTimeout:   15 * time.Second,
    63  		IdleTimeout:    30 * time.Second,
    64  		MaxHeaderBytes: 1 << 20,
    65  
    66  		ErrorLog: log.New(w, "", 0),
    67  	}
    68  
    69  	server.ListenAndServe()
    70  }