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() }