Saner HTTP client and contract

This commit is contained in:
Jaz Volpert
2025-07-23 07:14:15 +00:00
parent bbc022c0a6
commit 49282d1670
+38 -28
View File
@@ -5,10 +5,10 @@ import (
"context"
"crypto/subtle"
"crypto/tls"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"io"
"io/fs"
"net/http"
"net/netip"
@@ -48,7 +48,7 @@ type Config struct {
appviewHost string
ogcardHost string
linkHost string
ipccHost string
ipccLookupURL string
staticCDNHost string
}
@@ -66,6 +66,8 @@ func serve(cctx *cli.Context) error {
canonicalInstance := cctx.Bool("bsky-canonical-instance")
robotsDisallowAll := cctx.Bool("robots-disallow-all")
ipccLookupURL := fmt.Sprintf("%s/ipccdata.Service/Lookup", ipccHost)
// Echo
e := echo.New()
@@ -106,7 +108,7 @@ func serve(cctx *cli.Context) error {
appviewHost: appviewHost,
ogcardHost: ogcardHost,
linkHost: linkHost,
ipccHost: ipccHost,
ipccLookupURL: ipccLookupURL,
staticCDNHost: staticCDNHost,
},
ipccClient: http.Client{
@@ -615,39 +617,47 @@ func (srv *Server) WebIpCC(c echo.Context) error {
log.Warnf("could not parse IP %q %s", realIP, err)
return c.JSON(400, IPCCResponse{})
}
var request []byte
if addr.Is4() {
ip4 := addr.As4()
var dest [8]byte
base64.StdEncoding.Encode(dest[:], ip4[:])
request, _ = json.Marshal(IPCCRequest{IP: string(dest[:])})
} else if addr.Is6() {
ip6 := addr.As16()
var dest [24]byte
base64.StdEncoding.Encode(dest[:], ip6[:])
request, _ = json.Marshal(IPCCRequest{IP: string(dest[:])})
ipccReq := &IPCCRequest{
IP: addr.String(),
}
ipccUrlBuilder, err := url.Parse(srv.cfg.ipccHost)
data, err := json.Marshal(ipccReq)
if err != nil {
log.Errorf("ipcc misconfigured bad url %s", err)
log.Warnf("failed to marshal IPCC request %s", err)
return c.JSON(400, IPCCResponse{})
}
req, err := http.NewRequestWithContext(c.Request().Context(), http.MethodPost, srv.cfg.ipccLookupURL, bytes.NewBuffer(data))
if err != nil {
log.Warnf("failed to create IPCC request %s", err)
return c.JSON(500, IPCCResponse{})
}
ipccUrlBuilder.Path = "ipccdata.IpCcService/Lookup"
ipccUrl := ipccUrlBuilder.String()
postBodyReader := bytes.NewReader(request)
response, err := srv.ipccClient.Post(ipccUrl, "application/json", postBodyReader)
if err != nil {
log.Warnf("ipcc backend error %s", err)
return c.JSON(500, IPCCResponse{})
}
defer response.Body.Close()
dec := json.NewDecoder(response.Body)
var outResponse IPCCResponse
err = dec.Decode(&outResponse)
req.Header.Set("Content-Type", "application/json")
resp, err := srv.ipccClient.Do(req)
if err != nil {
log.Warnf("ipcc bad response %s", err)
return c.JSON(500, IPCCResponse{})
}
defer resp.Body.Close()
respBody, err := io.ReadAll(resp.Body)
if err != nil {
log.Warnf("ipcc read response body error %s", err)
return c.JSON(500, IPCCResponse{})
}
if resp.StatusCode != http.StatusOK {
log.Warnf("ipcc bad response status %d %s", resp.StatusCode, respBody)
return c.JSON(500, IPCCResponse{})
}
var outResponse IPCCResponse
if err := json.Unmarshal(respBody, &outResponse); err != nil {
log.Warnf("ipcc unmarshal response error %s", err)
return c.JSON(500, IPCCResponse{})
}
return c.JSON(200, outResponse)
}