Kyle: "Fold them into the plan." What changed and why is in docs/P6.md §14. In short:
- FetchFunc gets the *auth.Caller (the given api test could not compile, and a fetch with no
caller would bypass per-caller gates, the pool limit, the cache class and redaction);
- store reads never bump the lease (task 01's rule contradicted its own test); the API Touches;
- 1-2 workers round-robin over live jobs, so a batch holds at most 2 of the 8 global slots;
busy targets retry in the runner (bounded); batch PDFs use their own pool name; 210 s deadline;
- the api tests no longer touch the network or race the cancel; private names via fake DNS;
- failed/cancelled jobs are not reused; GET is a summary plus GET …/{idx} and ?results=1;
- the 256 KiB body cap moves into ServeHTTP; a fixed metrics label for /v1/batch/{id};
- guard.PreCheck (given verbatim) replaces guard.ParseURL at submit;
- 5 tasks became 8 (refactor, wiring, endpoints and serve/config split), each restating the
APIs it uses; every given test compiles against a panic-only skeleton and fails on it.
P6 starts after P5c: task 04 moves v1fetch, which P5b changes. Recheck the api given tests
against post-P5c master before the run.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
54 lines
1.5 KiB
Go
54 lines
1.5 KiB
Go
package guard
|
|
|
|
// P6 task 05: PreCheck is CheckURL without name resolution, for refusing a batch target at
|
|
// submit time.
|
|
|
|
import (
|
|
"context"
|
|
"net/netip"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestPreCheck(t *testing.T) {
|
|
g := &Guard{
|
|
AllowPrefixes: []netip.Prefix{netip.MustParsePrefix("127.0.0.0/8")},
|
|
LookupIP: func(context.Context, string) ([]netip.Addr, error) {
|
|
t.Fatal("PreCheck resolved a name")
|
|
return nil, nil
|
|
},
|
|
}
|
|
for _, u := range []string{
|
|
"https://example.com/",
|
|
"http://example.com/path?q=1",
|
|
"https://internal.test/", // a name: not resolved here, so not refused here
|
|
"http://127.0.0.1:8080/", // an allowed literal is exempt from the port rule, as in CheckURL
|
|
"http://93.184.215.14/", // a public literal
|
|
"http://0x7f000001:8080/", // inet_aton form of 127.0.0.1: an allowed literal
|
|
} {
|
|
if err := g.PreCheck(u); err != nil {
|
|
t.Errorf("PreCheck(%q) = %v, want nil", u, err)
|
|
}
|
|
}
|
|
for _, u := range []string{
|
|
"",
|
|
"ftp://example.com/",
|
|
"http://user@example.com/",
|
|
"http://example.com:8080/",
|
|
"http://10.0.0.5/",
|
|
"http://169.254.169.254/latest/meta-data/",
|
|
"http://[::1]/",
|
|
"http://0x0a000005/", // inet_aton form of 10.0.0.5
|
|
} {
|
|
err := g.PreCheck(u)
|
|
if err == nil || !strings.HasPrefix(err.Error(), "blocked") {
|
|
t.Errorf("PreCheck(%q) = %v, want a blocked error", u, err)
|
|
}
|
|
}
|
|
// With no allow list, loopback is refused like any other private literal.
|
|
var zero Guard
|
|
if err := zero.PreCheck("http://127.0.0.1/"); err == nil {
|
|
t.Error("a zero Guard allowed loopback")
|
|
}
|
|
}
|