waldo_proxy.go
1package rtw
2
3import (
4 "context"
5 "errors"
6 "log/slog"
7 "net/http"
8 "net/http/httputil"
9 "net/url"
10)
11
12// WaldoProxyHandler returns an HTTP handler that transparently proxies GET
13// requests to the upstream Waldo geocoding service at targetURL.
14// Forwards request headers and query parameters to the upstream Waldo service.
15func WaldoProxyHandler(targetURL string) http.Handler {
16 target, err := url.Parse(targetURL)
17 if err != nil {
18 slog.Error("invalid waldo target url", "error", err, "url", targetURL)
19 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
20 http.Error(w, "invalid geocoder configuration", http.StatusInternalServerError)
21 })
22 }
23
24 proxy := httputil.NewSingleHostReverseProxy(target)
25
26 proxy.ErrorHandler = func(w http.ResponseWriter, r *http.Request, err error) {
27 if errors.Is(err, context.Canceled) {
28 slog.Debug("waldo proxy client disconnected", "path", r.URL.Path)
29 return
30 }
31 slog.Error("waldo proxy error", "error", err, "path", r.URL.Path)
32 http.Error(w, "upstream error", http.StatusBadGateway)
33 }
34
35 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
36 if r.Method != http.MethodGet && r.Method != http.MethodHead {
37 w.Header().Set("Allow", "GET, HEAD")
38 http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
39 return
40 }
41 proxy.ServeHTTP(w, r)
42 })
43}