diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 093c77891..9a768a122 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -2,6 +2,8 @@ ## Unreleased - 2023-xx-xx +- Add `Resource::{get, post, etc...}` methods for more concisely adding routes that don't need additional guards. + ## 4.3.1 - 2023-02-26 - Add support for custom methods with the `#[route]` macro. [#2969] diff --git a/actix-web/src/resource.rs b/actix-web/src/resource.rs index 997036751..5d2c9706a 100644 --- a/actix-web/src/resource.rs +++ b/actix-web/src/resource.rs @@ -21,7 +21,7 @@ use crate::{ BoxedHttpService, BoxedHttpServiceFactory, HttpServiceFactory, ServiceRequest, ServiceResponse, }, - Error, FromRequest, HttpResponse, Responder, + web, Error, FromRequest, HttpResponse, Responder, }; /// A collection of [`Route`]s that respond to the same path pattern. @@ -38,11 +38,13 @@ use crate::{ /// /// let app = App::new().service( /// web::resource("/") -/// .route(web::get().to(|| HttpResponse::Ok()))); +/// .get(|| HttpResponse::Ok()) +/// .post(|| async { "Hello World!" }) +/// ); /// ``` /// -/// If no matching route is found, [a 405 response is returned with an appropriate Allow header][RFC -/// 9110 §15.5.6]. This default behavior can be overridden using +/// If no matching route is found, an empty 405 response is returned which includes an +/// [appropriate Allow header][RFC 9110 §15.5.6]. This default behavior can be overridden using /// [`default_service()`](Self::default_service). /// /// [RFC 9110 §15.5.6]: https://www.rfc-editor.org/rfc/rfc9110.html#section-15.5.6 @@ -58,6 +60,7 @@ pub struct Resource { } impl Resource { + /// Constructs new resource that matches a `path` pattern. pub fn new(path: T) -> Resource { let fref = Rc::new(RefCell::new(None)); @@ -368,6 +371,45 @@ where } } +macro_rules! route_shortcut { + ($method_fn:ident, $method_upper:literal) => { + #[doc = concat!(" Adds a ", $method_upper, " route.")] + /// + /// Use [`route`](Self::route) if you need to add additional guards. + /// + /// # Examples + /// + /// ``` + /// # use actix_web::web; + /// web::resource("/") + #[doc = concat!(" .", stringify!($method_fn), "(|| async { \"Hello World!\" })")] + /// # ; + /// ``` + pub fn $method_fn(self, handler: F) -> Self + where + F: Handler, + Args: FromRequest + 'static, + F::Output: Responder + 'static, + { + self.route(web::$method_fn().to(handler)) + } + }; +} + +/// Concise routes for well-known HTTP methods. +impl Resource +where + T: ServiceFactory, +{ + route_shortcut!(get, "GET"); + route_shortcut!(post, "POST"); + route_shortcut!(put, "PUT"); + route_shortcut!(patch, "PATCH"); + route_shortcut!(delete, "DELETE"); + route_shortcut!(head, "HEAD"); + route_shortcut!(trace, "TRACE"); +} + impl HttpServiceFactory for Resource where T: ServiceFactory<