A 200 with a bad Tavily body is tavily: error, not an empty success that would cache for the hour. Upstream clients stay in the source list if DNS is down at boot and retry the pin on Search; /healthz lists them as unresolved until a pin lands.
159 lines
3.6 KiB
Go
159 lines
3.6 KiB
Go
package dial_test
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/netip"
|
|
"net/url"
|
|
"strings"
|
|
"sync/atomic"
|
|
"testing"
|
|
|
|
"git.wntrmute.dev/kyle/sift/internal/search/dial"
|
|
)
|
|
|
|
var errDNS = errors.New("dns down")
|
|
|
|
func TestLoopbackAllowsConfiguredPort(t *testing.T) {
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(200)
|
|
_, _ = w.Write([]byte("ok"))
|
|
}))
|
|
defer ts.Close()
|
|
c, err := dial.New(ts.URL, dial.Options{Loopback: true, Timeout: 0})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
resp, err := c.HTTP.Get(ts.URL + "/")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer resp.Body.Close()
|
|
if resp.StatusCode != 200 {
|
|
t.Fatalf("status %d", resp.StatusCode)
|
|
}
|
|
}
|
|
|
|
func TestLoopbackRefusesOtherPort(t *testing.T) {
|
|
c, err := dial.New("http://127.0.0.1:8888", dial.Options{
|
|
Loopback: true,
|
|
Lookup: func(_ context.Context, _ string) ([]netip.Addr, error) {
|
|
return []netip.Addr{netip.MustParseAddr("127.0.0.1")}, nil
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
resp, err := c.HTTP.Get("http://127.0.0.1:11434/")
|
|
if err == nil {
|
|
resp.Body.Close()
|
|
t.Fatal("dialed other loopback port")
|
|
}
|
|
if !strings.Contains(err.Error(), "refused") && !strings.Contains(err.Error(), "search dial") {
|
|
t.Fatalf("err %v", err)
|
|
}
|
|
}
|
|
|
|
func TestPublicPoisonedPrivateRefused(t *testing.T) {
|
|
c, err := dial.New("https://api.tavily.com/search", dial.Options{
|
|
Loopback: false,
|
|
Lookup: func(_ context.Context, host string) ([]netip.Addr, error) {
|
|
return []netip.Addr{netip.MustParseAddr("127.0.0.1")}, nil
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if c.Ready() {
|
|
t.Fatal("poisoned A record pinned")
|
|
}
|
|
}
|
|
|
|
func TestPublicPrivateRFC1918Refused(t *testing.T) {
|
|
c, err := dial.New("https://api.search.brave.com/res/v1/llm/context", dial.Options{
|
|
Lookup: func(_ context.Context, _ string) ([]netip.Addr, error) {
|
|
return []netip.Addr{netip.MustParseAddr("10.0.0.5")}, nil
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if c.Ready() {
|
|
t.Fatal("private A pinned")
|
|
}
|
|
}
|
|
|
|
func TestTLSSystemRoots(t *testing.T) {
|
|
c, err := dial.New("https://api.tavily.com/search", dial.Options{
|
|
Lookup: func(_ context.Context, _ string) ([]netip.Addr, error) {
|
|
return []netip.Addr{netip.MustParseAddr("1.1.1.1")}, nil
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
cfg := c.TLSConfig()
|
|
if cfg == nil {
|
|
t.Fatal("nil tls")
|
|
}
|
|
if cfg.InsecureSkipVerify {
|
|
t.Fatal("InsecureSkipVerify")
|
|
}
|
|
if cfg.RootCAs != nil {
|
|
t.Fatal("want system roots (nil RootCAs)")
|
|
}
|
|
}
|
|
|
|
func TestNoUserinfo(t *testing.T) {
|
|
_, err := dial.New("http://u:p@127.0.0.1:8888", dial.Options{Loopback: true})
|
|
if err == nil {
|
|
t.Fatal("userinfo allowed")
|
|
}
|
|
}
|
|
|
|
func TestParseRejectsNonHTTP(t *testing.T) {
|
|
_, err := dial.New("ftp://example.com/", dial.Options{})
|
|
if err == nil {
|
|
t.Fatal("ftp allowed")
|
|
}
|
|
_ = url.URL{}
|
|
}
|
|
|
|
func TestResolveRetriesAfterDNSDown(t *testing.T) {
|
|
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(200)
|
|
}))
|
|
defer ts.Close()
|
|
u, _ := url.Parse(ts.URL)
|
|
ip := netip.MustParseAddr(u.Hostname())
|
|
var n atomic.Int32
|
|
c, err := dial.New(ts.URL, dial.Options{
|
|
Loopback: true,
|
|
Lookup: func(_ context.Context, host string) ([]netip.Addr, error) {
|
|
if n.Add(1) == 1 {
|
|
return nil, errDNS
|
|
}
|
|
return []netip.Addr{ip}, nil
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if c.Ready() {
|
|
t.Fatal("first lookup should fail")
|
|
}
|
|
if err := c.Ensure(context.Background()); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !c.Ready() {
|
|
t.Fatal("retry")
|
|
}
|
|
resp, err := c.HTTP.Get(ts.URL + "/")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
resp.Body.Close()
|
|
}
|