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<'a, 'de> Deserialize<'de> for Host<'a>
impl<'a, 'de> Deserialize<'de> for Host<'a>
source§fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error>
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error>
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
source§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,
source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key
and return true
if they are equal.source§impl<T> Instrument for T
impl<T> Instrument for T
source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
source§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
source§impl<T> Paint for Twhere
T: ?Sized,
impl<T> Paint for Twhere T: ?Sized,
source§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();
source§fn bright_black(&self) -> Painted<&T>
fn bright_black(&self) -> Painted<&T>
source§fn bright_red(&self) -> Painted<&T>
fn bright_red(&self) -> Painted<&T>
source§fn bright_green(&self) -> Painted<&T>
fn bright_green(&self) -> Painted<&T>
source§fn bright_yellow(&self) -> Painted<&T>
fn bright_yellow(&self) -> Painted<&T>
Returns self
with the
fg()
set to
Color::BrightYellow
.
Example
println!("{}", value.bright_yellow());
source§fn bright_blue(&self) -> Painted<&T>
fn bright_blue(&self) -> Painted<&T>
source§fn bright_magenta(&self) -> Painted<&T>
fn bright_magenta(&self) -> Painted<&T>
Returns self
with the
fg()
set to
Color::BrightMagenta
.
Example
println!("{}", value.bright_magenta());
source§fn bright_cyan(&self) -> Painted<&T>
fn bright_cyan(&self) -> Painted<&T>
source§fn bright_white(&self) -> Painted<&T>
fn bright_white(&self) -> Painted<&T>
source§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();
source§fn on_primary(&self) -> Painted<&T>
fn on_primary(&self) -> Painted<&T>
source§fn on_magenta(&self) -> Painted<&T>
fn on_magenta(&self) -> Painted<&T>
source§fn on_bright_black(&self) -> Painted<&T>
fn on_bright_black(&self) -> Painted<&T>
Returns self
with the
bg()
set to
Color::BrightBlack
.
Example
println!("{}", value.on_bright_black());
source§fn on_bright_red(&self) -> Painted<&T>
fn on_bright_red(&self) -> Painted<&T>
source§fn on_bright_green(&self) -> Painted<&T>
fn on_bright_green(&self) -> Painted<&T>
Returns self
with the
bg()
set to
Color::BrightGreen
.
Example
println!("{}", value.on_bright_green());
source§fn on_bright_yellow(&self) -> Painted<&T>
fn on_bright_yellow(&self) -> Painted<&T>
Returns self
with the
bg()
set to
Color::BrightYellow
.
Example
println!("{}", value.on_bright_yellow());
source§fn on_bright_blue(&self) -> Painted<&T>
fn on_bright_blue(&self) -> Painted<&T>
Returns self
with the
bg()
set to
Color::BrightBlue
.
Example
println!("{}", value.on_bright_blue());
source§fn on_bright_magenta(&self) -> Painted<&T>
fn on_bright_magenta(&self) -> Painted<&T>
Returns self
with the
bg()
set to
Color::BrightMagenta
.
Example
println!("{}", value.on_bright_magenta());
source§fn on_bright_cyan(&self) -> Painted<&T>
fn on_bright_cyan(&self) -> Painted<&T>
Returns self
with the
bg()
set to
Color::BrightCyan
.
Example
println!("{}", value.on_bright_cyan());
source§fn on_bright_white(&self) -> Painted<&T>
fn on_bright_white(&self) -> Painted<&T>
Returns self
with the
bg()
set to
Color::BrightWhite
.
Example
println!("{}", value.on_bright_white());
source§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();
source§fn underline(&self) -> Painted<&T>
fn underline(&self) -> Painted<&T>
Returns self
with the
attr()
set to
Attribute::Underline
.
Example
println!("{}", value.underline());
source§fn rapid_blink(&self) -> Painted<&T>
fn rapid_blink(&self) -> Painted<&T>
Returns self
with the
attr()
set to
Attribute::RapidBlink
.
Example
println!("{}", value.rapid_blink());
source§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();
source§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);