1
0
mirror of https://github.com/actix/actix-extras.git synced 2024-11-24 16:02:59 +01:00

App::route method

This commit is contained in:
Nikolay Kim 2018-04-06 21:18:42 -07:00
parent 7becb95a97
commit fffaf2bb2d
3 changed files with 108 additions and 17 deletions

View File

@ -17,18 +17,42 @@ A resource also has a pattern, meant to match against the *PATH* portion of a *U
It does not match against the *QUERY* portion (the portion following the scheme and It does not match against the *QUERY* portion (the portion following the scheme and
port, e.g., */foo/bar* in the *URL* *http://localhost:8080/foo/bar?q=value*). port, e.g., */foo/bar* in the *URL* *http://localhost:8080/foo/bar?q=value*).
The [App::resource](../actix_web/struct.App.html#method.resource) methods The [App::route](../actix_web/struct.App.html#method.route) method provides
add a single resource to application routing table. This method accepts a *path pattern* simple way of registering routes. This method adds a single route to application
routing table. This method accepts a *path pattern*,
*http method* and a handler function. `route()` method could be called multiple times
for the same path, in that case, multiple routes register for the same resource path.
```rust
# extern crate actix_web;
use actix_web::{App, HttpRequest, HttpResponse, http::Method};
fn index(req: HttpRequest) -> HttpResponse {
unimplemented!()
}
fn main() {
App::new()
.route("/user/{name}", Method::GET, index)
.route("/user/{name}", Method::POST, index)
.finish();
}
```
While *App::route()* provides simple way of registering routes, to access
complete resource configuration, different method has to be used.
The [App::resource](../actix_web/struct.App.html#method.resource) method
adds a single resource to application routing table. This method accepts a *path pattern*
and a resource configuration function. and a resource configuration function.
```rust ```rust
# extern crate actix_web; # extern crate actix_web;
# use actix_web::{App, HttpRequest, HttpResponse, http::Method}; use actix_web::{App, HttpRequest, HttpResponse, http::Method};
#
# fn index(req: HttpRequest) -> HttpResponse { fn index(req: HttpRequest) -> HttpResponse {
# unimplemented!() unimplemented!()
# } }
#
fn main() { fn main() {
App::new() App::new()
.resource("/prefix", |r| r.f(index)) .resource("/prefix", |r| r.f(index))

View File

@ -3,11 +3,12 @@ use std::rc::Rc;
use std::cell::UnsafeCell; use std::cell::UnsafeCell;
use std::collections::HashMap; use std::collections::HashMap;
use http::Method;
use handler::Reply; use handler::Reply;
use router::{Router, Resource}; use router::{Router, Resource};
use resource::{ResourceHandler}; use resource::{ResourceHandler};
use header::ContentEncoding; use header::ContentEncoding;
use handler::{Handler, RouteHandler, WrapHandler}; use handler::{Handler, RouteHandler, WrapHandler, FromRequest, Responder};
use httprequest::HttpRequest; use httprequest::HttpRequest;
use pipeline::{Pipeline, PipelineHandler, HandlerType}; use pipeline::{Pipeline, PipelineHandler, HandlerType};
use middleware::Middleware; use middleware::Middleware;
@ -225,6 +226,52 @@ impl<S> App<S> where S: 'static {
self self
} }
/// Configure route for specific path.
///
/// This is simplified version of `App::resource()` method.
/// Handler function needs to accept one request extractor argument.
/// This method could be called multiple times, in that case multiple routes
/// would be registered for same resource path.
///
/// ```rust
/// # extern crate actix_web;
/// use actix_web::{http, App, HttpRequest, HttpResponse};
///
/// fn main() {
/// let app = App::new()
/// .route("/test", http::Method::GET,
/// |_: HttpRequest| HttpResponse::Ok())
/// .route("/test", http::Method::POST,
/// |_: HttpRequest| HttpResponse::MethodNotAllowed());
/// }
/// ```
pub fn route<T, F, R>(mut self, path: &str, method: Method, f: F) -> App<S>
where F: Fn(T) -> R + 'static,
R: Responder + 'static,
T: FromRequest<S> + 'static,
{
{
let parts: &mut ApplicationParts<S> = unsafe{
mem::transmute(self.parts.as_mut().expect("Use after finish"))};
// get resource handler
for (pattern, handler) in &mut parts.resources {
if let Some(ref mut handler) = handler {
if pattern.pattern() == path {
handler.method(method).with(f);
return self
}
}
}
let mut handler = ResourceHandler::default();
handler.method(method).with(f);
let pattern = Resource::new(handler.get_name(), path);
parts.resources.push((pattern, Some(handler)));
}
self
}
/// Configure resource for specific path. /// Configure resource for specific path.
/// ///
/// Resource may have variable path also. For instance, a resource with /// Resource may have variable path also. For instance, a resource with
@ -261,12 +308,12 @@ impl<S> App<S> where S: 'static {
{ {
let parts = self.parts.as_mut().expect("Use after finish"); let parts = self.parts.as_mut().expect("Use after finish");
// add resource // add resource handler
let mut resource = ResourceHandler::default(); let mut handler = ResourceHandler::default();
f(&mut resource); f(&mut handler);
let pattern = Resource::new(resource.get_name(), path); let pattern = Resource::new(handler.get_name(), path);
parts.resources.push((pattern, Some(resource))); parts.resources.push((pattern, Some(handler)));
} }
self self
} }
@ -603,6 +650,26 @@ mod tests {
assert_eq!(resp.as_response().unwrap().status(), StatusCode::NOT_FOUND); assert_eq!(resp.as_response().unwrap().status(), StatusCode::NOT_FOUND);
} }
#[test]
fn test_route() {
let mut app = App::new()
.route("/test", Method::GET, |_: HttpRequest| HttpResponse::Ok())
.route("/test", Method::POST, |_: HttpRequest| HttpResponse::Created())
.finish();
let req = TestRequest::with_uri("/test").method(Method::GET).finish();
let resp = app.run(req);
assert_eq!(resp.as_response().unwrap().status(), StatusCode::OK);
let req = TestRequest::with_uri("/test").method(Method::POST).finish();
let resp = app.run(req);
assert_eq!(resp.as_response().unwrap().status(), StatusCode::CREATED);
let req = TestRequest::with_uri("/test").method(Method::HEAD).finish();
let resp = app.run(req);
assert_eq!(resp.as_response().unwrap().status(), StatusCode::NOT_FOUND);
}
#[test] #[test]
fn test_handler_prefix() { fn test_handler_prefix() {
let mut app = App::new() let mut app = App::new()

View File

@ -102,7 +102,7 @@ impl<S: 'static> Route<S> {
self.handler = InnerHandler::async(handler); self.handler = InnerHandler::async(handler);
} }
/// Set handler function with http request extractor. /// Set handler function, use request extractor for paramters.
/// ///
/// ```rust /// ```rust
/// # extern crate bytes; /// # extern crate bytes;
@ -137,7 +137,7 @@ impl<S: 'static> Route<S> {
cfg cfg
} }
/// Set handler function, function has to accept two request extractors. /// Set handler function, use request extractor for both paramters.
/// ///
/// ```rust /// ```rust
/// # extern crate bytes; /// # extern crate bytes;
@ -180,7 +180,7 @@ impl<S: 'static> Route<S> {
(cfg1, cfg2) (cfg1, cfg2)
} }
/// Set handler function, function has to accept three request extractors. /// Set handler function, use request extractor for all paramters.
pub fn with3<T1, T2, T3, F, R>(&mut self, handler: F) pub fn with3<T1, T2, T3, F, R>(&mut self, handler: F)
-> (ExtractorConfig<S, T1>, ExtractorConfig<S, T2>, ExtractorConfig<S, T3>) -> (ExtractorConfig<S, T1>, ExtractorConfig<S, T2>, ExtractorConfig<S, T3>)
where F: Fn(T1, T2, T3) -> R + 'static, where F: Fn(T1, T2, T3) -> R + 'static,