Implement TryFrom<Method> for MethodFilter (#1130)

* implement TryFrom<http::Method> for MethodFilter

* test for TryFrom<http::Method> for MethodFilter

* 'UnsupportedMethod' error type for MethodFilter

* Log TryFrom<http::Method> for MethodFilter

* adjust docs

* move docs

Co-authored-by: David Pedersen <david.pdrsn@gmail.com>
This commit is contained in:
NicolaLS 2022-07-01 10:37:41 +02:00 committed by GitHub
parent 698b5ccf39
commit 34146f3139
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 99 additions and 0 deletions

View file

@ -16,7 +16,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
`/foo/`). That is no longer supported and such requests will now be sent to
the fallback. Consider using `axum_extra::routing::RouterExt::route_with_tsr`
if you want the old behavior ([#1119])
- **added** Implement `TryFrom<http:: Method>` for `MethodFilter` and use new `NoMatchingMethodFilter` error in case of failure ([#1130])
[#1130]: https://github.com/tokio-rs/axum/pull/1130
[#1077]: https://github.com/tokio-rs/axum/pull/1077
[#1102]: https://github.com/tokio-rs/axum/pull/1102
[#1119]: https://github.com/tokio-rs/axum/pull/1119

View file

@ -1,4 +1,9 @@
use bitflags::bitflags;
use http::Method;
use std::{
fmt,
fmt::{Debug, Formatter},
};
bitflags! {
/// A filter that matches one or more HTTP methods.
@ -21,3 +26,95 @@ bitflags! {
const TRACE = 0b100000000;
}
}
/// Error type used when converting a [`Method`] to a [`MethodFilter`] fails.
#[derive(Debug)]
pub struct NoMatchingMethodFilter {
method: Method,
}
impl NoMatchingMethodFilter {
/// Get the [`Method`] that couldn't be converted to a [`MethodFilter`].
pub fn method(&self) -> &Method {
&self.method
}
}
impl fmt::Display for NoMatchingMethodFilter {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "no `MethodFilter` for `{}`", self.method.as_str())
}
}
impl std::error::Error for NoMatchingMethodFilter {}
impl TryFrom<Method> for MethodFilter {
type Error = NoMatchingMethodFilter;
fn try_from(m: Method) -> Result<Self, NoMatchingMethodFilter> {
match m {
Method::DELETE => Ok(MethodFilter::DELETE),
Method::GET => Ok(MethodFilter::GET),
Method::HEAD => Ok(MethodFilter::HEAD),
Method::OPTIONS => Ok(MethodFilter::OPTIONS),
Method::PATCH => Ok(MethodFilter::PATCH),
Method::POST => Ok(MethodFilter::POST),
Method::PUT => Ok(MethodFilter::PUT),
Method::TRACE => Ok(MethodFilter::TRACE),
other => Err(NoMatchingMethodFilter { method: other }),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn from_http_method() {
assert_eq!(
MethodFilter::try_from(Method::DELETE).unwrap(),
MethodFilter::DELETE
);
assert_eq!(
MethodFilter::try_from(Method::GET).unwrap(),
MethodFilter::GET
);
assert_eq!(
MethodFilter::try_from(Method::HEAD).unwrap(),
MethodFilter::HEAD
);
assert_eq!(
MethodFilter::try_from(Method::OPTIONS).unwrap(),
MethodFilter::OPTIONS
);
assert_eq!(
MethodFilter::try_from(Method::PATCH).unwrap(),
MethodFilter::PATCH
);
assert_eq!(
MethodFilter::try_from(Method::POST).unwrap(),
MethodFilter::POST
);
assert_eq!(
MethodFilter::try_from(Method::PUT).unwrap(),
MethodFilter::PUT
);
assert_eq!(
MethodFilter::try_from(Method::TRACE).unwrap(),
MethodFilter::TRACE
);
assert!(MethodFilter::try_from(http::Method::CONNECT)
.unwrap_err()
.to_string()
.contains("CONNECT"));
}
}