Repository: actix/actix-web
Pull request #718 (2019-03-07 20:06:21)

feat: enable use of patch as request method
When I was trying out actix-web I noticed that I am not able to register handlers for the PATCH HTTP method.

```rust
app.resource("/users/{userId}", |r| {
        r.get().f(get_user);
        r.patch().f(patch_user); // can't do this
        r.delete().f(delete_user);
    });
```

I dove into the code and added the capabilities where I could figure out additions are needed. I saw it come up only once [here](https://github.com/actix/actix-web/blob/ceca96da281ec0b7d3bdce202f1eb84d2447ce15/src/pred.rs#L161). Is there a reason PATCH is not supported yet?

If I am completely wrong feel free to close this PR or point me in the right direction 👍 

Edit: I was not sure where to add tests for this.

DoumanAsh: Could you please add note to CHANGELOG?
In addition to that please add test case with patch requests
jannikkeye: @DoumanAsh Kindly check again, did not get around to adjust the PR until today.

Patch:
diff --git a/CHANGES.md b/CHANGES.md
index 76f3465e..57333613 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -10,6 +10,8 @@
 
 * Add client HTTP Authentication methods `.basic_auth()`  and `.bearer_auth()`. #540
 
+* Add support for PATCH HTTP method
+
 ### Fixed
 
 * Ignored the `If-Modified-Since` if `If-None-Match` is specified. #680
diff --git a/src/client/mod.rs b/src/client/mod.rs
index 5321e4b0..8c15fae4 100644
--- a/src/client/mod.rs
+++ b/src/client/mod.rs
@@ -105,6 +105,13 @@ pub fn post<U: AsRef<str>>(uri: U) -> ClientRequestBuilder {
     builder
 }
 
+/// Create request builder for `PATCH` requests
+pub fn patch<U: AsRef<str>>(uri: U) -> ClientRequestBuilder {
+    let mut builder = ClientRequest::build();
+    builder.method(Method::PATCH).uri(uri);
+    builder
+}
+
 /// Create request builder for `PUT` requests
 pub fn put<U: AsRef<str>>(uri: U) -> ClientRequestBuilder {
     let mut builder = ClientRequest::build();
diff --git a/src/client/request.rs b/src/client/request.rs
index 89789933..bf5145df 100644
--- a/src/client/request.rs
+++ b/src/client/request.rs
@@ -112,6 +112,13 @@ impl ClientRequest {
         builder
     }
 
+    /// Create request builder for `PATCH` request
+    pub fn patch<U: AsRef<str>>(uri: U) -> ClientRequestBuilder {
+        let mut builder = ClientRequest::build();
+        builder.method(Method::PATCH).uri(uri);
+        builder
+    }
+
     /// Create request builder for `PUT` request
     pub fn put<U: AsRef<str>>(uri: U) -> ClientRequestBuilder {
         let mut builder = ClientRequest::build();
diff --git a/src/resource.rs b/src/resource.rs
index d884dd44..78aea07c 100644
--- a/src/resource.rs
+++ b/src/resource.rs
@@ -107,6 +107,12 @@ impl<S: 'static> Resource<S> {
         self.routes.last_mut().unwrap().filter(pred::Post())
     }
 
+    /// Register a new `PATCH` route.
+    pub fn patch(&mut self) -> &mut Route<S> {
+        self.routes.push(Route::default());
+        self.routes.last_mut().unwrap().filter(pred::Patch())
+    }
+
     /// Register a new `PUT` route.
     pub fn put(&mut self) -> &mut Route<S> {
         self.routes.push(Route::default());


Test patch:
diff --git a/src/test.rs b/src/test.rs
index 1d86db9f..584c02a5 100644
--- a/src/test.rs
+++ b/src/test.rs
@@ -239,6 +239,11 @@ impl TestServer {
         ClientRequest::post(self.url("/").as_str())
     }
 
+    /// Create `PATCH` request
+    pub fn patch(&self) -> ClientRequestBuilder {
+        ClientRequest::patch(self.url("/").as_str())
+    }
+
     /// Create `HEAD` request
     pub fn head(&self) -> ClientRequestBuilder {
         ClientRequest::head(self.url("/").as_str())
diff --git a/tests/test_server.rs b/tests/test_server.rs
index f3c9bf9d..68482bb1 100644
--- a/tests/test_server.rs
+++ b/tests/test_server.rs
@@ -1398,3 +1398,11 @@ fn test_content_length() {
         assert_eq!(response.headers().get(&header), Some(&value));
     }
 }
+
+#[test]
+fn test_patch_method() {
+    let mut srv = test::TestServer::new(|app| app.handler(|_| HttpResponse::Ok()));
+    let req = srv.patch().finish().unwrap();
+    let response = srv.execute(req.send()).unwrap();
+    assert!(response.status().is_success());
+}
\ No newline at end of file