Skip to main content

is_gateway_api_http_path

Function is_gateway_api_http_path 

Source
pub fn is_gateway_api_http_path(path: &str) -> Result<(), String>
Expand description

Predicate: assert that path is a valid HTTP path under both the K8s Gateway API v1 HTTPPathMatch.value admission grammar AND the Cilium L7 path: rule grammar — the two landing sites every validated pleme-io HTTP-shaped path lands in. The contract:

  • 1..=GATEWAY_API_HTTP_PATH_MAX_LEN (1024) bytes;
  • leading / (the PathPrefix invariant — pre-checked at the call site by each axis’s narrower *NotAbsolute variant; re-checked here so the predicate is usable from any future call site without a shape-mismatch footgun);
  • no consecutive / characters (HTTP path matchers reject // — collapse to a single /);
  • no /./ or /../ segments (and no trailing /. or /..) — path-traversal and no-op segments are rejected outright;
  • no ? (query separator: queries are matched separately via HTTPRoute queryParams, never in the path);
  • no # (fragment separator: fragments are client-side and never reach the gateway);
  • no whitespace (space, tab — must be percent-encoded as %20);
  • no ASCII control characters (0x00..0x1F, 0x7F);
  • no non-ASCII bytes (>= 0x80) — RFC 3986 requires %XX percent-encoding for anything outside the ASCII unreserved + reserved set;
  • no printable-ASCII byte outside the K8s Gateway API HTTPPathMatch.value apiserver-side OpenAPI regex ^(?:[-A-Za-z0-9/._~!$&'()*+,;=:@]|[%][0-9a-fA-F]{2})+$ accepted set — namely " < > [ \ ] ^ ` { | }. These eleven bytes are printable ASCII but RFC 3986’s pchar = unreserved / pct-encoded / sub-delims / ":" / "@" grammar excludes them, so the apiserver rejects them at admission time on every HTTPRoute.spec.rules[].matches[]. path.value landing site and the Cilium L7 path matcher refuses them too. Percent-encode (%XX) if the literal byte is intended.

Returns the parser-shaped reason on rejection (without wrapping in any error variant) so each per-axis caller — validate_entrada_path for :entrada :paths entries, WitContract::target for the HTTP- shaped :contratos :endpoint axis, every future per-path lift (the M4 CR materializer’s per-path validator, the future per-HTTPRouteRule per-path-match emission) — wraps the same reason in its own typed *Invalid { <axis>, reason } variant. The reason wording is axis-agnostic (“HTTP path matchers reject //”) so every call site reading the same diagnostic points at the same rule; drift between any two axes’ rule enforcement is a build error visible at this predicate, not a per-renderer “this passed validate but failed admission” surprise.

Empty input is rejected at the call site (each axis has its own narrower *Empty variant — crate::AplicacaoError::EntradaPathEmpty, crate::AplicacaoError::ContratoEndpointEmpty) before this predicate is consulted, mirroring is_dns_1123_label’s empty-first cascade. The predicate body re-checks empty + leading-/ defensively so it can be called from any future call site without a shape-mismatch footgun.

Lifted from caixa-core::aplicacao::validate_entrada_path (where it was first inlined for :entrada :paths in 55410e4) at the second occurrence of the HTTP-path-grammar — the :contratos :endpoint axis (c4213a4 gated non-empty + leading-/ only, silently passing the same authoring footguns the :entrada :paths gate catches) — so the second axis lands as a thin three-line wrapper at the per-axis call site rather than re-inlining 90 lines of grammar enforcement. Same compounding shape as is_dns_1123_label (lifted at its third occurrence in 31bfa43) and the M2-overlay / label-selector helpers (9e3a057, 9d09cfb, 9dbeafd, 31455a7, 07a4544) on the render side — each lifted a recurring shape into a typed primitive at the threshold where the duplication budget would otherwise have been exceeded.

§Errors

Returns the parser-shaped reason naming the specific violation (length / character-class / segment / consecutive-slash), without wrapping in any error variant — every caller maps the same String into its own typed *Invalid { <axis>, reason } enum variant.