├── go.mod ├── Dockerfile └── main.go /go.mod: -------------------------------------------------------------------------------- 1 | module lubien/tired-proxy 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1 2 | 3 | FROM golang:1.16-alpine 4 | 5 | WORKDIR /app 6 | 7 | COPY go.mod ./ 8 | 9 | RUN go mod download 10 | 11 | COPY *.go ./ 12 | 13 | RUN GOOS=linux GOARCH=amd64 go build -o /tired-proxy 14 | 15 | CMD [ "/tired-proxy" ] -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "fmt" 6 | "log" 7 | "net" 8 | "net/http" 9 | "net/http/httputil" 10 | "net/url" 11 | "os" 12 | "time" 13 | ) 14 | 15 | type IdleTracker struct { 16 | active map[net.Conn]bool 17 | idle time.Duration 18 | timer *time.Timer 19 | } 20 | 21 | func NewIdleTracker(idle time.Duration) *IdleTracker { 22 | return &IdleTracker{ 23 | active: make(map[net.Conn]bool), 24 | idle: idle, 25 | timer: time.NewTimer(idle), 26 | } 27 | } 28 | 29 | func (t *IdleTracker) Done() <-chan time.Time { 30 | return t.timer.C 31 | } 32 | 33 | func main() { 34 | var host = flag.String("host", "http://localhost", "host") 35 | var port = flag.String("port", "8080", "port") 36 | var timeInSeconds = flag.Int("time", 60, "time in seconds") 37 | flag.Parse() 38 | 39 | remote, err := url.Parse(*host) 40 | if err != nil { 41 | panic(err) 42 | } 43 | 44 | idle := NewIdleTracker(time.Duration(*timeInSeconds) * time.Second) 45 | 46 | handler := func(p *httputil.ReverseProxy) func(http.ResponseWriter, *http.Request) { 47 | return func(w http.ResponseWriter, r *http.Request) { 48 | idle.timer.Reset(idle.idle) 49 | log.Println(r.URL) 50 | r.Host = remote.Host 51 | w.Header().Set("X-Ben", "Rad") 52 | p.ServeHTTP(w, r) 53 | } 54 | } 55 | 56 | proxy := httputil.NewSingleHostReverseProxy(remote) 57 | http.HandleFunc("/", handler(proxy)) 58 | 59 | fmt.Println("Starting server") 60 | 61 | go func() { 62 | <-idle.Done() 63 | fmt.Println("Shutting down server") 64 | os.Exit(0) 65 | }() 66 | 67 | err = http.ListenAndServe(fmt.Sprintf(":%s", *port), nil) 68 | if err != nil { 69 | panic(err) 70 | } 71 | } 72 | --------------------------------------------------------------------------------