(
segment: &str,
resolver: &SecretResolver,
)
| 812 | // `rewrite_request_line`. |
| 813 | #[allow(clippy::similar_names)] |
| 814 | fn rewrite_path_segment( |
| 815 | segment: &str, |
| 816 | resolver: &SecretResolver, |
| 817 | ) -> Result<(String, String), UnresolvedPlaceholderError> { |
| 818 | let mut resolved = String::with_capacity(segment.len()); |
| 819 | let mut redacted = String::with_capacity(segment.len()); |
| 820 | let mut pos = 0; |
| 821 | let bytes = segment.as_bytes(); |
| 822 | |
| 823 | while pos < bytes.len() { |
| 824 | let next_canonical = segment[pos..].find(PLACEHOLDER_PREFIX).map(|p| pos + p); |
| 825 | let next_alias = segment[pos..] |
| 826 | .find(PROVIDER_ALIAS_MARKER) |
| 827 | .map(|marker_pos| { |
| 828 | let marker_abs = pos + marker_pos; |
| 829 | alias_start_for_marker(segment, marker_abs) |
| 830 | }); |
| 831 | if let Some(abs_start) = [next_canonical, next_alias].into_iter().flatten().min() { |
| 832 | // Copy literal prefix before the placeholder |
| 833 | resolved.push_str(&segment[pos..abs_start]); |
| 834 | redacted.push_str(&segment[pos..abs_start]); |
| 835 | |
| 836 | let Some((token_end, full_placeholder)) = canonical_token_at(segment, abs_start) |
| 837 | .or_else(|| alias_token_at(segment, abs_start)) |
| 838 | else { |
| 839 | return Err(UnresolvedPlaceholderError { location: "path" }); |
| 840 | }; |
| 841 | if let Some(secret) = resolver.resolve_placeholder(full_placeholder) { |
| 842 | validate_credential_for_path(secret).map_err(|reason| { |
| 843 | tracing::warn!( |
| 844 | location = "path", |
| 845 | %reason, |
| 846 | "credential resolution rejected: resolved value unsafe for path" |
| 847 | ); |
| 848 | UnresolvedPlaceholderError { location: "path" } |
| 849 | })?; |
| 850 | resolved.push_str(secret); |
| 851 | redacted.push_str("[CREDENTIAL]"); |
| 852 | } else { |
| 853 | return Err(UnresolvedPlaceholderError { location: "path" }); |
| 854 | } |
| 855 | pos = token_end; |
| 856 | } else { |
| 857 | // No more placeholders in remainder |
| 858 | resolved.push_str(&segment[pos..]); |
| 859 | redacted.push_str(&segment[pos..]); |
| 860 | break; |
| 861 | } |
| 862 | } |
| 863 | |
| 864 | Ok((resolved, redacted)) |
| 865 | } |
| 866 | |
| 867 | /// Rewrite placeholders in query parameter values. |
| 868 | /// |
no test coverage detected