Skip to main content

Crate templated_uri

Crate templated_uri 

Source
Expand description

Standards-compliant URI handling with templating, validation, and data classification.

This crate provides comprehensive URI manipulation capabilities designed for HTTP clients and servers that need type-safe, efficient, and data classification-aware URI handling. It builds on top of the standard http crate while adding additional validation guarantees, templating capabilities, and data classification features.

§Core Types

The crate centers around several key abstractions:

  • Uri - Flexible URI type composed of an optional BaseUri and an optional path/query
  • BaseUri - Lightweight type representing scheme, authority, and optional base path (BasePath)
  • PathAndQueryTemplate - RFC 6570 Level 3 compliant URI templating
  • Escaped and EscapedString - Generic newtype wrapper proving a value is properly escaped for URI components by not containing any reserved characters

§Basic Usage

§Simple URI Construction

use templated_uri::{BaseUri, PathAndQuery, Uri};

// Create the base (scheme + authority, optionally a path prefix)
let base_uri = BaseUri::from_static("https://api.example.com");

// Create a path (can be static for zero-allocation)
let path: PathAndQuery = PathAndQuery::from_static("/api/v1/users");

// Combine into complete URI
let uri = Uri::default().with_base(base_uri).with_path_and_query(path);
assert_eq!(
    uri.to_string().declassify_ref(),
    "https://api.example.com/api/v1/users"
);

§Templated URIs

For dynamic URIs with variable components, use the templating system:

use templated_uri::{BaseUri, EscapedString, PathAndQueryTemplate, Uri, templated};

#[templated(template = "/users/{user_id}/posts/{post_id}", unredacted)]
#[derive(Clone)]
struct UserPostPath {
    user_id: u32,
    post_id: EscapedString,
}

let path = UserPostPath {
    user_id: 42,
    post_id: EscapedString::escape("my-post"),
};

let uri = Uri::default()
    .with_base(BaseUri::from_static("https://api.example.com"))
    .with_path_and_query(path);

§URI Escaping Guarantees

The Escaped<T> newtype wraps values that are guaranteed to contain only valid URI characters. This prevents common URI injection vulnerabilities:

use templated_uri::EscapedString;

// This will succeed - percent-encodes any invalid characters
let encoded = EscapedString::escape("hello world?foo=bar");
assert_eq!(encoded.as_str(), "hello%20world%3Ffoo%3Dbar");

// This will succeed - contains only valid characters
let valid = EscapedString::try_new("hello-world_123").unwrap();
assert_eq!(valid.as_str(), "hello-world_123");

// try_new() fails on URI-reserved characters
let invalid = EscapedString::try_new("hello world?foo=bar");
assert!(invalid.is_err());

Built-in valid types include numeric types (u32, u64, etc.), Uuid (with the uuid feature), IP addresses, and validated EscapedString instances.

§Telemetry Labels

For complex templates, use the label attribute to provide a concise identifier for telemetry. When present, the label takes precedence over the template string.

use templated_uri::{EscapedString, templated};

#[templated(
    template = "/{org}/users/{user_id}/reports/{report_type}",
    label = "user_report",
    unredacted
)]
struct ReportPath {
    org: EscapedString,
    user_id: EscapedString,
    report_type: EscapedString,
}

§Data Classification

The crate integrates with data_privacy to track data sensitivity levels in URIs. This is particularly important for compliance and data security:

use data_privacy::Sensitive;
use templated_uri::{EscapedString, templated};

#[templated(template = "/{org_id}/user/{user_id}/")]
#[derive(Clone)]
struct UserPath {
    #[unredacted]
    org_id: EscapedString,
    user_id: Sensitive<EscapedString>,
}

§RFC 6570 Template Compliance

The templating system implements RFC 6570 Level 3 URI Template specification. Supported expansions include:

  • Simple string expansion: {var}
  • Reserved string expansion: {+var}
  • Path segments: {/var}
  • Query parameters: {?var}
  • Query continuation: {&var}

Note: Fragment expansion ({#var}) from RFC 6570 is not supported because URI fragments are stripped by the http crate and ignored by HTTP clients.

Template variables must implement Escape (except for reserved expansions, which use Raw) to ensure the resulting URI is valid.

§Undefined Values (Option<T>)

Per RFC 6570 section 2.3, template variables may be undefined. Use Option<T> to model this: a None value is treated as undefined and the variable (along with its prefix or separator) is omitted from the rendered URI.

use templated_uri::{EscapedString, PathAndQueryTemplate, templated};

#[templated(template = "/items{?query,limit}", unredacted)]
struct ItemSearch {
    query: EscapedString,
    limit: Option<u32>,
}

// With limit defined:
let path = ItemSearch {
    query: EscapedString::from_static("rust"),
    limit: Some(10),
};
assert_eq!(path.render(), "/items?query=rust&limit=10");

// With limit undefined:
let path = ItemSearch {
    query: EscapedString::from_static("rust"),
    limit: None,
};
assert_eq!(path.render(), "/items?query=rust");

§Integration with HTTP Ecosystem

This crate seamlessly integrates with the broader Rust HTTP ecosystem by re-exporting and building upon the standard http crate types. The resulting Uri can be converted to an http::Uri for use with HTTP clients and servers based on hyper like reqwest.

Modules§

_documentation
Longer form documentation for templated_uri.

Structs§

Authority
Represents the authority component of a URI.
BasePath
The base of a Uri, like /foo.
BaseUri
URI prefix consisting of a scheme, an authority, and an optional path prefix.
EscapeError
Error returned when a string is not a valid URI-escaped string.
Escaped
A wrapper that proves the inner value is already escaped for use in URI templates.
Origin
Scheme and authority components of a URI.
PathAndQuery
Path and query component of a Uri.
Scheme
Represents the scheme component of a URI
Uri
Target URI for HTTP requests, with optional BaseUri and PathAndQuery components.
UriError
Represents errors that occur during URI construction or validation.

Traits§

Escape
Marks types whose values are percent-encoded before being inserted into a URI.
PathAndQueryTemplate
Allows for the creation of URIs based on templates.
Raw
Marks types whose Display output is emitted verbatim into a URI, without percent-encoding reserved characters.

Type Aliases§

EscapedString
A URI-escaped string whose content is guaranteed to contain only characters permitted in URI templates as defined by RFC 6570 (anything else is percent-encoded).

Attribute Macros§

templated
Generates URI templating and data privacy implementations for structs and enums.

Derive Macros§

Escape
Derives the Escape trait for newtype wrappers around URI-escaped types.
Raw
Derives Raw for a newtype, delegating to the inner field’s Display impl.