package api import ( "encoding/json" "errors" "net/http" "git.fabledsword.com/bvandeusen/minstrel/internal/apierror" "git.fabledsword.com/bvandeusen/minstrel/internal/auth" "git.fabledsword.com/bvandeusen/minstrel/internal/netsettings" ) type networkSettingsResp struct { TrustedProxyHops int `json:"trusted_proxy_hops"` MaxHops int `json:"max_hops"` // DetectedClientIP is what the CURRENT setting resolves this very request // to. It's the difference between a number the operator has to reason // about and one they can verify: set the value, reload, and check the // address matches the machine you're sitting at. DetectedClientIP string `json:"detected_client_ip"` // ForwardedChain is the raw X-Forwarded-For as received, so an operator // whose detected address looks wrong can see how many hops actually // arrived and count them rather than guess. ForwardedChain string `json:"forwarded_chain"` RemoteAddr string `json:"remote_addr"` } type updateNetworkSettingsReq struct { TrustedProxyHops int `json:"trusted_proxy_hops"` } func (h *handlers) handleGetNetworkSettings(w http.ResponseWriter, r *http.Request) { writeJSON(w, http.StatusOK, h.networkSettingsPayload(r)) } func (h *handlers) handleUpdateNetworkSettings(w http.ResponseWriter, r *http.Request) { var req updateNetworkSettingsReq if err := json.NewDecoder(r.Body).Decode(&req); err != nil { writeErr(w, apierror.BadRequest("invalid_body", "malformed JSON")) return } if err := h.netSettings.SetHops(r.Context(), req.TrustedProxyHops); err != nil { if errors.Is(err, netsettings.ErrHopsOutOfRange) { writeErr(w, apierror.BadRequest("invalid_hops", err.Error())) return } writeErrWithLog(w, h.logger, "admin network: update failed", apierror.Internal(err)) return } // Echo the payload recomputed under the NEW value, so the card can show // immediately what the change did to this request's own address rather // than making the operator reload to find out. writeJSON(w, http.StatusOK, h.networkSettingsPayload(r)) } func (h *handlers) networkSettingsPayload(r *http.Request) networkSettingsResp { hops := h.netSettings.Hops() return networkSettingsResp{ TrustedProxyHops: hops, MaxHops: netsettings.MaxTrustedProxyHops, DetectedClientIP: auth.ClientIP(r, hops), ForwardedChain: r.Header.Get("X-Forwarded-For"), RemoteAddr: r.RemoteAddr, } }