diff --git a/CHANGES.md b/CHANGES.md index b5078d531..1ed434b74 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,6 +10,8 @@ * Add `test::TestRequest::set_json()` convenience method to automatically serialize data and set header in test requests. + +* Add codegen now supports head, options, trace, connect and patch http methods ### Changes diff --git a/actix-web-codegen/src/lib.rs b/actix-web-codegen/src/lib.rs index 70cde90e4..99abbb6a3 100644 --- a/actix-web-codegen/src/lib.rs +++ b/actix-web-codegen/src/lib.rs @@ -11,6 +11,11 @@ //! - [post](attr.post.html) //! - [put](attr.put.html) //! - [delete](attr.delete.html) +//! - [head](attr.head.html) +//! - [connect](attr.connect.html) +//! - [options](attr.options.html) +//! - [trace](attr.trace.html) +//! - [patch](attr.patch.html) //! //! ### Attributes: //! @@ -92,3 +97,63 @@ pub fn delete(args: TokenStream, input: TokenStream) -> TokenStream { let gen = route::Args::new(&args, input, route::GuardType::Delete); gen.generate() } + +/// Creates route handler with `HEAD` method guard. +/// +/// Syntax: `#[head("path"[, attributes])]` +/// +/// Attributes are the same as in [head](attr.head.html) +#[proc_macro_attribute] +pub fn head(args: TokenStream, input: TokenStream) -> TokenStream { + let args = parse_macro_input!(args as syn::AttributeArgs); + let gen = route::Args::new(&args, input, route::GuardType::Head); + gen.generate() +} + +/// Creates route handler with `CONNECT` method guard. +/// +/// Syntax: `#[connect("path"[, attributes])]` +/// +/// Attributes are the same as in [connect](attr.connect.html) +#[proc_macro_attribute] +pub fn connect(args: TokenStream, input: TokenStream) -> TokenStream { + let args = parse_macro_input!(args as syn::AttributeArgs); + let gen = route::Args::new(&args, input, route::GuardType::Connect); + gen.generate() +} + +/// Creates route handler with `OPTIONS` method guard. +/// +/// Syntax: `#[options("path"[, attributes])]` +/// +/// Attributes are the same as in [options](attr.options.html) +#[proc_macro_attribute] +pub fn options(args: TokenStream, input: TokenStream) -> TokenStream { + let args = parse_macro_input!(args as syn::AttributeArgs); + let gen = route::Args::new(&args, input, route::GuardType::Options); + gen.generate() +} + +/// Creates route handler with `TRACE` method guard. +/// +/// Syntax: `#[trace("path"[, attributes])]` +/// +/// Attributes are the same as in [trace](attr.trace.html) +#[proc_macro_attribute] +pub fn trace(args: TokenStream, input: TokenStream) -> TokenStream { + let args = parse_macro_input!(args as syn::AttributeArgs); + let gen = route::Args::new(&args, input, route::GuardType::Trace); + gen.generate() +} + +/// Creates route handler with `PATCH` method guard. +/// +/// Syntax: `#[patch("path"[, attributes])]` +/// +/// Attributes are the same as in [patch](attr.patch.html) +#[proc_macro_attribute] +pub fn patch(args: TokenStream, input: TokenStream) -> TokenStream { + let args = parse_macro_input!(args as syn::AttributeArgs); + let gen = route::Args::new(&args, input, route::GuardType::Patch); + gen.generate() +} \ No newline at end of file diff --git a/actix-web-codegen/src/route.rs b/actix-web-codegen/src/route.rs index 1a5f79298..3b890c1cb 100644 --- a/actix-web-codegen/src/route.rs +++ b/actix-web-codegen/src/route.rs @@ -25,6 +25,11 @@ pub enum GuardType { Post, Put, Delete, + Head, + Connect, + Options, + Trace, + Patch } impl fmt::Display for GuardType { @@ -34,6 +39,11 @@ impl fmt::Display for GuardType { &GuardType::Post => write!(f, "Post"), &GuardType::Put => write!(f, "Put"), &GuardType::Delete => write!(f, "Delete"), + &GuardType::Head => write!(f, "Head"), + &GuardType::Connect => write!(f, "Connect"), + &GuardType::Options => write!(f, "Options"), + &GuardType::Trace => write!(f, "Trace"), + &GuardType::Patch => write!(f, "Patch"), } } } diff --git a/actix-web-codegen/tests/test_macro.rs b/actix-web-codegen/tests/test_macro.rs index cd899d48d..718728879 100644 --- a/actix-web-codegen/tests/test_macro.rs +++ b/actix-web-codegen/tests/test_macro.rs @@ -1,7 +1,7 @@ use actix_http::HttpService; use actix_http_test::TestServer; use actix_web::{http, web::Path, App, HttpResponse, Responder}; -use actix_web_codegen::{delete, get, post, put}; +use actix_web_codegen::{delete, get, post, put, patch, head, connect, options, trace}; use futures::{future, Future}; #[get("/test")] @@ -14,11 +14,36 @@ fn put_test() -> impl Responder { HttpResponse::Created() } +#[patch("/test")] +fn patch_test() -> impl Responder { + HttpResponse::Ok() +} + #[post("/test")] fn post_test() -> impl Responder { HttpResponse::NoContent() } +#[head("/test")] +fn head_test() -> impl Responder { + HttpResponse::Ok() +} + +#[connect("/test")] +fn connect_test() -> impl Responder { + HttpResponse::Ok() +} + +#[options("/test")] +fn options_test() -> impl Responder { + HttpResponse::Ok() +} + +#[trace("/test")] +fn trace_test() -> impl Responder { + HttpResponse::Ok() +} + #[get("/test")] fn auto_async() -> impl Future { future::ok(HttpResponse::Ok().finish()) @@ -75,6 +100,11 @@ fn test_body() { App::new() .service(post_test) .service(put_test) + .service(head_test) + .service(connect_test) + .service(options_test) + .service(trace_test) + .service(patch_test) .service(test), ) }); @@ -82,6 +112,26 @@ fn test_body() { let response = srv.block_on(request.send()).unwrap(); assert!(response.status().is_success()); + let request = srv.request(http::Method::HEAD, srv.url("/test")); + let response = srv.block_on(request.send()).unwrap(); + assert!(response.status().is_success()); + + let request = srv.request(http::Method::CONNECT, srv.url("/test")); + let response = srv.block_on(request.send()).unwrap(); + assert!(response.status().is_success()); + + let request = srv.request(http::Method::OPTIONS, srv.url("/test")); + let response = srv.block_on(request.send()).unwrap(); + assert!(response.status().is_success()); + + let request = srv.request(http::Method::TRACE, srv.url("/test")); + let response = srv.block_on(request.send()).unwrap(); + assert!(response.status().is_success()); + + let request = srv.request(http::Method::PATCH, srv.url("/test")); + let response = srv.block_on(request.send()).unwrap(); + assert!(response.status().is_success()); + let request = srv.request(http::Method::PUT, srv.url("/test")); let response = srv.block_on(request.send()).unwrap(); assert!(response.status().is_success());