module

Noir::RustRequestGuards

Which request-guard / extractor types can refuse an anonymous caller, read off their impl FromRequest for X (Rocket, actix-web) or impl FromRequestParts<S> for X (axum) definitions instead of their names.

A type refuses when its impl can answer 401/403 (Status::Unauthorized, StatusCode::FORBIDDEN, actix ErrorUnauthorized, or a macro_rules! whose body does, or returns as its error a variant that fn status_code maps to 401/403: Err(MyError::IncorrectLogin) / .ok_or(MyError::IncorrectLogin) after MyError::IncorrectLogin => StatusCode::UNAUTHORIZED; into_response and any &self method returning a StatusCode, such as fn client_status_and_error(&self) -> (StatusCode, ClientError), map variants the same way, read where the enum is defined: its file when the guard's file defines it, else its crate), or forwards the failure of a type that refuses (try_outcome!(Headers::from_request(req).await), X::from_request_parts(..).await?). A refusal that only fires when another in-crate guard fails (let Outcome::Success(ip) = ClientIp::from_request(req).await else { 401 }) counts only if that guard itself refuses, so a wrapper around a guard that never fails is not a guard.

A redirect to a login page (Redirect::to("/login"), a SEE_OTHER with a /login location) refuses like a 401.

No file I/O: callers feed source text (and its path) to scan and combine the results.

Constants

ANY_STATUS_RE = /\bStatusCode::[A-Z]\w*|\bRedirect::\w+\s*\(/

A status or a redirect (any 3xx).

AUTH_STATUS_RE = /\bStatusCode::(?:UNAUTHORIZED|FORBIDDEN)\b/
AUTH_VARIANT_RE = /\A(?:Missing|Invalid|Expired|Bad|No)\w*(?:Authori[sz]ation|Credential|ApiKey|AuthToken|BearerToken)\w*\z|\A(?:Unauthori[sz]ed|Unauthenticated|Forbidden)\w*\z/

ponytail: fallback when no status mapping in reach decides a variant (e.g. a Code table behind a macro): the variant's own name says it refuses the credential. Add real mapping reads when a repo needs more.

CRATE_USE_RE = /\buse\s+crate::[^;]*;/
ENUM_DEF_RE = /\benum\s+([A-Z]\w*)/
ENUM_GLOB_RE = /\buse\s+(?:[\w:]+::)?([A-Z]\w*)::\*\s*;/
ERR_ADAPTERS = {"ok_or", "ok_or_else", "map_err"}

Methods whose argument becomes the Err of the value they return.

EVIDENCE_RE = /\bFromRequest|macro_rules!/
GUARD_CALL_RE = /(\w+)(?:\s*::\s*<[^<>]*>)?\s*::\s*from_request(?:_parts)?\s*\(|\bguard\s*::\s*<\s*(?:\w+::)*(\w+)/
IMPL_FOR_RE = /\bimpl\b[^{};]*?\bfor\s+(?:\w+::)*(\w+)/
IMPL_KEYWORD_RE = /\bimpl\b/
INHERENT_IMPL_RE = /impl(?:\s*<[^;{}]*>)?\s+(?:\w+::)*(\w+)(?:\s*<[^;{}]*>)?\s*\{/

impl Type, impl crate::Type, impl Type<T>, impl<T> Type<T>. Both impl patterns are matched anchored at an impl keyword.

LOGIN_REDIRECT_RE = /(?:\bRedirect::\w+\s*\(\s*|(?:\bLOCATION|"(?i:location)")\s*,\s*)"(?![^"]*\berror=)[^"]*?(?<![A-Za-z])(?i:log_?in|sign_?in)/

Redirect::to("/login"), (header::LOCATION, "/signin"): the target literal names a login page and carries no error= (an OAuth callback sending a failed login back is not a refusal of the caller).

MAX_DEPTH = 256
PATTERN_PATH_RE = /(?<![\w:])((?:[A-Za-z_]\w*::)*[A-Z]\w*)(?![\w:])/

An enum path in a match pattern: AppError::NotLoggedIn, NotLoggedIn.

REFUSAL_RE = /\bStatus::(?:Unauthorized|Forbidden)\b|\bStatusCode::(?:UNAUTHORIZED|FORBIDDEN)\b|\bError(?:Unauthorized|Forbidden)\b/
RUST_LITERAL_RE = /(?<![\w'])b?r(#*)"[\s\S]*?"\1|'(?:[^'\\\n]|\\(?:u\{[0-9a-fA-F]{1,6}\}|x[0-9a-fA-F]{2}|.))'/

A raw string (r#"say "hi""#) or a char literal ('"', '\'', '\u{1F600}'), neither of which the C-style stripper can read; not a lifetime ('a).

SELF_CALL_RE = /\bSelf\s*::\s*(\w+)\s*(?:::\s*<[^<>]*>\s*)?\(/

Self::auth_token(...): a call to an inherent method of the guard type.

STATUS_FN_RE = /\bfn\s+(?:(status_code)|into_response)\b|\bfn\s+\w+\s*\(\s*&?\s*(?:mut\s+)?self\b[^)]*\)\s*->\s*[^{;]*\bStatusCode\b/

ponytail: a status mapping is read off its signature, not its callers; a &self -> StatusCode helper nothing calls still maps its variants.

SUCCESS_ARM_RE = /\A(?:(?:\w+::)*Outcome::)?(?:Success|Ok)\s*\(/
TRAIT_RE = /\A(?:\w+::)*FromRequest(?:Parts)?\b/
VARIANT_PATH_RE = /\A(?:\w+::)*[A-Z]\w*\z/

Class methods

handler_param_types(source : String) : Hash(Int32, Array(String))

Leaf type names of a fn's parameters that are required guards, keyed by the fn name's 1-based line. Option<X> / Result<X, E> parameters never refuse the request, so they are left out.

Source
resolve(facts : Facts) : Hash(String, Bool)

{type => refuses?} for every type whose impls agree.

Source
scan(source : String, facts : Facts, path : String = "") : Nil
Source
type_leaf(text : String) : String | Nil
Source

Nested types