Commit graph Crafter.Network/tests/ShouldFollowRedirectsHTTP1
Author SHA1 Message Date
7ee938c98e
feat(http1): ClientHTTP1::Fetch follows redirects by the RFC, on a URL type
One request to an http(s) URL with redirects followed by RFC 9110 §15.4:
301, 302, 303, 307 and 308 for every method; a 303 makes the request a
GET without its body and content headers, a 301 or 302 does so for a POST
alone, a 307 or 308 keeps the method and the body. The Location is
resolved against the sending URL by RFC 3986, a hop between http and
https is allowed, Authorization, Proxy-Authorization and Cookie are
dropped on a change of origin, and each hop is a client of its own, since
one ClientHTTP1 is one origin. A redirect without a usable Location, to
another scheme, back to a URL already visited or past maxRedirects comes
back as the response, with `stop` saying why.

The new :URL partition is the URL type behind it, exported: Parse,
Resolve (RFC 3986 §5.2; its §5.4 examples are the test), ToString, and
the pieces a request is built from.

This replaces the FetchHTTP1 free function, which followed redirects the
way Python's urllib did (its repeat limit, its quoting of the Location, a
POST turned back on a 307) for a port that no longer needs the fidelity.

Breaking: FetchHTTP1, FetchOptionsHTTP1 and FetchResultHTTP1 are gone;
use ClientHTTP1::Fetch, FetchOptions and FetchResult, whose `url` is a
URL and whose `limited` became `stop`.
2026-10-31 20:39:43 +01:00
f9a45c143e
feat(http1): bound the connect, and FetchHTTP1 for a URL with redirects
- ClientHTTP1 gains connectTimeout (default 15 s), applied to each
  address the host resolves to. `timeout` only ever bounded the waits for
  a response, so a host that drops the SYNs held Send() for the kernel's
  retries, about two minutes, whatever the caller had asked for.
- The default Host header puts an IPv6 literal in brackets.
- FetchHTTP1(url, options) makes one request to an http:// or https://
  URL and follows redirects as Python's urllib does, so urllib code ported
  over keeps its behaviour: 301/302/303/307/308 for GET and HEAD,
  301/302/303 for POST (re-sent as a GET without its body), a relative
  Location resolved as urljoin resolves it and percent-encoded as urllib
  quotes it, http and https hops mixed, each redirect's body read before
  the next request, and the chain stopped by urllib's limits (4 repeats
  of one URL, 10 different URLs) with the last redirect returned and
  `limited` set. Proxies are not consulted.

New: ShouldTimeoutSilentHTTP1, ShouldFollowRedirectsHTTP1.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 20:28:32 +01:00