Repository: seanmonstar/warp (language: rust)

Issue:
Support for HTTP extension methods
**Is your feature request related to a problem? Please describe.**
I'm trying to implement WebDAV handlers using warp, which requires filters for non-standard HTTP methods, as documented in RFC 4918. While `http::Method` allows defining custom methods, warp only provides a pre-defined set of filters for the standard methods and keeps `method_is` in `filters::method` private, so I couldn't figure out any other way to filter for custom methods.
  
**Describe the solution you'd like**
Making `method_is` public would probably be enough already. warp could provide some sugar for `Method::from_bytes`, but that is not absolutely necessary.  

**Describe alternatives you've considered**
I could't figure out any other way to filter for the method in warp.

**Additional context**
N/A


Discussion / hints:
Update, I was now able to write my own filter but it's not particularly pretty vs. what could be achieved if warp supported it directly.

```rust
fn method(name: &str) -> impl Filter<Extract = (), Error = Rejection> + Clone {
    let method =
        Method::from_str(name).expect(&format!("Method name {} could not be converted", name));

    warp::method()
        .and_then(move |m: Method| {
            let method = method.clone();
            async move {
                if m == method {
                    Ok(())
                } else {
                    Err(reject::custom(GatewayHandlerError::MethodNotAllowed))
                }
            }
        })
        .untuple_one()
}

```

Fix patch:
diff --git a/examples/README.md b/examples/README.md
index 087930a5e..1b3bb8a2a 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -62,3 +62,7 @@ Hooray! `warp` also includes built-in support for WebSockets
 ### Debugging
 
 - [`tracing.rs`](./tracing.rs) - Warp has built-in support for rich diagnostics with [`tracing`](https://docs.rs/tracing)!
+
+## Custom HTTP Methods
+
+- [`custom_methods.rs`](./custom_methods.rs) - It is also possible to use Warp with custom HTTP methods.
diff --git a/examples/custom_methods.rs b/examples/custom_methods.rs
new file mode 100644
index 000000000..2e2660413
--- /dev/null
+++ b/examples/custom_methods.rs
@@ -0,0 +1,61 @@
+#![deny(warnings)]
+use std::net::SocketAddr;
+
+use warp::hyper::StatusCode;
+use warp::{hyper::Method, reject, Filter, Rejection, Reply};
+
+#[derive(Debug)]
+struct MethodError;
+impl reject::Reject for MethodError {}
+
+const FOO_METHOD: &'static str = "FOO";
+const BAR_METHOD: &'static str = "BAR";
+
+fn method(name: &'static str) -> impl Filter<Extract = (), Error = Rejection> + Clone {
+    warp::method()
+        .and_then(move |m: Method| async move {
+            if m == name {
+                Ok(())
+            } else {
+                Err(reject::custom(MethodError))
+            }
+        })
+        .untuple_one()
+}
+
+pub async fn handle_not_found(reject: Rejection) -> Result<impl Reply, Rejection> {
+    if reject.is_not_found() {
+        Ok(StatusCode::NOT_FOUND)
+    } else {
+        Err(reject)
+    }
+}
+
+pub async fn handle_custom(reject: Rejection) -> Result<impl Reply, Rejection> {
+    if reject.find::<MethodError>().is_some() {
+        Ok(StatusCode::METHOD_NOT_ALLOWED)
+    } else {
+        Err(reject)
+    }
+}
+
+#[tokio::main]
+async fn main() -> Result<(), Box<dyn std::error::Error>> {
+    let address: SocketAddr = "[::]:3030".parse()?;
+
+    let foo_route = method(FOO_METHOD)
+        .and(warp::path!("foo"))
+        .map(|| "Success")
+        .recover(handle_not_found);
+
+    let bar_route = method(BAR_METHOD)
+        .and(warp::path!("bar"))
+        .map(|| "Success")
+        .recover(handle_not_found);
+
+    warp::serve(foo_route.or(bar_route).recover(handle_custom))
+        .run(address)
+        .await;
+
+    Ok(())
+}


Test patch: