mirror of https://github.com/fafhrd91/actix-web
chore: changelog, docs, tests
This commit is contained in:
parent
b962959b82
commit
f73c5406cb
|
@ -1,6 +1,9 @@
|
||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2021-xx-xx
|
## Unreleased - 2022-xx-xx
|
||||||
|
- Added `#[actix_web::routes]` macro to support multiple routes on one handler
|
||||||
|
|
||||||
|
[#2718]: https://github.com/actix/actix-web/pull/2718
|
||||||
|
|
||||||
|
|
||||||
## 4.0.0 - 2022-02-24
|
## 4.0.0 - 2022-02-24
|
||||||
|
|
|
@ -46,9 +46,20 @@
|
||||||
//! ```
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! # Multiple Path Handlers
|
//! # Multiple Path Handlers
|
||||||
//! There are no macros to generate multi-path handlers. Let us know in [this issue].
|
//! Acts as a wrapper for multiple single method handler macros. It takes no arguments and
|
||||||
|
//! delegates those to the macros for the individual methods. See [macro@routes] macro docs.
|
||||||
//!
|
//!
|
||||||
//! [this issue]: https://github.com/actix/actix-web/issues/1709
|
//! ```
|
||||||
|
//! # use actix_web::HttpResponse;
|
||||||
|
//! # use actix_web_codegen::routes;
|
||||||
|
//! #[routes]
|
||||||
|
//! #[get("/test")]
|
||||||
|
//! #[get("/test2")]
|
||||||
|
//! #[delete("/test")]
|
||||||
|
//! async fn example() -> HttpResponse {
|
||||||
|
//! HttpResponse::Ok().finish()
|
||||||
|
//! }
|
||||||
|
//! ```
|
||||||
//!
|
//!
|
||||||
//! [actix-web attributes docs]: https://docs.rs/actix-web/latest/actix_web/#attributes
|
//! [actix-web attributes docs]: https://docs.rs/actix-web/latest/actix_web/#attributes
|
||||||
//! [GET]: macro@get
|
//! [GET]: macro@get
|
||||||
|
@ -104,6 +115,34 @@ pub fn route(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
route::with_method(None, args, input)
|
route::with_method(None, args, input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates resource handler, allowing multiple HTTP methods and paths.
|
||||||
|
///
|
||||||
|
/// # Syntax
|
||||||
|
/// ```plain
|
||||||
|
/// #[routes]
|
||||||
|
/// #[<method>("path", ...)]
|
||||||
|
/// #[<method>("path", ...)]
|
||||||
|
/// ...
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// # Attributes
|
||||||
|
/// The `routes` macro it self has no parameters, but allows specifying the attribute macros for
|
||||||
|
/// the different methods, e.g. [`GET`](macro@get) or [`POST`](macro@post).
|
||||||
|
///
|
||||||
|
/// These helper attributes take the same parameters as the [single method handlers](crate#single-method-handler).
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```
|
||||||
|
/// # use actix_web::HttpResponse;
|
||||||
|
/// # use actix_web_codegen::routes;
|
||||||
|
/// #[routes]
|
||||||
|
/// #[get("/test")]
|
||||||
|
/// #[get("/test2")]
|
||||||
|
/// #[delete("/test")]
|
||||||
|
/// async fn example() -> HttpResponse {
|
||||||
|
/// HttpResponse::Ok().finish()
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn routes(_: TokenStream, input: TokenStream) -> TokenStream {
|
pub fn routes(_: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
route::with_methods(input)
|
route::with_methods(input)
|
||||||
|
|
|
@ -10,7 +10,9 @@ use actix_web::{
|
||||||
},
|
},
|
||||||
web, App, Error, HttpResponse, Responder,
|
web, App, Error, HttpResponse, Responder,
|
||||||
};
|
};
|
||||||
use actix_web_codegen::{connect, delete, get, head, options, patch, post, put, route, trace};
|
use actix_web_codegen::{
|
||||||
|
connect, delete, get, head, options, patch, post, put, route, routes, trace,
|
||||||
|
};
|
||||||
use futures_core::future::LocalBoxFuture;
|
use futures_core::future::LocalBoxFuture;
|
||||||
|
|
||||||
// Make sure that we can name function as 'config'
|
// Make sure that we can name function as 'config'
|
||||||
|
@ -89,6 +91,14 @@ async fn route_test() -> impl Responder {
|
||||||
HttpResponse::Ok()
|
HttpResponse::Ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[routes]
|
||||||
|
#[get("/routes/test")]
|
||||||
|
#[get("/routes/test2")]
|
||||||
|
#[post("/routes/test")]
|
||||||
|
async fn routes_test() -> impl Responder {
|
||||||
|
HttpResponse::Ok()
|
||||||
|
}
|
||||||
|
|
||||||
#[get("/custom_resource_name", name = "custom")]
|
#[get("/custom_resource_name", name = "custom")]
|
||||||
async fn custom_resource_name_test<'a>(req: actix_web::HttpRequest) -> impl Responder {
|
async fn custom_resource_name_test<'a>(req: actix_web::HttpRequest) -> impl Responder {
|
||||||
assert!(req.url_for_static("custom").is_ok());
|
assert!(req.url_for_static("custom").is_ok());
|
||||||
|
@ -186,6 +196,7 @@ async fn test_body() {
|
||||||
.service(patch_test)
|
.service(patch_test)
|
||||||
.service(test_handler)
|
.service(test_handler)
|
||||||
.service(route_test)
|
.service(route_test)
|
||||||
|
.service(routes_test)
|
||||||
.service(custom_resource_name_test)
|
.service(custom_resource_name_test)
|
||||||
});
|
});
|
||||||
let request = srv.request(http::Method::GET, srv.url("/test"));
|
let request = srv.request(http::Method::GET, srv.url("/test"));
|
||||||
|
@ -242,6 +253,18 @@ async fn test_body() {
|
||||||
let response = request.send().await.unwrap();
|
let response = request.send().await.unwrap();
|
||||||
assert!(!response.status().is_success());
|
assert!(!response.status().is_success());
|
||||||
|
|
||||||
|
let request = srv.request(http::Method::GET, srv.url("/routes/test"));
|
||||||
|
let response = request.send().await.unwrap();
|
||||||
|
assert!(response.status().is_success());
|
||||||
|
|
||||||
|
let request = srv.request(http::Method::GET, srv.url("/routes/test2"));
|
||||||
|
let response = request.send().await.unwrap();
|
||||||
|
assert!(response.status().is_success());
|
||||||
|
|
||||||
|
let request = srv.request(http::Method::POST, srv.url("/routes/test"));
|
||||||
|
let response = request.send().await.unwrap();
|
||||||
|
assert!(response.status().is_success());
|
||||||
|
|
||||||
let request = srv.request(http::Method::GET, srv.url("/custom_resource_name"));
|
let request = srv.request(http::Method::GET, srv.url("/custom_resource_name"));
|
||||||
let response = request.send().await.unwrap();
|
let response = request.send().await.unwrap();
|
||||||
assert!(response.status().is_success());
|
assert!(response.status().is_success());
|
||||||
|
|
|
@ -12,6 +12,8 @@ fn compile_macros() {
|
||||||
t.compile_fail("tests/trybuild/route-unexpected-method-fail.rs");
|
t.compile_fail("tests/trybuild/route-unexpected-method-fail.rs");
|
||||||
t.compile_fail("tests/trybuild/route-malformed-path-fail.rs");
|
t.compile_fail("tests/trybuild/route-malformed-path-fail.rs");
|
||||||
|
|
||||||
|
t.pass("tests/trybuild/routes-ok.rs");
|
||||||
|
|
||||||
t.pass("tests/trybuild/docstring-ok.rs");
|
t.pass("tests/trybuild/docstring-ok.rs");
|
||||||
|
|
||||||
t.pass("tests/trybuild/test-runtime.rs");
|
t.pass("tests/trybuild/test-runtime.rs");
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
use actix_web_codegen::*;
|
||||||
|
|
||||||
|
#[routes]
|
||||||
|
#[get("/")]
|
||||||
|
#[post("/")]
|
||||||
|
async fn index() -> String {
|
||||||
|
"Hello World!".to_owned()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[actix_web::main]
|
||||||
|
async fn main() {
|
||||||
|
use actix_web::App;
|
||||||
|
|
||||||
|
let srv = actix_test::start(|| App::new().service(index));
|
||||||
|
|
||||||
|
let request = srv.get("/");
|
||||||
|
let response = request.send().await.unwrap();
|
||||||
|
assert!(response.status().is_success());
|
||||||
|
|
||||||
|
let request = srv.post("/");
|
||||||
|
let response = request.send().await.unwrap();
|
||||||
|
assert!(response.status().is_success());
|
||||||
|
}
|
|
@ -132,6 +132,7 @@ macro_rules! codegen_reexport {
|
||||||
codegen_reexport!(main);
|
codegen_reexport!(main);
|
||||||
codegen_reexport!(test);
|
codegen_reexport!(test);
|
||||||
codegen_reexport!(route);
|
codegen_reexport!(route);
|
||||||
|
codegen_reexport!(routes);
|
||||||
codegen_reexport!(head);
|
codegen_reexport!(head);
|
||||||
codegen_reexport!(get);
|
codegen_reexport!(get);
|
||||||
codegen_reexport!(post);
|
codegen_reexport!(post);
|
||||||
|
|
Loading…
Reference in New Issue