rocket_post_as_delete/
lib.rs

1//! `rocket-post-as-delete` is a Fairing for [Rocket](https://rocket.rs) rewriting
2//! requests such as `POST foo/bar/delete` into `DELETE foo/bar`.
3//!
4//! This is useful when you have web forms (which, unless you use javascript, only
5//! support POST and GET) for deleting stuff, and want to write those routes with
6//! (the more correct) `DELETE` verb.
7//!
8//! # Example
9//!
10//! ```rust
11//! use rocket::{launch, delete, routes};
12//! use rocket_post_as_delete::PostAsDelete;
13//! 
14//! #[launch]
15//! fn rocket() -> _ {
16//!    rocket::build()
17//!        .attach(PostAsDelete)
18//!        .mount("/", routes![delete_foo_bar])
19//! }
20//! 
21//! #[delete("/foo/bar")]
22//! async fn delete_foo_bar() -> String {
23//!     "Poof!".into()
24//! }
25//! 
26//! # use rocket::local::blocking::Client;
27//! # use rocket::http::Status;
28//! #     let client = Client::tracked(rocket()).expect("valid rocket instance");
29//! #     let response = client.post("/foo/bar/delete").dispatch();
30//! #     assert_eq!(response.status(), Status::Ok);
31//! #     assert_eq!(response.into_string().unwrap(), "Poof!");
32//! ```
33//!
34//! Now forms such as this (`POST` verb, and submit URL suffixed by `/delete`):
35//! ```html
36//! <form method="post" action="/foo/bar/delete">
37//!     <button>Delete me!</button>
38//! </form>
39//! ```
40//!
41//! Will run the `delete_foo_bar` route as expected.
42
43use rocket::{
44    fairing::{Fairing, Info, Kind},
45    http::Method,
46    Data, Request,
47};
48
49pub struct PostAsDelete;
50
51#[rocket::async_trait]
52impl Fairing for PostAsDelete {
53    fn info(&self) -> Info {
54        let kind = Kind::Request;
55        Info {
56            kind,
57            name: "POST as DELETE",
58        }
59    }
60
61    async fn on_request(&self, request: &mut Request<'_>, _: &mut Data<'_>) {
62        let last = request.uri().path().segments().last();
63        if request.method() == Method::Post && last == Some("delete") {
64            request.set_method(Method::Delete);
65            request.set_uri(
66                request
67                    .uri()
68                    .map_path(|p| p.strip_suffix("/delete").unwrap_or(p))
69                    .unwrap(),
70            );
71        }
72    }
73}