Trait rocket_http::uri::UriDisplay [−][src]
Expand description
Trait implemented by types that can be displayed as part of a URI in
uri!.
Types implementing this trait can be displayed in a URI-safe manner. Unlike
Display, the string written by a UriDisplay implementation must be
URI-safe. In practice, this means that the string must either be
percent-encoded or consist only of characters that are alphanumeric, “-”,
“.”, “_”, or “~” - the “unreserved” characters.
Marker Generic: Path, Query
The UriPart parameter P in UriDisplay<P> must be either Path or
Query (see the UriPart documentation for how this is enforced),
resulting in either UriDisplay<Path> or UriDisplay<Query>.
As the names might imply, the Path version of the trait is used when
displaying parameters in the path part of the URI while the Query version
is used when displaying parameters in the query part of the URI. These
distinct versions of the trait exist exactly to differentiate, at the
type-level, where in the URI a value is to be written to, allowing for type
safety in the face of differences between the two locations. For example,
while it is valid to use a value of None in the query part, omitting the
parameter entirely, doing so is not valid in the path part. By
differentiating in the type system, both of these conditions can be enforced
appropriately through distinct implementations of UriDisplay<Path> and
UriDisplay<Query>.
Occasionally, the implementation of UriDisplay is independent of where the
parameter is to be displayed. When this is the case, the parameter may be
kept generic. That is, implementations can take the form:
impl<P: UriPart> UriDisplay<P> for SomeTypeCode Generation
When the uri! macro is used to generate a URI for a route, the types for
the route’s path URI parameters must implement UriDisplay<Path>, while
types in the route’s query parameters must implement UriDisplay<Query>.
Any parameters ignored with _ must be of a type that implements
Ignorable. The UriDisplay implementation for these types is used when
generating the URI.
To illustrate UriDisplay’s role in code generation for uri!, consider
the following route:
#[get("/item/<id>?<track>")]
fn get_item(id: i32, track: Option<String>) { /* .. */ }A URI for this route can be generated as follows:
// With unnamed parameters.
uri!(get_item: 100, "inbound");
// With named parameters.
uri!(get_item: id = 100, track = "inbound");
uri!(get_item: track = "inbound", id = 100);
// Ignoring `track`.
uri!(get_item: 100, _);
uri!(get_item: id = 100, track = _);
uri!(get_item: track = _, id = 100);After verifying parameters and their types, Rocket will generate code similar (in spirit) to the following:
Origin::parse(&format!("/item/{}?track={}",
&100 as &UriDisplay<Path>, &"inbound" as &UriDisplay<Query>));For this expression to typecheck, i32 must implement UriDisplay<Path>
and &str must implement UriDisplay<Query>. What’s more, when track is
ignored, Option<String> is required to implement Ignorable. As can be
seen, the implementations will be used to display the value in a URI-safe
manner.
Provided Implementations
Rocket implements UriDisplay<P> for all P: UriPart for several built-in
types.
-
i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize, f32, f64, bool, IpAddr, Ipv4Addr, Ipv6Addr
The implementation of
UriDisplayfor these types is identical to theDisplayimplementation. -
&RawStr,String,&str,Cow<str>The string is percent encoded.
-
&T,&mut TwhereT: UriDisplayUses the implementation of
UriDisplayforT.
Rocket implements UriDisplay<Path> (but not UriDisplay<Query>) for
several built-in types.
-
TforOption<T>whereT: UriDisplay<Path>Uses the implementation of
UriDisplayforT::Target.When a type of
Option<T>appears in a route path, use a type ofTas the parameter inuri!. Note thatOption<T>itself does not implementUriDisplay<Path>. -
TforResult<T, E>whereT: UriDisplay<Path>Uses the implementation of
UriDisplayforT::Target.When a type of
Result<T, E>appears in a route path, use a type ofTas the parameter inuri!. Note thatResult<T, E>itself does not implementUriDisplay<Path>.
Rocket implements UriDisplay<Query> (but not UriDisplay<Path>) for
several built-in types.
-
Form<T>,LenientForm<T>whereT: FromUriParam + FromFormUses the implementation of
UriDisplayforT::Target.In general, when a type of
Form<T>is to be displayed as part of a URI’s query, it suffices to deriveUriDisplayforT. Note that any type that can be converted into aTusingFromUriParamcan be used in place of aForm<T>in auri!invocation. -
Option<T>whereT: UriDisplay<Query>If the
OptionisSome, uses the implementation ofUriDisplayforT. Otherwise, nothing is rendered. -
Result<T, E>whereT: UriDisplay<Query>If the
ResultisOk, uses the implementation ofUriDisplayforT. Otherwise, nothing is rendered.
Deriving
Manually implementing UriDisplay should be done with care. For most use
cases, deriving UriDisplay will suffice:
// Derives `UriDisplay<Query>`
#[derive(UriDisplayQuery)]
struct User {
name: String,
age: usize,
}
let user = User { name: "Michael Smith".into(), age: 31 };
let uri_string = format!("{}", &user as &UriDisplay<Query>);
assert_eq!(uri_string, "name=Michael%20Smith&age=31");
// Derives `UriDisplay<Path>`
#[derive(UriDisplayPath)]
struct Name(String);
let name = Name("Bob Smith".into());
let uri_string = format!("{}", &name as &UriDisplay<Path>);
assert_eq!(uri_string, "Bob%20Smith");As long as every field in the structure (or enum) implements UriDisplay,
the trait can be derived. The implementation calls
Formatter::write_named_value() for every named field and
Formatter::write_value() for every unnamed field. See the
UriDisplay<Path> and UriDisplay<Query> derive documentation for full
details.
Implementing
Implementing UriDisplay is similar to implementing
Display with the caveat that extra care must be
taken to ensure that the written string is URI-safe. As mentioned before, in
practice, this means that the string must either be percent-encoded or
consist only of characters that are alphanumeric, “-”, “.”, “_”, or “~”.
When manually implementing UriDisplay for your types, you should defer to
existing implementations of UriDisplay as much as possible. In the example
below, for instance, Name’s implementation defers to String’s
implementation. To percent-encode a string, use
Uri::percent_encode().
Example
The following snippet consists of a Name type that implements both
FromParam and UriDisplay<Path>. The FromParam implementation allows
Name to be used as the target type of a dynamic parameter, while the
UriDisplay implementation allows URIs to be generated for routes with
Name as a dynamic path parameter type. Note the custom parsing in the
FromParam implementation; as a result of this, a custom (reflexive)
UriDisplay implementation is required.
use rocket::http::RawStr;
use rocket::request::FromParam;
struct Name(String);
const PREFIX: &str = "name:";
impl<'r> FromParam<'r> for Name {
type Error = &'r RawStr;
/// Validates parameters that start with 'name:', extracting the text
/// after 'name:' as long as there is at least one character.
fn from_param(param: &'r RawStr) -> Result<Self, Self::Error> {
let decoded = param.percent_decode().map_err(|_| param)?;
if !decoded.starts_with(PREFIX) || decoded.len() < (PREFIX.len() + 1) {
return Err(param);
}
let real_name = decoded[PREFIX.len()..].to_string();
Ok(Name(real_name))
}
}
use std::fmt;
use rocket::http::impl_from_uri_param_identity;
use rocket::http::uri::{Formatter, FromUriParam, UriDisplay, Path};
use rocket::response::Redirect;
impl UriDisplay<Path> for Name {
// Delegates to the `UriDisplay` implementation for `String` via the
// call to `write_value` to ensure that the written string is
// URI-safe. In this case, the string will be percent encoded.
// Prefixes the inner name with `name:`.
fn fmt(&self, f: &mut Formatter<Path>) -> fmt::Result {
f.write_value(&format!("name:{}", self.0))
}
}
impl_from_uri_param_identity!([Path] Name);
#[get("/name/<name>")]
fn redirector(name: Name) -> Redirect {
Redirect::to(uri!(real: name))
}
#[get("/<name>")]
fn real(name: Name) -> String {
format!("Hello, {}!", name.0)
}
let uri = uri!(real: Name("Mike Smith".into()));
assert_eq!(uri.path(), "/name:Mike%20Smith");Required methods
Trait Implementations
Implementations on Foreign Types
Percent-encodes the raw string.
Percent-encodes each segment in the path and normalizes separators.
This implementation is identical to the Display implementation.
This implementation is identical to the Display implementation.
This implementation is identical to the Display implementation.
This implementation is identical to the Display implementation.
This implementation is identical to the Display implementation.
This implementation is identical to the Display implementation.
This implementation is identical to the Display implementation.
This implementation is identical to the Display implementation.
This implementation is identical to the Display implementation.
This implementation is identical to the Display implementation.
This implementation is identical to the Display implementation.
This implementation is identical to the Display implementation.
This implementation is identical to the Display implementation.
This implementation is identical to the Display implementation.
This implementation is identical to the Display implementation.
This implementation is identical to the Display implementation.
This implementation is identical to the Display implementation.
This implementation is identical to the Display implementation.
Percent-encodes the raw string. Defers to str.
Percent-encodes the raw string. Defers to str.
Percent-encodes each segment in the path and normalizes separators.
Defers to the UriDisplay<P> implementation for T.
Defers to the UriDisplay<P> implementation for T.
Defers to the UriDisplay<Query> implementation for T.
Defers to the UriDisplay<Query> implementation for T.
Implementors
Percent-encodes the raw string. Defers to str.