118 lines
2.1 KiB
Go
118 lines
2.1 KiB
Go
package http
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"net"
|
|
"net/http"
|
|
httppprof "net/http/pprof"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/benbjohnson/litestream"
|
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
|
"golang.org/x/sync/errgroup"
|
|
)
|
|
|
|
// Server represents an HTTP API server for Litestream.
|
|
type Server struct {
|
|
ln net.Listener
|
|
closed bool
|
|
|
|
httpServer *http.Server
|
|
promHandler http.Handler
|
|
|
|
addr string
|
|
server *litestream.Server
|
|
|
|
g errgroup.Group
|
|
|
|
Logger *log.Logger
|
|
}
|
|
|
|
func NewServer(server *litestream.Server, addr string) *Server {
|
|
s := &Server{
|
|
addr: addr,
|
|
server: server,
|
|
Logger: log.New(os.Stderr, "http: ", litestream.LogFlags),
|
|
}
|
|
|
|
s.promHandler = promhttp.Handler()
|
|
s.httpServer = &http.Server{
|
|
Handler: http.HandlerFunc(s.serveHTTP),
|
|
}
|
|
return s
|
|
}
|
|
|
|
func (s *Server) Open() (err error) {
|
|
if s.ln, err = net.Listen("tcp", s.addr); err != nil {
|
|
return err
|
|
}
|
|
|
|
s.g.Go(func() error {
|
|
if err := s.httpServer.Serve(s.ln); err != nil && !s.closed {
|
|
return err
|
|
}
|
|
return nil
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *Server) Close() (err error) {
|
|
s.closed = true
|
|
|
|
if s.ln != nil {
|
|
if e := s.ln.Close(); e != nil && err == nil {
|
|
err = e
|
|
}
|
|
}
|
|
|
|
if e := s.g.Wait(); e != nil && err == nil {
|
|
err = e
|
|
}
|
|
return err
|
|
}
|
|
|
|
// Port returns the port the listener is running on.
|
|
func (s *Server) Port() int {
|
|
if s.ln == nil {
|
|
return 0
|
|
}
|
|
return s.ln.Addr().(*net.TCPAddr).Port
|
|
}
|
|
|
|
// URL returns the full base URL for the running server.
|
|
func (s *Server) URL() string {
|
|
host, _, _ := net.SplitHostPort(s.addr)
|
|
if host == "" {
|
|
host = "localhost"
|
|
}
|
|
return fmt.Sprintf("http://%s", net.JoinHostPort(host, fmt.Sprint(s.Port())))
|
|
}
|
|
|
|
func (s *Server) serveHTTP(w http.ResponseWriter, r *http.Request) {
|
|
if strings.HasPrefix(r.URL.Path, "/debug/pprof") {
|
|
switch r.URL.Path {
|
|
case "/debug/pprof/cmdline":
|
|
httppprof.Cmdline(w, r)
|
|
case "/debug/pprof/profile":
|
|
httppprof.Profile(w, r)
|
|
case "/debug/pprof/symbol":
|
|
httppprof.Symbol(w, r)
|
|
case "/debug/pprof/trace":
|
|
httppprof.Trace(w, r)
|
|
default:
|
|
httppprof.Index(w, r)
|
|
}
|
|
return
|
|
}
|
|
|
|
switch r.URL.Path {
|
|
case "/metrics":
|
|
s.promHandler.ServeHTTP(w, r)
|
|
default:
|
|
http.NotFound(w, r)
|
|
}
|
|
}
|