restore web proc macros

This commit is contained in:
Nikolay Kim 2020-04-10 13:28:50 +06:00
parent 95d1b4a43d
commit c1877c2707
10 changed files with 139 additions and 147 deletions

View file

@ -6,12 +6,14 @@ members = [
"ntex-rt", "ntex-rt",
"ntex-rt-macros", "ntex-rt-macros",
"ntex-service", "ntex-service",
"ntex-macros",
] ]
#[patch.crates-io] [patch.crates-io]
#ntex = { path = "ntex" } ntex = { path = "ntex" }
#ntex-codec = { path = "ntex-codec" } ntex-codec = { path = "ntex-codec" }
#ntex-router = { path = "ntex-router" } ntex-router = { path = "ntex-router" }
#ntex-rt = { path = "ntex-rt" } ntex-rt = { path = "ntex-rt" }
#ntex-rt-macros = { path = "ntex-rt-macros" } ntex-rt-macros = { path = "ntex-rt-macros" }
#ntex-service = { path = "ntex-service" } ntex-service = { path = "ntex-service" }
ntex-macros = { path = "ntex-macros" }

View file

@ -1,5 +1,5 @@
# Changes # Changes
## [0.1.0] - 2020-xx-xx ## [0.1.0] - 2020-04-10
* Fork * Fork to ntex namespace

View file

@ -16,5 +16,5 @@ syn = { version = "^1", features = ["full", "parsing"] }
proc-macro2 = "^1" proc-macro2 = "^1"
[dev-dependencies] [dev-dependencies]
ntex = { path = "../ntex/" } ntex = "0.1.6"
futures = { version = "0.3.1" } futures = "0.3.4"

View file

@ -1,26 +1,27 @@
#![recursion_limit = "512"] #![recursion_limit = "512"]
//! web macros module //! web macros module
//! //!
//! Generators for routes and scopes //! Generators for routes
//! //!
//! ## Route //! ## Route
//! //!
//! Macros: //! Macros:
//! //!
//! - [web_get](attr.get.html) //! - [get](attr.web_get.html)
//! - [web_post](attr.post.html) //! - [post](attr.web_post.html)
//! - [web_put](attr.put.html) //! - [put](attr.web_put.html)
//! - [web_delete](attr.delete.html) //! - [delete](attr.web_delete.html)
//! - [web_head](attr.head.html) //! - [head](attr.web_head.html)
//! - [web_connect](attr.connect.html) //! - [connect](attr.web_connect.html)
//! - [web_options](attr.options.html) //! - [options](attr.web_options.html)
//! - [web_trace](attr.trace.html) //! - [trace](attr.web_trace.html)
//! - [web_patch](attr.patch.html) //! - [patch](attr.web_patch.html)
//! //!
//! ### Attributes: //! ### Attributes:
//! //!
//! - `"path"` - Raw literal string with path for which to register handle. Mandatory. //! - `"path"` - Raw literal string with path for which to register handle. Mandatory.
//! - `guard = "function_name"` - Registers function as guard using `ntex::web::guard::fn_guard` //! - `guard = "function_name"` - Registers function as guard using `ntex::web::guard::fn_guard`
//! - `error = "ErrorRenderer"` - Register handler for specified error renderer
//! //!
//! ## Notes //! ## Notes
//! //!
@ -30,11 +31,11 @@
//! ## Example: //! ## Example:
//! //!
//! ```rust //! ```rust
//! use ntex::web::{get, HttpResponse}; //! use ntex::web::{get, Error, HttpResponse};
//! use futures::{future, Future}; //! use futures::{future, Future};
//! //!
//! #[get("/test")] //! #[get("/test")]
//! async fn async_test() -> Result<HttpResponse, ntex::http::Error> { //! async fn async_test() -> Result<HttpResponse, Error> {
//! Ok(HttpResponse::Ok().finish()) //! Ok(HttpResponse::Ok().finish())
//! } //! }
//! ``` //! ```
@ -54,10 +55,11 @@ use syn::parse_macro_input;
/// ///
/// - `"path"` - Raw literal string with path for which to register handler. Mandatory. /// - `"path"` - Raw literal string with path for which to register handler. Mandatory.
/// - `guard = "function_name"` - Registers function as guard using `ntex::web::guard::fn_guard` /// - `guard = "function_name"` - Registers function as guard using `ntex::web::guard::fn_guard`
/// - `error = "ErrorRenderer"` - Register handler for different error renderer
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn web_get(args: TokenStream, input: TokenStream) -> TokenStream { pub fn web_get(args: TokenStream, input: TokenStream) -> TokenStream {
let args = parse_macro_input!(args as syn::AttributeArgs); let args = parse_macro_input!(args as syn::AttributeArgs);
let gen = match route::Route::new(args, input, route::GuardType::Get) { let gen = match route::Route::new(args, input, route::MethodType::Get) {
Ok(gen) => gen, Ok(gen) => gen,
Err(err) => return err.to_compile_error().into(), Err(err) => return err.to_compile_error().into(),
}; };
@ -72,7 +74,7 @@ pub fn web_get(args: TokenStream, input: TokenStream) -> TokenStream {
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn web_post(args: TokenStream, input: TokenStream) -> TokenStream { pub fn web_post(args: TokenStream, input: TokenStream) -> TokenStream {
let args = parse_macro_input!(args as syn::AttributeArgs); let args = parse_macro_input!(args as syn::AttributeArgs);
let gen = match route::Route::new(args, input, route::GuardType::Post) { let gen = match route::Route::new(args, input, route::MethodType::Post) {
Ok(gen) => gen, Ok(gen) => gen,
Err(err) => return err.to_compile_error().into(), Err(err) => return err.to_compile_error().into(),
}; };
@ -87,7 +89,7 @@ pub fn web_post(args: TokenStream, input: TokenStream) -> TokenStream {
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn web_put(args: TokenStream, input: TokenStream) -> TokenStream { pub fn web_put(args: TokenStream, input: TokenStream) -> TokenStream {
let args = parse_macro_input!(args as syn::AttributeArgs); let args = parse_macro_input!(args as syn::AttributeArgs);
let gen = match route::Route::new(args, input, route::GuardType::Put) { let gen = match route::Route::new(args, input, route::MethodType::Put) {
Ok(gen) => gen, Ok(gen) => gen,
Err(err) => return err.to_compile_error().into(), Err(err) => return err.to_compile_error().into(),
}; };
@ -102,7 +104,7 @@ pub fn web_put(args: TokenStream, input: TokenStream) -> TokenStream {
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn web_delete(args: TokenStream, input: TokenStream) -> TokenStream { pub fn web_delete(args: TokenStream, input: TokenStream) -> TokenStream {
let args = parse_macro_input!(args as syn::AttributeArgs); let args = parse_macro_input!(args as syn::AttributeArgs);
let gen = match route::Route::new(args, input, route::GuardType::Delete) { let gen = match route::Route::new(args, input, route::MethodType::Delete) {
Ok(gen) => gen, Ok(gen) => gen,
Err(err) => return err.to_compile_error().into(), Err(err) => return err.to_compile_error().into(),
}; };
@ -117,7 +119,7 @@ pub fn web_delete(args: TokenStream, input: TokenStream) -> TokenStream {
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn web_head(args: TokenStream, input: TokenStream) -> TokenStream { pub fn web_head(args: TokenStream, input: TokenStream) -> TokenStream {
let args = parse_macro_input!(args as syn::AttributeArgs); let args = parse_macro_input!(args as syn::AttributeArgs);
let gen = match route::Route::new(args, input, route::GuardType::Head) { let gen = match route::Route::new(args, input, route::MethodType::Head) {
Ok(gen) => gen, Ok(gen) => gen,
Err(err) => return err.to_compile_error().into(), Err(err) => return err.to_compile_error().into(),
}; };
@ -132,7 +134,7 @@ pub fn web_head(args: TokenStream, input: TokenStream) -> TokenStream {
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn web_connect(args: TokenStream, input: TokenStream) -> TokenStream { pub fn web_connect(args: TokenStream, input: TokenStream) -> TokenStream {
let args = parse_macro_input!(args as syn::AttributeArgs); let args = parse_macro_input!(args as syn::AttributeArgs);
let gen = match route::Route::new(args, input, route::GuardType::Connect) { let gen = match route::Route::new(args, input, route::MethodType::Connect) {
Ok(gen) => gen, Ok(gen) => gen,
Err(err) => return err.to_compile_error().into(), Err(err) => return err.to_compile_error().into(),
}; };
@ -147,7 +149,7 @@ pub fn web_connect(args: TokenStream, input: TokenStream) -> TokenStream {
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn web_options(args: TokenStream, input: TokenStream) -> TokenStream { pub fn web_options(args: TokenStream, input: TokenStream) -> TokenStream {
let args = parse_macro_input!(args as syn::AttributeArgs); let args = parse_macro_input!(args as syn::AttributeArgs);
let gen = match route::Route::new(args, input, route::GuardType::Options) { let gen = match route::Route::new(args, input, route::MethodType::Options) {
Ok(gen) => gen, Ok(gen) => gen,
Err(err) => return err.to_compile_error().into(), Err(err) => return err.to_compile_error().into(),
}; };
@ -162,7 +164,7 @@ pub fn web_options(args: TokenStream, input: TokenStream) -> TokenStream {
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn web_trace(args: TokenStream, input: TokenStream) -> TokenStream { pub fn web_trace(args: TokenStream, input: TokenStream) -> TokenStream {
let args = parse_macro_input!(args as syn::AttributeArgs); let args = parse_macro_input!(args as syn::AttributeArgs);
let gen = match route::Route::new(args, input, route::GuardType::Trace) { let gen = match route::Route::new(args, input, route::MethodType::Trace) {
Ok(gen) => gen, Ok(gen) => gen,
Err(err) => return err.to_compile_error().into(), Err(err) => return err.to_compile_error().into(),
}; };
@ -177,7 +179,7 @@ pub fn web_trace(args: TokenStream, input: TokenStream) -> TokenStream {
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn web_patch(args: TokenStream, input: TokenStream) -> TokenStream { pub fn web_patch(args: TokenStream, input: TokenStream) -> TokenStream {
let args = parse_macro_input!(args as syn::AttributeArgs); let args = parse_macro_input!(args as syn::AttributeArgs);
let gen = match route::Route::new(args, input, route::GuardType::Patch) { let gen = match route::Route::new(args, input, route::MethodType::Patch) {
Ok(gen) => gen, Ok(gen) => gen,
Err(err) => return err.to_compile_error().into(), Err(err) => return err.to_compile_error().into(),
}; };

View file

@ -1,10 +1,10 @@
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::{AttributeArgs, Ident, NestedMeta}; use syn::{AttributeArgs, Ident, NestedMeta, Path};
#[derive(PartialEq)] #[derive(PartialEq)]
pub enum GuardType { pub enum MethodType {
Get, Get,
Post, Post,
Put, Put,
@ -16,23 +16,23 @@ pub enum GuardType {
Patch, Patch,
} }
impl GuardType { impl MethodType {
fn as_str(&self) -> &'static str { fn as_str(&self) -> &'static str {
match self { match self {
GuardType::Get => "Get", MethodType::Get => "Get",
GuardType::Post => "Post", MethodType::Post => "Post",
GuardType::Put => "Put", MethodType::Put => "Put",
GuardType::Delete => "Delete", MethodType::Delete => "Delete",
GuardType::Head => "Head", MethodType::Head => "Head",
GuardType::Connect => "Connect", MethodType::Connect => "Connect",
GuardType::Options => "Options", MethodType::Options => "Options",
GuardType::Trace => "Trace", MethodType::Trace => "Trace",
GuardType::Patch => "Patch", MethodType::Patch => "Patch",
} }
} }
} }
impl ToTokens for GuardType { impl ToTokens for MethodType {
fn to_tokens(&self, stream: &mut TokenStream2) { fn to_tokens(&self, stream: &mut TokenStream2) {
let ident = self.as_str(); let ident = self.as_str();
let ident = Ident::new(ident, Span::call_site()); let ident = Ident::new(ident, Span::call_site());
@ -43,12 +43,14 @@ impl ToTokens for GuardType {
struct Args { struct Args {
path: syn::LitStr, path: syn::LitStr,
guards: Vec<Ident>, guards: Vec<Ident>,
error: Path,
} }
impl Args { impl Args {
fn new(args: AttributeArgs) -> syn::Result<Self> { fn new(args: AttributeArgs) -> syn::Result<Self> {
let mut path = None; let mut path = None;
let mut guards = Vec::new(); let mut guards = Vec::new();
let mut error: Option<Path> = None;
for arg in args { for arg in args {
match arg { match arg {
NestedMeta::Lit(syn::Lit::Str(lit)) => match path { NestedMeta::Lit(syn::Lit::Str(lit)) => match path {
@ -72,10 +74,19 @@ impl Args {
"Attribute guard expects literal string!", "Attribute guard expects literal string!",
)); ));
} }
} else if nv.path.is_ident("error") {
if let syn::Lit::Str(lit) = nv.lit {
error = Some(syn::parse_str(&lit.value())?);
} else {
return Err(syn::Error::new_spanned(
nv.lit,
"Attribute error expects type path!",
));
}
} else { } else {
return Err(syn::Error::new_spanned( return Err(syn::Error::new_spanned(
nv.path, nv.path,
"Unknown attribute key is specified. Allowed: guard", "Unknown attribute key is specified. Allowed: guard or error",
)); ));
} }
} }
@ -87,6 +98,8 @@ impl Args {
Ok(Args { Ok(Args {
path: path.unwrap(), path: path.unwrap(),
guards, guards,
error: error
.unwrap_or_else(|| syn::parse_str("ntex::web::DefaultError").unwrap()),
}) })
} }
} }
@ -95,21 +108,21 @@ pub struct Route {
name: syn::Ident, name: syn::Ident,
args: Args, args: Args,
ast: syn::ItemFn, ast: syn::ItemFn,
guard: GuardType, method: MethodType,
} }
impl Route { impl Route {
pub fn new( pub fn new(
args: AttributeArgs, args: AttributeArgs,
input: TokenStream, input: TokenStream,
guard: GuardType, method: MethodType,
) -> syn::Result<Self> { ) -> syn::Result<Self> {
if args.is_empty() { if args.is_empty() {
return Err(syn::Error::new( return Err(syn::Error::new(
Span::call_site(), Span::call_site(),
format!( format!(
r#"invalid server definition, expected #[{}("<some path>")]"#, r#"invalid server definition, expected #[{}("<some path>")]"#,
guard.as_str().to_ascii_lowercase() method.as_str().to_ascii_lowercase()
), ),
)); ));
} }
@ -121,64 +134,35 @@ impl Route {
name, name,
args, args,
ast, ast,
guard, method,
}) })
} }
pub fn generate(&self) -> TokenStream { pub fn generate(&self) -> TokenStream {
let name = &self.name; let name = &self.name;
let resource_name = name.to_string(); let resource_name = name.to_string();
let guard = &self.guard;
let ast = &self.ast; let ast = &self.ast;
let path = &self.args.path; let path = &self.args.path;
let extra_guards = &self.args.guards; let extra_guards = &self.args.guards;
let error = &self.args.error;
let args: Vec<_> = ast let method = &self.method;
.sig
.inputs
.iter()
.filter(|item| match item {
syn::FnArg::Receiver(_) => false,
syn::FnArg::Typed(_) => true,
})
.map(|item| match item {
syn::FnArg::Receiver(_) => panic!(),
syn::FnArg::Typed(ref pt) => pt.ty.clone(),
})
.collect();
let assert_responder: syn::Path = syn::parse_str(
format!(
"ntex::web::dev::__assert_handler{}",
if args.is_empty() {
"".to_string()
} else {
format!("{}", args.len())
}
)
.as_str(),
)
.unwrap();
let stream = quote! { let stream = quote! {
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub struct #name; pub struct #name;
impl<__E: 'static> ntex::web::dev::HttpServiceFactory<__E> for #name impl ntex::web::dev::WebServiceFactory<#error> for #name
where __E: ntex::web::error::ErrorRenderer
{ {
fn register(self, __config: &mut ntex::web::dev::AppService<__E>) { fn register(self, __config: &mut ntex::web::dev::WebServiceConfig<#error>) {
#(ntex::web::dev::__assert_extractor::<__E, #args>();)*
#ast #ast
let __resource = ntex::web::Resource::new(#path) let __resource = ntex::web::Resource::new(#path)
.name(#resource_name) .name(#resource_name)
.guard(ntex::web::guard::#guard()) .guard(ntex::web::guard::#method())
#(.guard(ntex::web::guard::fn_guard(#extra_guards)))* #(.guard(ntex::web::guard::fn_guard(#extra_guards)))*
.to(#assert_responder(#name)); .to(#name);
ntex::web::dev::HttpServiceFactory::register(__resource, __config) ntex::web::dev::WebServiceFactory::register(__resource, __config)
} }
} }
}; };

View file

@ -1,82 +1,80 @@
use futures::{future, Future}; use futures::{future, Future};
use ntex::http::{Error, Method, StatusCode}; use ntex::http::{Method, StatusCode};
use ntex::web::{test, types::Path, App, HttpResponse, Responder}; use ntex::web::{test, types::Path, App, Error, HttpResponse, HttpResponseBuilder};
use ntex_web_macros::{connect, delete, get, head, options, patch, post, put, trace}; use ntex_macros::{
web_connect, web_delete, web_get, web_head, web_options, web_patch, web_post,
web_put, web_trace,
};
// Make sure that we can name function as 'config' // Make sure that we can name function as 'config'
#[get("/config")] #[web_get("/config")]
async fn config() -> impl Responder { async fn config() -> HttpResponse {
HttpResponse::Ok() HttpResponse::Ok().finish()
} }
#[get("/test")] #[web_get("/test")]
async fn test_handler() -> impl Responder { async fn test_handler() -> HttpResponse {
HttpResponse::Ok() HttpResponse::Ok().finish()
} }
#[put("/test")] #[web_put("/test")]
async fn put_test() -> impl Responder { async fn put_test() -> HttpResponse {
HttpResponse::Created() HttpResponse::Created().finish()
} }
#[patch("/test")] #[web_patch("/test")]
async fn patch_test() -> impl Responder { async fn patch_test() -> HttpResponse {
HttpResponse::Ok() HttpResponse::Ok().finish()
} }
#[post("/test")] #[web_post("/test")]
async fn post_test() -> impl Responder { async fn post_test() -> HttpResponse {
HttpResponse::NoContent() HttpResponse::NoContent().finish()
} }
#[head("/test")] #[web_head("/test")]
async fn head_test() -> impl Responder { async fn head_test() -> HttpResponse {
HttpResponse::Ok() HttpResponse::Ok().finish()
} }
#[connect("/test")] #[web_connect("/test")]
async fn connect_test() -> impl Responder { async fn connect_test() -> HttpResponse {
HttpResponse::Ok() HttpResponse::Ok().finish()
} }
#[options("/test")] #[web_options("/test")]
async fn options_test() -> impl Responder { async fn options_test() -> HttpResponse {
HttpResponse::Ok() HttpResponse::Ok().finish()
} }
#[trace("/test")] #[web_trace("/test")]
async fn trace_test() -> impl Responder { async fn trace_test() -> HttpResponse {
HttpResponse::Ok() HttpResponse::Ok().finish()
} }
#[get("/test")] #[web_get("/test")]
fn auto_async() -> impl Future<Output = Result<HttpResponse, Error>> { fn auto_async() -> impl Future<Output = Result<HttpResponse, Error>> {
future::ok(HttpResponse::Ok().finish()) future::ok(HttpResponse::Ok().finish())
} }
#[get("/test")] #[web_put("/test/{param}")]
fn auto_sync() -> impl Future<Output = Result<HttpResponse, Error>> { async fn put_param_test(_: Path<String>) -> HttpResponseBuilder {
future::ok(HttpResponse::Ok().finish())
}
#[put("/test/{param}")]
async fn put_param_test(_: Path<String>) -> impl Responder {
HttpResponse::Created() HttpResponse::Created()
} }
#[delete("/test/{param}")] #[web_delete("/test/{param}")]
async fn delete_param_test(_: Path<String>) -> impl Responder { async fn delete_param_test(_: Path<String>) -> HttpResponseBuilder {
HttpResponse::NoContent() HttpResponse::NoContent()
} }
#[get("/test/{param}")] #[web_get("/test/{param}")]
async fn get_param_test(_: Path<String>) -> impl Responder { async fn get_param_test(_: Path<String>) -> HttpResponse {
HttpResponse::Ok() HttpResponse::Ok().finish()
} }
#[ntex::test] #[ntex::test]
async fn test_params() { async fn test_params() {
let srv = test::start(|| { let srv = test::server(|| {
App::new() App::new()
.service(get_param_test) .service(get_param_test)
.service(put_param_test) .service(put_param_test)
@ -98,7 +96,7 @@ async fn test_params() {
#[ntex::test] #[ntex::test]
async fn test_body() { async fn test_body() {
let srv = test::start(|| { let srv = test::server(|| {
App::new() App::new()
.service(post_test) .service(post_test)
.service(put_test) .service(put_test)
@ -150,7 +148,7 @@ async fn test_body() {
#[ntex::test] #[ntex::test]
async fn test_auto_async() { async fn test_auto_async() {
let srv = test::start(|| App::new().service(auto_async)); let srv = test::server(|| App::new().service(auto_async));
let request = srv.request(Method::GET, srv.url("/test")); let request = srv.request(Method::GET, srv.url("/test"));
let response = request.send().await.unwrap(); let response = request.send().await.unwrap();

View file

@ -41,6 +41,7 @@ ntex-rt = "0.1"
ntex-rt-macros = "0.1" ntex-rt-macros = "0.1"
ntex-router = "0.3.2" ntex-router = "0.3.2"
ntex-service = "0.1" ntex-service = "0.1"
ntex-macros = "0.1"
actix-threadpool = "0.3.1" actix-threadpool = "0.3.1"
base64 = "0.12" base64 = "0.12"

View file

@ -1,7 +1,7 @@
use ntex::http; use ntex::http;
use ntex::web::{self, middleware, App, HttpRequest, HttpResponse, HttpServer}; use ntex::web::{self, middleware, App, HttpRequest, HttpResponse, HttpServer};
// #[get("/resource1/{name}/index.html")] #[web::get("/resource1/{name}/index.html")]
async fn index(req: HttpRequest, name: web::types::Path<String>) -> String { async fn index(req: HttpRequest, name: web::types::Path<String>) -> String {
println!("REQ: {:?}", req); println!("REQ: {:?}", req);
format!("Hello: {}!\r\n", name) format!("Hello: {}!\r\n", name)
@ -12,7 +12,7 @@ async fn index_async(req: HttpRequest) -> &'static str {
"Hello world!\r\n" "Hello world!\r\n"
} }
// #[get("/")] #[web::get("/")]
async fn no_params() -> &'static str { async fn no_params() -> &'static str {
"Hello world!\r\n" "Hello world!\r\n"
} }
@ -24,11 +24,8 @@ async fn main() -> std::io::Result<()> {
HttpServer::new(|| { HttpServer::new(|| {
App::new() App::new()
// .wrap(middleware::Logger::default()) .wrap(middleware::Logger::default())
.service(web::resource("/resource1/{name}/index.html").to(index)) .service((index, no_params))
.service(web::resource("/").route(web::get().to(no_params)))
// .service(index)
// .service(no_params)
.service( .service(
web::resource("/resource2/index.html") web::resource("/resource2/index.html")
.wrap( .wrap(

View file

@ -1,6 +1,6 @@
use ntex::web::{self, middleware, App, Error, HttpRequest, HttpResponse, HttpServer}; use ntex::web::{self, middleware, App, Error, HttpRequest, HttpResponse, HttpServer};
// #[get("/resource1/{name}/index.html")] #[web::get("/resource1/{name}/index.html")]
async fn index(req: HttpRequest, name: web::types::Path<String>) -> String { async fn index(req: HttpRequest, name: web::types::Path<String>) -> String {
println!("REQ: {:?}", req); println!("REQ: {:?}", req);
format!("Hello: {}!\r\n", name) format!("Hello: {}!\r\n", name)
@ -11,7 +11,7 @@ async fn index_async(req: HttpRequest) -> Result<&'static str, Error> {
Ok("Hello world!\r\n") Ok("Hello world!\r\n")
} }
// #[get("/")] #[web::get("/")]
async fn no_params() -> &'static str { async fn no_params() -> &'static str {
"Hello world!\r\n" "Hello world!\r\n"
} }
@ -26,10 +26,7 @@ async fn main() -> std::io::Result<()> {
App::new() App::new()
.wrap(middleware::DefaultHeaders::new().header("X-Version", "0.2")) .wrap(middleware::DefaultHeaders::new().header("X-Version", "0.2"))
.wrap(middleware::Logger::default()) .wrap(middleware::Logger::default())
.service(web::resource("/resource1/{name}/index.html").to(index)) .service((index, no_params))
.service(web::resource("/").route(web::get().to(no_params)))
// .service(index)
// .service(no_params)
.service( .service(
web::resource("/resource2/index.html") web::resource("/resource2/index.html")
.wrap( .wrap(

View file

@ -87,6 +87,17 @@ pub mod test;
pub mod types; pub mod types;
mod util; mod util;
// re-export proc macro
pub use ntex_macros::web_connect as connect;
pub use ntex_macros::web_delete as delete;
pub use ntex_macros::web_get as get;
pub use ntex_macros::web_head as head;
pub use ntex_macros::web_options as options;
pub use ntex_macros::web_patch as patch;
pub use ntex_macros::web_post as post;
pub use ntex_macros::web_put as put;
pub use ntex_macros::web_trace as trace;
pub use crate::http::Response as HttpResponse; pub use crate::http::Response as HttpResponse;
pub use crate::http::ResponseBuilder as HttpResponseBuilder; pub use crate::http::ResponseBuilder as HttpResponseBuilder;