use std::fmt::{self, Formatter};
use crate::http::uri::Scheme;
use crate::http::{Method, Request};
use crate::routing::{Filter, PathState};
#[derive(Clone, PartialEq, Eq)]
pub struct MethodFilter(pub Method);
impl MethodFilter {
pub fn new(method: Method) -> Self {
Self(method)
}
}
impl Filter for MethodFilter {
#[inline]
fn filter(&self, req: &mut Request, _state: &mut PathState) -> bool {
req.method() == self.0
}
}
impl fmt::Debug for MethodFilter {
#[inline]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "method:{:?}", self.0)
}
}
#[derive(Clone, PartialEq, Eq)]
#[non_exhaustive]
pub struct SchemeFilter {
pub scheme: Scheme,
pub lack: bool,
}
impl SchemeFilter {
pub fn new(scheme: Scheme) -> Self {
Self { scheme, lack: false }
}
pub fn lack(mut self, lack: bool) -> Self {
self.lack = lack;
self
}
}
impl Filter for SchemeFilter {
#[inline]
fn filter(&self, req: &mut Request, _state: &mut PathState) -> bool {
req.uri().scheme().map(|s| s == &self.scheme).unwrap_or(self.lack)
}
}
impl fmt::Debug for SchemeFilter {
#[inline]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "scheme:{:?}", self.scheme)
}
}
#[derive(Clone, PartialEq, Eq)]
pub struct HostFilter {
pub host: String,
pub lack: bool,
}
impl HostFilter {
pub fn new(host: impl Into<String>) -> Self {
Self {
host: host.into(),
lack: false,
}
}
pub fn lack(mut self, lack: bool) -> Self {
self.lack = lack;
self
}
}
impl Filter for HostFilter {
#[inline]
fn filter(&self, req: &mut Request, _state: &mut PathState) -> bool {
#[cfg(feature = "fix-http1-request-uri")]
let host = req.uri().authority().map(|a| a.as_str());
#[cfg(not(feature = "fix-http1-request-uri"))]
let host = req.uri().authority().map(|a| a.as_str()).or_else(|| {
req.headers()
.get(crate::http::header::HOST)
.and_then(|h| h.to_str().ok())
});
host.map(|h| {
if h.contains(':') {
h.rsplit_once(':')
.expect("rsplit_once by ':' should not returns `None`")
.0
} else {
h
}
})
.map(|h| h == self.host)
.unwrap_or(self.lack)
}
}
impl fmt::Debug for HostFilter {
#[inline]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "host:{:?}", self.host)
}
}
#[derive(Clone, PartialEq, Eq)]
#[non_exhaustive]
pub struct PortFilter {
pub port: u16,
pub lack: bool,
}
impl PortFilter {
pub fn new(port: u16) -> Self {
Self { port, lack: false }
}
pub fn lack(mut self, lack: bool) -> Self {
self.lack = lack;
self
}
}
impl Filter for PortFilter {
#[inline]
fn filter(&self, req: &mut Request, _state: &mut PathState) -> bool {
#[cfg(feature = "fix-http1-request-uri")]
let host = req.uri().authority().map(|a| a.as_str());
#[cfg(not(feature = "fix-http1-request-uri"))]
let host = req.uri().authority().map(|a| a.as_str()).or_else(|| {
req.headers()
.get(crate::http::header::HOST)
.and_then(|h| h.to_str().ok())
});
host.map(|h| {
if h.contains(':') {
h.rsplit_once(':')
.expect("rsplit_once by ':' should not returns `None`")
.1
} else {
h
}
})
.and_then(|p| p.parse::<u16>().ok())
.map(|p| p == self.port)
.unwrap_or(self.lack)
}
}
impl fmt::Debug for PortFilter {
#[inline]
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
write!(f, "port:{:?}", self.port)
}
}