83 lines
1.6 KiB
Go
83 lines
1.6 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"net/http/httputil"
|
|
"net/url"
|
|
"os"
|
|
"os/signal"
|
|
"strings"
|
|
|
|
"tailscale.com/tsnet"
|
|
)
|
|
|
|
func must[T any](t T, err error) T {
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return t
|
|
}
|
|
|
|
func main() {
|
|
var servers []*http.Server
|
|
|
|
upstreamsConfig := os.Getenv("UPSTREAMS")
|
|
hosts := strings.Split(upstreamsConfig, ",")
|
|
if upstreamsConfig == "" || len(hosts) == 0 {
|
|
log.Fatalf("set UPSTREAMS in environment like 'dockerhost:7400,otherdocker:80'")
|
|
}
|
|
|
|
for _, upstream := range hosts {
|
|
hostname, port, ok := strings.Cut(upstream, ":")
|
|
if hostname == "" {
|
|
// parsing error, just skip it
|
|
continue
|
|
}
|
|
if !ok || port == "" {
|
|
// default to 80
|
|
port = "80"
|
|
}
|
|
s := &tsnet.Server{
|
|
Dir: "/.config/" + hostname,
|
|
Hostname: hostname,
|
|
Logf: func(s string, a ...any) { // silence most tsnet logs
|
|
if strings.HasPrefix(s, "To start this tsnet server") {
|
|
log.Printf(s, a...)
|
|
}
|
|
},
|
|
}
|
|
defer s.Close()
|
|
|
|
ln, err := s.Listen("tcp", ":80")
|
|
if err != nil {
|
|
fmt.Printf("%+v\n", err)
|
|
return
|
|
}
|
|
defer ln.Close()
|
|
|
|
srv := &http.Server{
|
|
Handler: httputil.NewSingleHostReverseProxy(
|
|
must(url.Parse("http://" + hostname + ":" + port + "/")),
|
|
),
|
|
}
|
|
servers = append(servers, srv)
|
|
// start server
|
|
go func() {
|
|
err = srv.Serve(ln)
|
|
fmt.Printf("%+v\n", err)
|
|
}()
|
|
}
|
|
|
|
sigint := make(chan os.Signal, 1)
|
|
signal.Notify(sigint, os.Interrupt)
|
|
<-sigint
|
|
for _, server := range servers {
|
|
if err := server.Shutdown(context.Background()); err != nil {
|
|
log.Printf("HTTP server Shutdown: %v", err)
|
|
}
|
|
}
|
|
}
|