mirror of https://github.com/fafhrd91/actix-web
Compare commits
4 Commits
ab73c72596
...
2f4b859dab
Author | SHA1 | Date |
---|---|---|
|
2f4b859dab | |
|
bcc0bed4f5 | |
|
4fb51ad70a | |
|
828be28199 |
|
@ -245,79 +245,23 @@ pub fn test(_: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
///
|
///
|
||||||
/// Syntax: `#[scope("path")]`
|
/// Syntax: `#[scope("path")]`
|
||||||
///
|
///
|
||||||
/// Due to current limitation it cannot be applied to modules themself.
|
|
||||||
/// Instead one should create const variable that contains module code.
|
|
||||||
///
|
|
||||||
/// ## Attributes:
|
/// ## Attributes:
|
||||||
///
|
///
|
||||||
/// - `"path"` - Raw literal string with path for which to register handler. Mandatory.
|
/// - `"path"` - Raw literal string with path for which to register handler. Mandatory.
|
||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
///
|
///
|
||||||
/// scope("/test")
|
|
||||||
/// ```rust
|
/// ```rust
|
||||||
/// use actix_web_codegen::{scope};
|
/// use actix_web_codegen::{scope};
|
||||||
///
|
/// #[scope("/test")]
|
||||||
/// const mod_inner: () = {
|
/// mod scope_module {
|
||||||
/// use actix_web::{HttpResponse, HttpRequest, Responder, put, head, connect, options, trace, patch, delete, web };
|
/// use actix_web::{get, HttpResponse, Responder};
|
||||||
/// use actix_web::web::Json;
|
/// #[get("/test")]
|
||||||
///
|
/// pub async fn test() -> impl Responder {
|
||||||
/// #[actix_web::get("/test")]
|
/// // this has path /test/test
|
||||||
/// pub async fn test() -> impl Responder {
|
/// HttpResponse::Ok().finish()
|
||||||
/// mod_test2()
|
/// }
|
||||||
/// }
|
/// }
|
||||||
///
|
|
||||||
/// #[actix_web::get("/twicetest/{value}")]
|
|
||||||
/// pub async fn test_twice(value: web::Path<String>) -> impl actix_web::Responder {
|
|
||||||
/// let int_value: i32 = value.parse().unwrap_or(0);
|
|
||||||
/// let doubled = int_value * 2;
|
|
||||||
/// HttpResponse::Ok().body(format!("Twice value: {}", doubled))
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// #[actix_web::post("/test")]
|
|
||||||
/// pub async fn test_post() -> impl Responder {
|
|
||||||
/// HttpResponse::Ok().body(format!("post works"))
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// #[put("/test")]
|
|
||||||
/// pub async fn test_put() -> impl Responder {
|
|
||||||
/// HttpResponse::Ok().body(format!("put works"))
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// #[head("/test")]
|
|
||||||
/// pub async fn test_head() -> impl Responder {
|
|
||||||
/// HttpResponse::Ok().finish()
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// #[connect("/test")]
|
|
||||||
/// pub async fn test_connect() -> impl Responder {
|
|
||||||
/// HttpResponse::Ok().body("CONNECT works")
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// #[options("/test")]
|
|
||||||
/// pub async fn test_options() -> impl Responder {
|
|
||||||
/// HttpResponse::Ok().body("OPTIONS works")
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// #[trace("/test")]
|
|
||||||
/// pub async fn test_trace(req: HttpRequest) -> impl Responder {
|
|
||||||
/// HttpResponse::Ok().body(format!("TRACE works: {:?}", req))
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// #[patch("/test")]
|
|
||||||
/// pub async fn test_patch() -> impl Responder {
|
|
||||||
/// HttpResponse::Ok().body(format!("patch works"))
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// #[delete("/test")]
|
|
||||||
/// pub async fn test_delete() -> impl Responder {
|
|
||||||
/// HttpResponse::Ok().body("DELETE works")
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// pub fn mod_test2() -> impl actix_web::Responder {
|
|
||||||
/// actix_web::HttpResponse::Ok().finish()
|
|
||||||
/// }
|
|
||||||
///};
|
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
|
|
|
@ -4,8 +4,7 @@ use actix_router::ResourceDef;
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use proc_macro2::{Span, TokenStream as TokenStream2};
|
use proc_macro2::{Span, TokenStream as TokenStream2};
|
||||||
use quote::{quote, ToTokens, TokenStreamExt};
|
use quote::{quote, ToTokens, TokenStreamExt};
|
||||||
use syn::Item::Fn;
|
use syn::{punctuated::Punctuated, Ident, LitStr, Path, Token};
|
||||||
use syn::{punctuated::Punctuated, Ident, ItemFn, LitStr, Path, Token}; // todo: cleanup
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct RouteArgs {
|
pub struct RouteArgs {
|
||||||
|
@ -332,14 +331,14 @@ pub struct Route {
|
||||||
args: Vec<Args>,
|
args: Vec<Args>,
|
||||||
|
|
||||||
/// AST of the handler function being annotated.
|
/// AST of the handler function being annotated.
|
||||||
ast: ItemFn,
|
ast: syn::ItemFn,
|
||||||
|
|
||||||
/// The doc comment attributes to copy to generated struct, if any.
|
/// The doc comment attributes to copy to generated struct, if any.
|
||||||
doc_attributes: Vec<syn::Attribute>,
|
doc_attributes: Vec<syn::Attribute>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Route {
|
impl Route {
|
||||||
pub fn new(args: RouteArgs, ast: ItemFn, method: Option<MethodType>) -> syn::Result<Self> {
|
pub fn new(args: RouteArgs, ast: syn::ItemFn, method: Option<MethodType>) -> syn::Result<Self> {
|
||||||
let name = ast.sig.ident.clone();
|
let name = ast.sig.ident.clone();
|
||||||
|
|
||||||
// Try and pull out the doc comments so that we can reapply them to the generated struct.
|
// Try and pull out the doc comments so that we can reapply them to the generated struct.
|
||||||
|
@ -375,7 +374,7 @@ impl Route {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn multiple(args: Vec<Args>, ast: ItemFn) -> syn::Result<Self> {
|
fn multiple(args: Vec<Args>, ast: syn::ItemFn) -> syn::Result<Self> {
|
||||||
let name = ast.sig.ident.clone();
|
let name = ast.sig.ident.clone();
|
||||||
|
|
||||||
// Try and pull out the doc comments so that we can reapply them to the generated struct.
|
// Try and pull out the doc comments so that we can reapply them to the generated struct.
|
||||||
|
@ -484,7 +483,7 @@ pub(crate) fn with_method(
|
||||||
Err(err) => return input_and_compile_error(input, err),
|
Err(err) => return input_and_compile_error(input, err),
|
||||||
};
|
};
|
||||||
|
|
||||||
let ast = match syn::parse::<ItemFn>(input.clone()) {
|
let ast = match syn::parse::<syn::ItemFn>(input.clone()) {
|
||||||
Ok(ast) => ast,
|
Ok(ast) => ast,
|
||||||
// on parse error, make IDEs happy; see fn docs
|
// on parse error, make IDEs happy; see fn docs
|
||||||
Err(err) => return input_and_compile_error(input, err),
|
Err(err) => return input_and_compile_error(input, err),
|
||||||
|
@ -498,7 +497,7 @@ pub(crate) fn with_method(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn with_methods(input: TokenStream) -> TokenStream {
|
pub(crate) fn with_methods(input: TokenStream) -> TokenStream {
|
||||||
let mut ast = match syn::parse::<ItemFn>(input.clone()) {
|
let mut ast = match syn::parse::<syn::ItemFn>(input.clone()) {
|
||||||
Ok(ast) => ast,
|
Ok(ast) => ast,
|
||||||
// on parse error, make IDEs happy; see fn docs
|
// on parse error, make IDEs happy; see fn docs
|
||||||
Err(err) => return input_and_compile_error(input, err),
|
Err(err) => return input_and_compile_error(input, err),
|
||||||
|
@ -556,15 +555,6 @@ fn input_and_compile_error(mut item: TokenStream, err: syn::Error) -> TokenStrea
|
||||||
item
|
item
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: regular new scoped path test...
|
|
||||||
// todo: test with enums in module...
|
|
||||||
// todo: test with different namespaces...
|
|
||||||
// todo: test with multiple get/post methods...
|
|
||||||
// todo: test with doc strings in attributes...
|
|
||||||
// todo: clean up the nested tree of death, tell it about the input_and_compile_error convenience function...
|
|
||||||
// todo: add in the group functions for convenient handling of group...
|
|
||||||
// todo: see if can cleanup the Attribute with a clone plus one field change...
|
|
||||||
// todo: #[actix_web::get("/test")] the namespace is messing matching up
|
|
||||||
pub fn with_scope(args: TokenStream, input: TokenStream) -> TokenStream {
|
pub fn with_scope(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
// Attempt to parse the scope path, returning on error
|
// Attempt to parse the scope path, returning on error
|
||||||
if args.is_empty() {
|
if args.is_empty() {
|
||||||
|
@ -576,7 +566,7 @@ pub fn with_scope(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
let scope_path = syn::parse::<LitStr>(args.clone().into());
|
let scope_path = syn::parse::<LitStr>(args.clone());
|
||||||
if let Err(_err) = scope_path {
|
if let Err(_err) = scope_path {
|
||||||
return input_and_compile_error(
|
return input_and_compile_error(
|
||||||
args.clone(),
|
args.clone(),
|
||||||
|
@ -590,10 +580,10 @@ pub fn with_scope(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
// Expect macro to be for a module
|
// Expect macro to be for a module
|
||||||
match syn::parse::<syn::ItemMod>(input) {
|
match syn::parse::<syn::ItemMod>(input) {
|
||||||
Ok(mut ast) => {
|
Ok(mut ast) => {
|
||||||
// Modify the attributes of functions within the module with method with scope, if any
|
// Modify the attributes of functions with method or route(s) by adding scope argument as prefix, if any
|
||||||
if let Some((_, ref mut items)) = ast.content {
|
if let Some((_, ref mut items)) = ast.content {
|
||||||
items.iter_mut().for_each(|item| {
|
items.iter_mut().for_each(|item| {
|
||||||
if let Fn(fun) = item {
|
if let syn::Item::Fn(fun) = item {
|
||||||
fun.attrs = fun
|
fun.attrs = fun
|
||||||
.attrs
|
.attrs
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -615,19 +605,37 @@ pub fn with_scope(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn has_allowed_methods_in_scope(attr: &syn::Attribute) -> bool {
|
||||||
|
MethodType::from_path(attr.path()).is_ok()
|
||||||
|
|| attr.path().is_ident("route")
|
||||||
|
|| attr.path().is_ident("ROUTE")
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the attribute is a method type and has a route path, then modify it
|
// Check if the attribute is a method type and has a route path, then modify it
|
||||||
fn modify_attribute_with_scope(attr: &syn::Attribute, scope_path: &str) -> syn::Attribute {
|
fn modify_attribute_with_scope(attr: &syn::Attribute, scope_path: &str) -> syn::Attribute {
|
||||||
match (
|
match (attr.parse_args::<RouteArgs>(), attr.clone().meta) {
|
||||||
MethodType::from_path(attr.path()),
|
(Ok(route_args), syn::Meta::List(meta_list)) if has_allowed_methods_in_scope(attr) => {
|
||||||
attr.parse_args::<RouteArgs>(),
|
|
||||||
attr.clone().meta,
|
|
||||||
) {
|
|
||||||
(Ok(_method), Ok(route_args), syn::Meta::List(meta_list)) => {
|
|
||||||
let modified_path = format!("{}{}", scope_path, route_args.path.value());
|
let modified_path = format!("{}{}", scope_path, route_args.path.value());
|
||||||
let modified_tokens = quote! { #modified_path };
|
|
||||||
|
let options_tokens: Vec<TokenStream2> = route_args
|
||||||
|
.options
|
||||||
|
.iter()
|
||||||
|
.map(|option| {
|
||||||
|
quote! { ,#option }
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let combined_options_tokens: TokenStream2 =
|
||||||
|
options_tokens
|
||||||
|
.into_iter()
|
||||||
|
.fold(TokenStream2::new(), |mut acc, ts| {
|
||||||
|
acc.extend(std::iter::once(ts));
|
||||||
|
acc
|
||||||
|
});
|
||||||
|
|
||||||
syn::Attribute {
|
syn::Attribute {
|
||||||
meta: syn::Meta::List(syn::MetaList {
|
meta: syn::Meta::List(syn::MetaList {
|
||||||
tokens: modified_tokens,
|
tokens: quote! { #modified_path #combined_options_tokens },
|
||||||
..meta_list.clone()
|
..meta_list.clone()
|
||||||
}),
|
}),
|
||||||
..attr.clone()
|
..attr.clone()
|
||||||
|
|
|
@ -6,7 +6,6 @@ use actix_web::{
|
||||||
http::{
|
http::{
|
||||||
self,
|
self,
|
||||||
header::{HeaderName, HeaderValue},
|
header::{HeaderName, HeaderValue},
|
||||||
StatusCode,
|
|
||||||
},
|
},
|
||||||
web, App, Error, HttpRequest, HttpResponse, Responder,
|
web, App, Error, HttpRequest, HttpResponse, Responder,
|
||||||
};
|
};
|
||||||
|
@ -371,26 +370,17 @@ async fn test_auto_async() {
|
||||||
let response = request.send().await.unwrap();
|
let response = request.send().await.unwrap();
|
||||||
assert!(response.status().is_success());
|
assert!(response.status().is_success());
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
#[actix_web::test]
|
|
||||||
async fn test_wrap() {
|
|
||||||
let srv = actix_test::start(|| App::new().service(get_wrap));
|
|
||||||
|
|
||||||
let request = srv.request(http::Method::GET, srv.url("/test/wrap"));
|
|
||||||
let mut response = request.send().await.unwrap();
|
|
||||||
assert_eq!(response.status(), StatusCode::NOT_FOUND);
|
|
||||||
assert!(response.headers().contains_key("custom-header"));
|
|
||||||
let body = response.body().await.unwrap();
|
|
||||||
let body = String::from_utf8(body.to_vec()).unwrap();
|
|
||||||
assert!(body.contains("wrong number of parameters"));
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
#[scope("/test")]
|
#[scope("/test")]
|
||||||
mod scope_module {
|
mod scope_module {
|
||||||
use actix_web::{
|
use actix_web::{delete, get, post, route, routes, web, HttpResponse, Responder};
|
||||||
get, post, connect, delete, head, options, patch, put, trace, web, HttpRequest,
|
|
||||||
HttpResponse, Responder,
|
use crate::guard_module;
|
||||||
};
|
|
||||||
|
#[get("/test/guard", guard = "guard_module::guard")]
|
||||||
|
pub async fn test_guard() -> impl Responder {
|
||||||
|
HttpResponse::Ok()
|
||||||
|
}
|
||||||
|
|
||||||
#[get("/test")]
|
#[get("/test")]
|
||||||
pub async fn test() -> impl Responder {
|
pub async fn test() -> impl Responder {
|
||||||
|
@ -409,67 +399,59 @@ mod scope_module {
|
||||||
HttpResponse::Ok().body(format!("post works"))
|
HttpResponse::Ok().body(format!("post works"))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[put("/test")]
|
|
||||||
pub async fn test_put() -> impl Responder {
|
|
||||||
HttpResponse::Ok().body(format!("put works"))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[head("/test")]
|
|
||||||
pub async fn test_head() -> impl Responder {
|
|
||||||
HttpResponse::Ok().finish()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[connect("/test")]
|
|
||||||
pub async fn test_connect() -> impl Responder {
|
|
||||||
HttpResponse::Ok().body("connect works")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[options("/test")]
|
|
||||||
pub async fn test_options() -> impl Responder {
|
|
||||||
HttpResponse::Ok().body("options works")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[trace("/test")]
|
|
||||||
pub async fn test_trace(req: HttpRequest) -> impl Responder {
|
|
||||||
HttpResponse::Ok().body(format!("trace works: {:?}", req))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[patch("/test")]
|
|
||||||
pub async fn test_patch() -> impl Responder {
|
|
||||||
HttpResponse::Ok().body(format!("patch works"))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[delete("/test")]
|
#[delete("/test")]
|
||||||
pub async fn test_delete() -> impl Responder {
|
pub async fn test_delete() -> impl Responder {
|
||||||
HttpResponse::Ok().body("delete works")
|
HttpResponse::Ok().body("delete works")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mod_test2() -> impl actix_web::Responder {
|
#[route("/test", method = "PUT", method = "PATCH", method = "CUSTOM")]
|
||||||
actix_web::HttpResponse::Ok().finish()
|
pub async fn test_multiple_shared_path() -> impl Responder {
|
||||||
|
HttpResponse::Ok().finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[routes]
|
||||||
|
#[head("/test")]
|
||||||
|
#[connect("/test")]
|
||||||
|
#[options("/test")]
|
||||||
|
#[trace("/test")]
|
||||||
|
async fn test_multiple_separate_paths() -> impl Responder {
|
||||||
|
HttpResponse::Ok().finish()
|
||||||
|
}
|
||||||
|
|
||||||
|
// test calling this from other mod scope with scope attribute...
|
||||||
pub fn mod_common(message: String) -> impl actix_web::Responder {
|
pub fn mod_common(message: String) -> impl actix_web::Responder {
|
||||||
HttpResponse::Ok().body(message)
|
HttpResponse::Ok().body(message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[scope("/v1")]
|
#[scope("/v1")]
|
||||||
mod mod_inner_v1 {
|
mod mod_scope_v1 {
|
||||||
use actix_web::{get, Responder};
|
use actix_web::{get, Responder};
|
||||||
|
|
||||||
#[get("/test")]
|
#[get("/test")]
|
||||||
|
#[doc = "doc string to check in cargo expand"]
|
||||||
pub async fn test() -> impl Responder {
|
pub async fn test() -> impl Responder {
|
||||||
super::scope_module::mod_common("version1 works".to_string())
|
super::scope_module::mod_common("version1 works".to_string())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[scope("/v2")]
|
#[scope("/v2")]
|
||||||
mod mod_inner_v2 {
|
mod mod_scope_v2 {
|
||||||
use actix_web::{get, Responder};
|
use actix_web::{get, Responder};
|
||||||
|
|
||||||
|
// check to make sure non-function tokens in the scope block are preserved...
|
||||||
|
enum TestEnum {
|
||||||
|
Works,
|
||||||
|
}
|
||||||
|
|
||||||
#[get("/test")]
|
#[get("/test")]
|
||||||
pub async fn test() -> impl Responder {
|
pub async fn test() -> impl Responder {
|
||||||
super::scope_module::mod_common("version2 works".to_string())
|
// make sure this type still exists...
|
||||||
|
let test_enum = TestEnum::Works;
|
||||||
|
|
||||||
|
match test_enum {
|
||||||
|
TestEnum::Works => super::scope_module::mod_common("version2 works".to_string()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,67 +487,37 @@ async fn test_scope_post_async() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn test_scope_put_async() {
|
async fn test_multiple_shared_path_async() {
|
||||||
let srv = actix_test::start(|| App::new().service(scope_module::test_put));
|
let srv = actix_test::start(|| App::new().service(scope_module::test_multiple_shared_path));
|
||||||
|
|
||||||
let request = srv.request(http::Method::PUT, srv.url("/test/test"));
|
let request = srv.request(http::Method::PUT, srv.url("/test/test"));
|
||||||
let mut response = request.send().await.unwrap();
|
let response = request.send().await.unwrap();
|
||||||
let body = response.body().await.unwrap();
|
assert!(response.status().is_success());
|
||||||
let body_str = String::from_utf8(body.to_vec()).unwrap();
|
|
||||||
assert_eq!(body_str, "put works");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[actix_rt::test]
|
let request = srv.request(http::Method::PATCH, srv.url("/test/test"));
|
||||||
async fn test_scope_head_async() {
|
|
||||||
let srv = actix_test::start(|| App::new().service(scope_module::test_head));
|
|
||||||
|
|
||||||
let request = srv.request(http::Method::HEAD, srv.url("/test/test"));
|
|
||||||
let response = request.send().await.unwrap();
|
let response = request.send().await.unwrap();
|
||||||
assert!(response.status().is_success());
|
assert!(response.status().is_success());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn test_scope_connect_async() {
|
async fn test_multiple_multipaths_async() {
|
||||||
let srv = actix_test::start(|| App::new().service(scope_module::test_connect));
|
let srv = actix_test::start(|| App::new().service(scope_module::test_multiple_separate_paths));
|
||||||
|
|
||||||
let request = srv.request(http::Method::CONNECT, srv.url("/test/test"));
|
let request = srv.request(http::Method::CONNECT, srv.url("/test/test"));
|
||||||
let mut response = request.send().await.unwrap();
|
let response = request.send().await.unwrap();
|
||||||
let body = response.body().await.unwrap();
|
assert!(response.status().is_success());
|
||||||
let body_str = String::from_utf8(body.to_vec()).unwrap();
|
|
||||||
assert_eq!(body_str, "connect works");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[actix_rt::test]
|
|
||||||
async fn test_scope_options_async() {
|
|
||||||
let srv = actix_test::start(|| App::new().service(scope_module::test_options));
|
|
||||||
|
|
||||||
let request = srv.request(http::Method::OPTIONS, srv.url("/test/test"));
|
let request = srv.request(http::Method::OPTIONS, srv.url("/test/test"));
|
||||||
let mut response = request.send().await.unwrap();
|
let response = request.send().await.unwrap();
|
||||||
let body = response.body().await.unwrap();
|
assert!(response.status().is_success());
|
||||||
let body_str = String::from_utf8(body.to_vec()).unwrap();
|
|
||||||
assert_eq!(body_str, "options works");
|
|
||||||
}
|
|
||||||
|
|
||||||
#[actix_rt::test]
|
|
||||||
async fn test_scope_trace_async() {
|
|
||||||
let srv = actix_test::start(|| App::new().service(scope_module::test_trace));
|
|
||||||
|
|
||||||
let request = srv.request(http::Method::TRACE, srv.url("/test/test"));
|
let request = srv.request(http::Method::TRACE, srv.url("/test/test"));
|
||||||
let mut response = request.send().await.unwrap();
|
let response = request.send().await.unwrap();
|
||||||
let body = response.body().await.unwrap();
|
assert!(response.status().is_success());
|
||||||
let body_str = String::from_utf8(body.to_vec()).unwrap();
|
|
||||||
assert!(body_str.contains("trace works"));
|
|
||||||
}
|
|
||||||
|
|
||||||
#[actix_rt::test]
|
let request = srv.request(http::Method::HEAD, srv.url("/test/test"));
|
||||||
async fn test_scope_patch_async() {
|
let response = request.send().await.unwrap();
|
||||||
let srv = actix_test::start(|| App::new().service(scope_module::test_patch));
|
assert!(response.status().is_success());
|
||||||
|
|
||||||
let request = srv.request(http::Method::PATCH, srv.url("/test/test"));
|
|
||||||
let mut response = request.send().await.unwrap();
|
|
||||||
let body = response.body().await.unwrap();
|
|
||||||
let body_str = String::from_utf8(body.to_vec()).unwrap();
|
|
||||||
assert_eq!(body_str, "patch works");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
|
@ -579,9 +531,24 @@ async fn test_scope_delete_async() {
|
||||||
assert_eq!(body_str, "delete works");
|
assert_eq!(body_str, "delete works");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn test_scope_get_with_guard_async() {
|
||||||
|
let srv = actix_test::start(|| App::new().service(scope_module::test_guard));
|
||||||
|
|
||||||
|
let request = srv
|
||||||
|
.request(http::Method::GET, srv.url("/test/test/guard"))
|
||||||
|
.insert_header(("Accept", "image/*"));
|
||||||
|
let response = request.send().await.unwrap();
|
||||||
|
assert!(response.status().is_success());
|
||||||
|
}
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn test_scope_v1_v2_async() {
|
async fn test_scope_v1_v2_async() {
|
||||||
let srv = actix_test::start(|| App::new().service(mod_inner_v1::test).service(mod_inner_v2::test));
|
let srv = actix_test::start(|| {
|
||||||
|
App::new()
|
||||||
|
.service(mod_scope_v1::test)
|
||||||
|
.service(mod_scope_v2::test)
|
||||||
|
});
|
||||||
|
|
||||||
let request = srv.request(http::Method::GET, srv.url("/v1/test"));
|
let request = srv.request(http::Method::GET, srv.url("/v1/test"));
|
||||||
let mut response = request.send().await.unwrap();
|
let mut response = request.send().await.unwrap();
|
||||||
|
|
Loading…
Reference in New Issue