Struct rocket_http::uri::Host
source · pub struct Host<'a>(/* private fields */);
Expand description
A domain and port identified by a client as the server being messaged.
For requests made via HTTP/1.1, a host is identified via the HOST
header.
In HTTP/2 and HTTP/3, this information is instead communicated via the
:authority
and :port
pseudo-header request fields. It is a
client-controlled value via which the client communicates to the server the
domain name and port it is attempting to communicate with. The following
diagram illustrates the syntactic structure of a Host
:
some.domain.foo:8088
|-------------| |--|
domain port
Only the domain part is required. Its value is case-insensitive.
URI Construction
A Host
is not a Uri
, and none of Rocket’s APIs will
accept a Host
value as such. This is because doing so would facilitate the
construction of URIs to internal routes in a manner controllable by an
attacker, inevitably leading to “HTTP Host header attacks”.
Instead, a Host
must be checked before being converted to a [Uri
]
value. The Host::to_authority
and Host::to_absolute
methods provide
these mechanisms:
use rocket::http::uri::Host;
// A sensitive URI we want to prefix with safe hosts.
#[get("/token?<secret>")]
fn token(secret: Token) { /* .. */ }
// Whitelist of known hosts. In a real setting, you might retrieve this
// list from config at ignite-time using tools like `AdHoc::config()`.
const WHITELIST: [Host<'static>; 4] = [
Host::new(uri!("rocket.rs")),
Host::new(uri!("rocket.rs:443")),
Host::new(uri!("guide.rocket.rs")),
Host::new(uri!("guide.rocket.rs:443")),
];
// Use `Host::to_absolute()` to case-insensitively check a host against a
// whitelist, returning an `Absolute` usable as a `uri!()` prefix.
let host = Host::new(uri!("guide.ROCKET.rs"));
let prefix = host.to_absolute("https", &WHITELIST);
// Since `guide.rocket.rs` is in the whitelist, `prefix` is `Some`.
assert!(prefix.is_some());
if let Some(prefix) = prefix {
// We can use this prefix to safely construct URIs.
let uri = uri!(prefix, token("some-secret-token"));
assert_eq!(uri, "https://guide.ROCKET.rs/token?secret=some-secret-token");
}
(De)serialization
Host
is both Serialize
and Deserialize
:
use serde::{Serialize, Deserialize};
use rocket::http::uri::Host;
#[derive(Deserialize, Serialize)]
struct UriOwned {
uri: Host<'static>,
}
#[derive(Deserialize, Serialize)]
struct UriBorrowed<'a> {
uri: Host<'a>,
}
Implementations§
source§impl<'a> Host<'a>
impl<'a> Host<'a>
sourcepub const fn new(authority: Authority<'a>) -> Self
pub const fn new(authority: Authority<'a>) -> Self
Create a new Host
from an Authority
. Only the host
and port
parts are preserved.
use rocket::http::uri::Host;
let host = Host::new(uri!("developer.mozilla.org"));
assert_eq!(host.to_string(), "developer.mozilla.org");
let host = Host::new(uri!("foo:bar@developer.mozilla.org:1234"));
assert_eq!(host.to_string(), "developer.mozilla.org:1234");
let host = Host::new(uri!("rocket.rs:443"));
assert_eq!(host.to_string(), "rocket.rs:443");
sourcepub fn parse(string: &'a str) -> Result<Host<'a>, Error<'a>>
pub fn parse(string: &'a str) -> Result<Host<'a>, Error<'a>>
Parses the string string
into a Host
. Parsing will never allocate.
Returns an Error
if string
is not a valid authority URI, meaning
that this parser accepts a user_info
part for compatibility but
discards it.
Example
use rocket::http::uri::Host;
// Parse from a valid authority URI.
let host = Host::parse("user:pass@domain").expect("valid host");
assert_eq!(host.domain(), "domain");
assert_eq!(host.port(), None);
// Parse from a valid host.
let host = Host::parse("domain:311").expect("valid host");
assert_eq!(host.domain(), "doMaIN");
assert_eq!(host.port(), Some(311));
// Invalid hosts fail to parse.
Host::parse("https://rocket.rs").expect_err("invalid host");
// Prefer to use `uri!()` when the input is statically known:
let host = Host::new(uri!("domain"));
assert_eq!(host.domain(), "domain");
assert_eq!(host.port(), None);
sourcepub fn parse_owned(string: String) -> Result<Host<'static>, Error<'static>>
pub fn parse_owned(string: String) -> Result<Host<'static>, Error<'static>>
Parses the string string
into an Host
. Parsing never allocates
on success. May allocate on error.
This method should be used instead of Host::parse()
when the source
is already a String
. Returns an Error
if string
is not a valid
authority URI, meaning that this parser accepts a user_info
part for
compatibility but discards it.
Example
use rocket::http::uri::Host;
let source = format!("rocket.rs:8000");
let host = Host::parse_owned(source).expect("valid host");
assert_eq!(host.domain(), "rocket.rs");
assert_eq!(host.port(), Some(8000));
sourcepub fn domain(&self) -> &UncasedStr
pub fn domain(&self) -> &UncasedStr
Returns the case-insensitive domain part of the host.
Example
use rocket::http::uri::Host;
let host = Host::new(uri!("domain.com:123"));
assert_eq!(host.domain(), "domain.com");
let host = Host::new(uri!("username:password@domain:123"));
assert_eq!(host.domain(), "domain");
let host = Host::new(uri!("[1::2]:123"));
assert_eq!(host.domain(), "[1::2]");
sourcepub fn port(&self) -> Option<u16>
pub fn port(&self) -> Option<u16>
Returns the port part of the host, if there is one.
Example
use rocket::http::uri::Host;
// With a port.
let host = Host::new(uri!("domain:123"));
assert_eq!(host.port(), Some(123));
let host = Host::new(uri!("domain.com:8181"));
assert_eq!(host.port(), Some(8181));
// Without a port.
let host = Host::new(uri!("domain.foo.bar.tld"));
assert_eq!(host.port(), None);
Checks self
against whitelist
. If self
is in whitelist
, returns
an Authority
URI representing self. Otherwise, returns None
.
Domain comparison is case-insensitive.
See URI construction for more.
Example
use rocket::http::uri::Host;
let whitelist = &[Host::new(uri!("domain.tld"))];
// A host in the whitelist returns `Some`.
let host = Host::new(uri!("domain.tld"));
let uri = host.to_authority(whitelist);
assert!(uri.is_some());
assert_eq!(uri.unwrap().to_string(), "domain.tld");
let host = Host::new(uri!("foo:bar@doMaIN.tLd"));
let uri = host.to_authority(whitelist);
assert!(uri.is_some());
assert_eq!(uri.unwrap().to_string(), "doMaIN.tLd");
// A host _not_ in the whitelist returns `None`.
let host = Host::new(uri!("domain.tld:1234"));
let uri = host.to_authority(whitelist);
assert!(uri.is_none());
sourcepub fn to_absolute<'h, W>(
&self,
scheme: &'a str,
whitelist: W
) -> Option<Absolute<'a>>where
W: IntoIterator<Item = &'h Host<'h>>,
pub fn to_absolute<'h, W>( &self, scheme: &'a str, whitelist: W ) -> Option<Absolute<'a>>where W: IntoIterator<Item = &'h Host<'h>>,
Checks self
against whitelist
. If self
is in whitelist
, returns
an Absolute
URI representing self
with scheme scheme
. Otherwise,
returns None
. Domain comparison is case-insensitive.
See URI construction for more.
Example
use rocket::http::uri::Host;
let whitelist = &[Host::new(uri!("domain.tld:443"))];
// A host in the whitelist returns `Some`.
let host = Host::new(uri!("user@domain.tld:443"));
let uri = host.to_absolute("http", whitelist);
assert!(uri.is_some());
assert_eq!(uri.unwrap().to_string(), "http://domain.tld:443");
let host = Host::new(uri!("domain.TLD:443"));
let uri = host.to_absolute("https", whitelist);
assert!(uri.is_some());
assert_eq!(uri.unwrap().to_string(), "https://domain.TLD:443");
// A host _not_ in the whitelist returns `None`.
let host = Host::new(uri!("domain.tld"));
let uri = host.to_absolute("http", whitelist);
assert!(uri.is_none());
Trait Implementations§
source§impl PartialEq<&str> for Host<'_>
impl PartialEq<&str> for Host<'_>
source§impl PartialEq<Host<'_>> for str
impl PartialEq<Host<'_>> for str
source§impl<'a, 'b> PartialEq<Host<'b>> for Host<'a>
impl<'a, 'b> PartialEq<Host<'b>> for Host<'a>
source§impl PartialEq<str> for Host<'_>
impl PartialEq<str> for Host<'_>
impl Eq for Host<'_>
Auto Trait Implementations§
impl<'a> RefUnwindSafe for Host<'a>
impl<'a> Send for Host<'a>
impl<'a> Sync for Host<'a>
impl<'a> Unpin for Host<'a>
impl<'a> UnwindSafe for Host<'a>
Blanket Implementations§
source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<Q, K> Equivalent<K> for Qwhere
Q: Eq + ?Sized,
K: Borrow<Q> + ?Sized,
impl<Q, K> Equivalent<K> for Qwhere Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
§impl<Q, K> Equivalent<K> for Qwhere
Q: Eq + ?Sized,
K: Borrow<Q> + ?Sized,
impl<Q, K> Equivalent<K> for Qwhere Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key
and return true
if they are equal.§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
source§impl<T> IntoCollection<T> for T
impl<T> IntoCollection<T> for T
§impl<T> Paint for Twhere
T: ?Sized,
impl<T> Paint for Twhere T: ?Sized,
§fn fg(&self, value: Color) -> Painted<&T>
fn fg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self
with the foreground set to
value
.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like red()
and
green()
, which have the same functionality but are
pithier.
Example
Set foreground color to white using fg()
:
use yansi::{Paint, Color};
painted.fg(Color::White);
Set foreground color to white using white()
.
use yansi::Paint;
painted.white();
§fn bright_black(&self) -> Painted<&T>
fn bright_black(&self) -> Painted<&T>
§fn bright_red(&self) -> Painted<&T>
fn bright_red(&self) -> Painted<&T>
§fn bright_green(&self) -> Painted<&T>
fn bright_green(&self) -> Painted<&T>
§fn bright_yellow(&self) -> Painted<&T>
fn bright_yellow(&self) -> Painted<&T>
§fn bright_blue(&self) -> Painted<&T>
fn bright_blue(&self) -> Painted<&T>
§fn bright_magenta(&self) -> Painted<&T>
fn bright_magenta(&self) -> Painted<&T>
§fn bright_cyan(&self) -> Painted<&T>
fn bright_cyan(&self) -> Painted<&T>
§fn bright_white(&self) -> Painted<&T>
fn bright_white(&self) -> Painted<&T>
§fn bg(&self, value: Color) -> Painted<&T>
fn bg(&self, value: Color) -> Painted<&T>
Returns a styled value derived from self
with the background set to
value
.
This method should be used rarely. Instead, prefer to use color-specific
builder methods like on_red()
and
on_green()
, which have the same functionality but
are pithier.
Example
Set background color to red using fg()
:
use yansi::{Paint, Color};
painted.bg(Color::Red);
Set background color to red using on_red()
.
use yansi::Paint;
painted.on_red();
§fn on_primary(&self) -> Painted<&T>
fn on_primary(&self) -> Painted<&T>
§fn on_magenta(&self) -> Painted<&T>
fn on_magenta(&self) -> Painted<&T>
§fn on_bright_black(&self) -> Painted<&T>
fn on_bright_black(&self) -> Painted<&T>
§fn on_bright_red(&self) -> Painted<&T>
fn on_bright_red(&self) -> Painted<&T>
§fn on_bright_green(&self) -> Painted<&T>
fn on_bright_green(&self) -> Painted<&T>
§fn on_bright_yellow(&self) -> Painted<&T>
fn on_bright_yellow(&self) -> Painted<&T>
§fn on_bright_blue(&self) -> Painted<&T>
fn on_bright_blue(&self) -> Painted<&T>
§fn on_bright_magenta(&self) -> Painted<&T>
fn on_bright_magenta(&self) -> Painted<&T>
§fn on_bright_cyan(&self) -> Painted<&T>
fn on_bright_cyan(&self) -> Painted<&T>
§fn on_bright_white(&self) -> Painted<&T>
fn on_bright_white(&self) -> Painted<&T>
§fn attr(&self, value: Attribute) -> Painted<&T>
fn attr(&self, value: Attribute) -> Painted<&T>
Enables the styling [Attribute
] value
.
This method should be used rarely. Instead, prefer to use
attribute-specific builder methods like bold()
and
underline()
, which have the same functionality
but are pithier.
Example
Make text bold using attr()
:
use yansi::{Paint, Attribute};
painted.attr(Attribute::Bold);
Make text bold using using bold()
.
use yansi::Paint;
painted.bold();
§fn rapid_blink(&self) -> Painted<&T>
fn rapid_blink(&self) -> Painted<&T>
§fn quirk(&self, value: Quirk) -> Painted<&T>
fn quirk(&self, value: Quirk) -> Painted<&T>
Enables the yansi
[Quirk
] value
.
This method should be used rarely. Instead, prefer to use quirk-specific
builder methods like mask()
and
wrap()
, which have the same functionality but are
pithier.
Example
Enable wrapping using .quirk()
:
use yansi::{Paint, Quirk};
painted.quirk(Quirk::Wrap);
Enable wrapping using wrap()
.
use yansi::Paint;
painted.wrap();
§fn whenever(&self, value: Condition) -> Painted<&T>
fn whenever(&self, value: Condition) -> Painted<&T>
Conditionally enable styling based on whether the [Condition
] value
applies. Replaces any previous condition.
See the crate level docs for more details.
Example
Enable styling painted
only when both stdout
and stderr
are TTYs:
use yansi::{Paint, Condition};
painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);