HTTP reverse proxy for Tailscale

log gateway errors

The default handler logs to the global stdlib logger. This uses our
structured logger and adds the upstream to the log line.

+5 -2
+1 -2
main.go
··· 136 136 } 137 137 138 138 logger := slog.New(slog.NewJSONHandler(os.Stderr)) 139 - // see ReverseProxy.ErrorLog; this ensures these logs go to our logger. 140 139 slog.SetDefault(logger) 141 140 142 141 st, err := tsWaitStatusReady(ctx, &tailscale.LocalClient{}) ··· 223 222 Handler: promhttp.InstrumentHandlerInFlight(requestsInFlight, 224 223 promhttp.InstrumentHandlerDuration(duration, 225 224 promhttp.InstrumentHandlerCounter(requests, 226 - newReverseProxy(log, lc, upstream.backend)))), 225 + newReverseProxy(log.With(slog.String("upstream", upstream.name)), lc, upstream.backend)))), 227 226 } 228 227 229 228 g.Add(func() error {
+4
tsproxy.go
··· 61 61 req.Out.Host = req.In.Host 62 62 }, 63 63 } 64 + rproxy.ErrorHandler = func(w http.ResponseWriter, r *http.Request, err error) { 65 + http.Error(w, http.StatusText(http.StatusBadGateway), http.StatusBadGateway) 66 + logger.Error("upstream error", err) 67 + } 64 68 65 69 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 66 70 whois, err := lc.WhoIs(r.Context(), r.RemoteAddr)