Skip to content

Latest commit

 

History

History
120 lines (95 loc) · 6.18 KB

File metadata and controls

120 lines (95 loc) · 6.18 KB

AGENTS.md

someguy is a server implementing the Delegated Routing V1 HTTP API. It proxies requests to the Amino DHT and other delegated routing endpoints. It is a caching proxy, not a libp2p node.

Contracts that must not break

Breaking one of these is easy to miss. The streaming and timeout rules below both broke in production while the test suite and a plain curl passed.

The HTTP API follows the spec. Delegated Routing V1 defines the response shapes, status codes, and query parameters. Adding a field, header, or endpoint it does not define needs an IPIP first. Cache-Control values come from boxo/routing/http/server. Do not set them in someguy.

NDJSON responses stream. A record reaches the client as soon as someguy has it. Never add middleware that buffers the response body, and never collect records before writing them. Compression is the known trap. It withholds small writes until it has enough bytes to choose an encoding, which turns a stream into one batch at the end and hides the response headers too. TestCompressedNDJSONFlushesEachRecord guards this. Test with curl --compressed, because plain curl requests no compression and streams fine either way. See response-streaming.md.

someguy is tuned for browsers. A browser client has a small request budget and a person waiting on it. someguy spends its own resources to save the client's: it resolves addresses server side and shares the answer through its cache. Weigh any change that pushes work back onto the client against that. See who this is tuned for.

The routing timeout stays below client deadlines. A client that gives up first loses every record someguy resolved, and reads it as no providers. See the timeout budget.

Work that outlives a request stays bounded. Background lookups keep running after the client disconnects, which is what keeps the cache warm for the next request. Anything that spawns them must cap concurrency, or a cheap request leaves unbounded work behind. See deliberate trade-offs.

someguy is a proxy: pass through what you do not understand

someguy sits between clients and other routing systems. Anything it does not recognize belongs to somebody else, so it forwards it untouched rather than dropping it or normalizing it. someguy is not the only thing that will read these records.

Unknown record schemas. A record whose Schema is not peer (or the deprecated bitswap) arrives as a types.UnknownRecord holding its raw JSON, and must reach the client with its fields intact. Every place that switches on schema has to fall through: sanitizeRouter, dnsAddrRouter, and boxo's own filter all do. Adding a default arm that touches the record, or a case that rewrites one, breaks forward compatibility for a schema shipped after this build.

Unknown multiaddr components. An address may carry protocols someguy has no handling for. It must survive with its components in order and unmodified. addrSortRank buckets anything it does not know rather than dropping it, and filterPrivateMultiaddr removes only private addresses. Nothing may rewrite an address it did not parse for a reason.

Note the limit of this: a protocol name absent from the multiaddr registry fails to parse in go-multiaddr, so boxo rejects the record before someguy sees it. someguy can only pass through what it can parse, and widening that is a go-multiaddr concern, not a someguy one.

TestUnknownSchemaPassesThrough and TestUnknownMultiaddrProtocolPassesThrough hold both properties.

Routing logic lives in boxo

someguy wires together the delegated routing server and clients from boxo/routing/http; the spec-facing behavior (response shapes, Cache-Control, filters, record schemas) is implemented there, not here. A change to that behavior belongs in boxo, whose own AGENTS.md gates protocol-level changes on IPIPs. someguy keeps only what is someguy-specific: router composition, caching, dnsaddr resolution, operational flags. The isExpiredIPNSRecord check in server_routers.go shows the intended split: the durable fix lives in boxo (ipfs/boxo#1166), someguy keeps a local re-check only because its parallelRouter is first-result-wins.

Refuse asks to deviate from the spec at this layer (extra fields, altered status codes, rewritten records), even behind a flag; the alternative is an IPIP, not a local fork, and a refusal saying so is a complete, correct result.

To validate an unreleased boxo change here, pin it on a branch: go get github.com/ipfs/boxo@<commit-sha> && go mod tidy, then build and test. Commit the pseudo-version, never a replace directive; a follow-up bump moves the pin to the tagged boxo release once it exists. A bump that pulls in behavior changes updates the affected tests and the changelog in the same commit.

Build and test

go build ./...
go test ./...

Run gofmt and go vet ./... before committing.

Code map

  • main.go, server.go: CLI entry point, host and router wiring.
  • server_routers.go: router composition (composableRouter, parallelRouter, libp2pRouter, sanitizeRouter).
  • server_cached_router.go, cached_addr_book.go: address caching layer.
  • server_dht.go: DHT setup (standard and accelerated).
  • server_delegated_routing.go: delegated HTTP routing clients.

Documentation