pub fn parse_www_authenticate(s: &str) -> Vec<Challenge>Expand description
Parse a WWW-Authenticate / Proxy-Authenticate field value into a
list of Challenges, per RFC 9110 §11.6.1:
WWW-Authenticate = #challenge
challenge = auth-scheme [ 1*SP ( token68 / #auth-param ) ]
auth-scheme = token
auth-param = token BWS "=" BWS ( token / quoted-string )
token68 = 1*( ALPHA / DIGIT / "-" / "." / "_" / "~"
/ "+" / "/" ) *"="§The §11.6.1 list ambiguity
Both the challenge list AND the auth-param list inside a challenge
are comma-separated, so a flat top-level comma split cannot by itself
tell “next challenge” from “next auth-param of the current
challenge”. §11.6.1 spells out the worked example:
WWW-Authenticate: Basic realm="simple", Newauth realm="apps",
type=1, title="Login to \"apps\""which is two challenges: Basic with realm="simple", and
Newauth with realm="apps", type=1, title="Login to \"apps\"".
The disambiguation rule this parser applies, after a quoted-string-
aware top-level comma split (§5.6.1 #-list, so a comma inside a
"…" value never splits): each list element is classified as either
- a bare
auth-param(token BWS "=" …) — it has NO scheme of its own, so it attaches to the challenge currently being built; or - a challenge head (
auth-schemealone, orauth-scheme 1*SP <arg>) — it starts a new challenge.
An element is a bare auth-param when its first token is
immediately followed (modulo §11.2 BWS around =) by = with no
intervening 1*SP scheme/argument boundary. Everything else opens a
new challenge, whose first whitespace-delimited token is the
auth-scheme and whose remainder (if any) is the first token68 or
first auth-param.
§Token68 vs auth-param within a challenge
§11.2’s token68 may end in *"=", which collides with the
auth-param =. The parser treats a challenge argument as
token68 only when it is one whitespace-free run whose body is all
token68 characters with any = confined to a trailing pad run AND
it is not of name=value auth-param shape; otherwise the
remainder is parsed as the #auth-param list. Once a challenge has
committed to auth-params, subsequent bare auth-param elements
attach to it.
§Robustness
Matching the rest of the driver’s §5.6.1 list handling, malformed
pieces are skipped rather than failing the whole parse: an empty
list element (the §11.6.1 “comma, whitespace, comma” note calls this
harmless), an auth-param slot that is not token = (token / quoted-string), or a leading bare auth-param with no challenge to
attach to are all dropped while the surrounding well-formed
challenges survive. An obs-fold (RFC 7230 §3.2.4) anywhere in the
value is normalised to a single SP before parsing.
The same grammar backs Proxy-Authenticate (§11.7.1) and, with the
credentials = auth-scheme [ 1*SP ( token68 / #auth-param ) ]
production being identical, a single Authorization /
Proxy-Authorization value (which carries exactly one challenge-
shaped credentials); a caller wanting just the credentials reads
the first element of the returned Vec.