mirror of
https://github.com/actix/actix-extras.git
synced 2025-06-25 09:59:21 +02:00
simplify Application creation; update url dispatch guide section
This commit is contained in:
@ -69,13 +69,11 @@ impl Application<()> {
|
||||
|
||||
/// Create application with empty state. Application can
|
||||
/// be configured with builder-like pattern.
|
||||
///
|
||||
/// This method accepts path prefix for which it should serve requests.
|
||||
pub fn new<T: Into<String>>(prefix: T) -> Application<()> {
|
||||
pub fn new() -> Application<()> {
|
||||
Application {
|
||||
parts: Some(ApplicationParts {
|
||||
state: (),
|
||||
prefix: prefix.into(),
|
||||
prefix: "/".to_owned(),
|
||||
default: Resource::default_not_found(),
|
||||
resources: HashMap::new(),
|
||||
external: HashMap::new(),
|
||||
@ -85,6 +83,12 @@ impl Application<()> {
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Application<()> {
|
||||
fn default() -> Self {
|
||||
Application::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> Application<S> where S: 'static {
|
||||
|
||||
/// Create application with specific state. Application can be
|
||||
@ -92,11 +96,11 @@ impl<S> Application<S> where S: 'static {
|
||||
///
|
||||
/// State is shared with all reousrces within same application and could be
|
||||
/// accessed with `HttpRequest::state()` method.
|
||||
pub fn with_state<T: Into<String>>(prefix: T, state: S) -> Application<S> {
|
||||
pub fn with_state(state: S) -> Application<S> {
|
||||
Application {
|
||||
parts: Some(ApplicationParts {
|
||||
state: state,
|
||||
prefix: prefix.into(),
|
||||
prefix: "/".to_owned(),
|
||||
default: Resource::default_not_found(),
|
||||
resources: HashMap::new(),
|
||||
external: HashMap::new(),
|
||||
@ -105,6 +109,42 @@ impl<S> Application<S> where S: 'static {
|
||||
}
|
||||
}
|
||||
|
||||
/// Set application prefix.
|
||||
///
|
||||
/// Only requests that matches application's prefix get processed by this application.
|
||||
/// Application prefix always contains laading "/" slash. If supplied prefix
|
||||
/// does not contain leading slash, it get inserted.
|
||||
///
|
||||
/// Inthe following example only requests with "/app/" path prefix
|
||||
/// get handled. Request with path "/app/test/" will be handled,
|
||||
/// but request with path "/other/..." will return *NOT FOUND*
|
||||
///
|
||||
/// ```rust
|
||||
/// # extern crate actix_web;
|
||||
/// use actix_web::*;
|
||||
///
|
||||
/// fn main() {
|
||||
/// let app = Application::new()
|
||||
/// .prefix("/app")
|
||||
/// .resource("/test", |r| {
|
||||
/// r.method(Method::GET).f(|_| httpcodes::HTTPOk);
|
||||
/// r.method(Method::HEAD).f(|_| httpcodes::HTTPMethodNotAllowed);
|
||||
/// })
|
||||
/// .finish();
|
||||
/// }
|
||||
/// ```
|
||||
pub fn prefix<P: Into<String>>(&mut self, prefix: P) -> &mut Self {
|
||||
{
|
||||
let parts = self.parts.as_mut().expect("Use after finish");
|
||||
let mut prefix = prefix.into();
|
||||
if !prefix.starts_with('/') {
|
||||
prefix.insert(0, '/')
|
||||
}
|
||||
parts.prefix = prefix;
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Configure resource for specific path.
|
||||
///
|
||||
/// Resource may have variable path also. For instance, a resource with
|
||||
@ -128,7 +168,7 @@ impl<S> Application<S> where S: 'static {
|
||||
/// use actix_web::*;
|
||||
///
|
||||
/// fn main() {
|
||||
/// let app = Application::new("/")
|
||||
/// let app = Application::new()
|
||||
/// .resource("/test", |r| {
|
||||
/// r.method(Method::GET).f(|_| httpcodes::HTTPOk);
|
||||
/// r.method(Method::HEAD).f(|_| httpcodes::HTTPMethodNotAllowed);
|
||||
@ -184,7 +224,7 @@ impl<S> Application<S> where S: 'static {
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// let app = Application::new("/")
|
||||
/// let app = Application::new()
|
||||
/// .resource("/index.html", |r| r.f(index))
|
||||
/// .external_resource("youtube", "https://youtube.com/watch/{video_id}")
|
||||
/// .finish();
|
||||
@ -275,7 +315,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_default_resource() {
|
||||
let app = Application::new("/")
|
||||
let app = Application::new()
|
||||
.resource("/test", |r| r.h(httpcodes::HTTPOk))
|
||||
.finish();
|
||||
|
||||
@ -291,7 +331,7 @@ mod tests {
|
||||
let resp = app.run(req);
|
||||
assert_eq!(resp.as_response().unwrap().status(), StatusCode::NOT_FOUND);
|
||||
|
||||
let app = Application::new("/")
|
||||
let app = Application::new()
|
||||
.default_resource(|r| r.h(httpcodes::HTTPMethodNotAllowed))
|
||||
.finish();
|
||||
let req = HttpRequest::new(
|
||||
@ -303,7 +343,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_unhandled_prefix() {
|
||||
let app = Application::new("/test")
|
||||
let app = Application::new()
|
||||
.prefix("/test")
|
||||
.resource("/test", |r| r.h(httpcodes::HTTPOk))
|
||||
.finish();
|
||||
assert!(app.handle(HttpRequest::default()).is_err());
|
||||
@ -311,7 +352,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_state() {
|
||||
let app = Application::with_state("/", 10)
|
||||
let app = Application::with_state(10)
|
||||
.resource("/", |r| r.h(httpcodes::HTTPOk))
|
||||
.finish();
|
||||
let req = HttpRequest::default().with_state(Rc::clone(&app.state), app.router.clone());
|
||||
|
@ -199,7 +199,7 @@ impl FromRequest for FilesystemElement {
|
||||
/// use actix_web::{fs, Application};
|
||||
///
|
||||
/// fn main() {
|
||||
/// let app = Application::new("/")
|
||||
/// let app = Application::new()
|
||||
/// .resource("/static/{tail:.*}", |r| r.h(fs::StaticFiles::new("tail", ".", true)))
|
||||
/// .finish();
|
||||
/// }
|
||||
|
@ -303,7 +303,7 @@ impl<T: Serialize> FromRequest for Json<T> {
|
||||
/// # httpcodes::HTTPOk
|
||||
/// # }
|
||||
/// fn main() {
|
||||
/// let app = Application::new("/")
|
||||
/// let app = Application::new()
|
||||
/// .resource("/test/", |r| r.f(index))
|
||||
/// .default_resource(|r| r.h(NormalizePath::default()))
|
||||
/// .finish();
|
||||
@ -412,7 +412,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_normalize_path_trailing_slashes() {
|
||||
let app = Application::new("/")
|
||||
let app = Application::new()
|
||||
.resource("/resource1", |r| r.method(Method::GET).f(index))
|
||||
.resource("/resource2/", |r| r.method(Method::GET).f(index))
|
||||
.default_resource(|r| r.h(NormalizePath::default()))
|
||||
@ -444,7 +444,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_normalize_path_trailing_slashes_disabled() {
|
||||
let app = Application::new("/")
|
||||
let app = Application::new()
|
||||
.resource("/resource1", |r| r.method(Method::GET).f(index))
|
||||
.resource("/resource2/", |r| r.method(Method::GET).f(index))
|
||||
.default_resource(|r| r.h(
|
||||
@ -471,7 +471,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_normalize_path_merge_slashes() {
|
||||
let app = Application::new("/")
|
||||
let app = Application::new()
|
||||
.resource("/resource1", |r| r.method(Method::GET).f(index))
|
||||
.resource("/resource1/a/b", |r| r.method(Method::GET).f(index))
|
||||
.default_resource(|r| r.h(NormalizePath::default()))
|
||||
@ -507,7 +507,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_normalize_path_merge_and_append_slashes() {
|
||||
let app = Application::new("/")
|
||||
let app = Application::new()
|
||||
.resource("/resource1", |r| r.method(Method::GET).f(index))
|
||||
.resource("/resource2/", |r| r.method(Method::GET).f(index))
|
||||
.resource("/resource1/a/b", |r| r.method(Method::GET).f(index))
|
||||
|
@ -21,6 +21,7 @@ pub struct ConnectionInfo<'a> {
|
||||
impl<'a> ConnectionInfo<'a> {
|
||||
|
||||
/// Create *ConnectionInfo* instance for a request.
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(cyclomatic_complexity))]
|
||||
pub fn new<S>(req: &'a HttpRequest<S>) -> ConnectionInfo<'a> {
|
||||
let mut host = None;
|
||||
let mut scheme = None;
|
||||
|
@ -15,7 +15,7 @@ use middlewares::{Response, Middleware};
|
||||
/// use actix_web::*;
|
||||
///
|
||||
/// fn main() {
|
||||
/// let app = Application::new("/")
|
||||
/// let app = Application::new()
|
||||
/// .middleware(
|
||||
/// middlewares::DefaultHeaders::build()
|
||||
/// .header("X-Version", "0.2")
|
||||
|
@ -27,7 +27,7 @@ use middlewares::{Middleware, Started, Finished};
|
||||
/// use actix_web::middlewares::Logger;
|
||||
///
|
||||
/// fn main() {
|
||||
/// let app = Application::new("/")
|
||||
/// let app = Application::new()
|
||||
/// .middleware(Logger::default())
|
||||
/// .middleware(Logger::new("%a %{User-Agent}i"))
|
||||
/// .finish();
|
||||
|
@ -170,7 +170,7 @@ mod tests {
|
||||
let pred = Header("transfer-encoding", "other");
|
||||
assert!(!pred.check(&mut req));
|
||||
|
||||
let pred = Header("content-tye", "other");
|
||||
let pred = Header("content-type", "other");
|
||||
assert!(!pred.check(&mut req));
|
||||
}
|
||||
|
||||
|
@ -2,8 +2,9 @@ use std::marker::PhantomData;
|
||||
|
||||
use http::Method;
|
||||
|
||||
use pred;
|
||||
use route::Route;
|
||||
use handler::{Reply, Handler, FromRequest, RouteHandler, WrapHandler};
|
||||
use handler::{Reply, Handler, FromRequest, RouteHandler};
|
||||
use httpcodes::HTTPNotFound;
|
||||
use httprequest::HttpRequest;
|
||||
|
||||
@ -22,7 +23,7 @@ use httprequest::HttpRequest;
|
||||
/// use actix_web::*;
|
||||
///
|
||||
/// fn main() {
|
||||
/// let app = Application::new("/")
|
||||
/// let app = Application::new()
|
||||
/// .resource(
|
||||
/// "/", |r| r.method(Method::GET).f(|r| HttpResponse::Ok()))
|
||||
/// .finish();
|
||||
@ -31,7 +32,6 @@ pub struct Resource<S=()> {
|
||||
name: String,
|
||||
state: PhantomData<S>,
|
||||
routes: Vec<Route<S>>,
|
||||
default: Box<RouteHandler<S>>,
|
||||
}
|
||||
|
||||
impl<S> Default for Resource<S> {
|
||||
@ -39,8 +39,7 @@ impl<S> Default for Resource<S> {
|
||||
Resource {
|
||||
name: String::new(),
|
||||
state: PhantomData,
|
||||
routes: Vec::new(),
|
||||
default: Box::new(HTTPNotFound)}
|
||||
routes: Vec::new() }
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,8 +49,7 @@ impl<S> Resource<S> {
|
||||
Resource {
|
||||
name: String::new(),
|
||||
state: PhantomData,
|
||||
routes: Vec::new(),
|
||||
default: Box::new(HTTPNotFound)}
|
||||
routes: Vec::new() }
|
||||
}
|
||||
|
||||
/// Set resource name
|
||||
@ -74,7 +72,7 @@ impl<S: 'static> Resource<S> {
|
||||
/// use actix_web::*;
|
||||
///
|
||||
/// fn main() {
|
||||
/// let app = Application::new("/")
|
||||
/// let app = Application::new()
|
||||
/// .resource(
|
||||
/// "/", |r| r.route()
|
||||
/// .p(pred::Any(vec![pred::Get(), pred::Put()]))
|
||||
@ -97,7 +95,7 @@ impl<S: 'static> Resource<S> {
|
||||
/// ```
|
||||
pub fn method(&mut self, method: Method) -> &mut Route<S> {
|
||||
self.routes.push(Route::default());
|
||||
self.routes.last_mut().unwrap().method(method)
|
||||
self.routes.last_mut().unwrap().p(pred::Method(method))
|
||||
}
|
||||
|
||||
/// Register a new route and add handler object.
|
||||
@ -126,12 +124,6 @@ impl<S: 'static> Resource<S> {
|
||||
self.routes.push(Route::default());
|
||||
self.routes.last_mut().unwrap().f(handler)
|
||||
}
|
||||
|
||||
/// Default handler is used if no matched route found.
|
||||
/// By default `HTTPNotFound` is used.
|
||||
pub fn default_handler<H>(&mut self, handler: H) where H: Handler<S> {
|
||||
self.default = Box::new(WrapHandler::new(handler));
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: 'static> RouteHandler<S> for Resource<S> {
|
||||
@ -142,6 +134,6 @@ impl<S: 'static> RouteHandler<S> for Resource<S> {
|
||||
return route.handle(req)
|
||||
}
|
||||
}
|
||||
self.default.handle(req)
|
||||
Reply::response(HTTPNotFound)
|
||||
}
|
||||
}
|
||||
|
17
src/route.rs
17
src/route.rs
@ -1,8 +1,7 @@
|
||||
use http::Method;
|
||||
use futures::Future;
|
||||
|
||||
use error::Error;
|
||||
use pred::{self, Predicate};
|
||||
use pred::Predicate;
|
||||
use handler::{Reply, Handler, FromRequest, RouteHandler, AsyncHandler, WrapHandler};
|
||||
use httpcodes::HTTPNotFound;
|
||||
use httprequest::HttpRequest;
|
||||
@ -43,20 +42,6 @@ impl<S: 'static> Route<S> {
|
||||
self.handler.handle(req)
|
||||
}
|
||||
|
||||
/// Add method check to route. This method could be called multiple times.
|
||||
pub fn method(&mut self, method: Method) -> &mut Self {
|
||||
self.preds.push(pred::Method(method));
|
||||
self
|
||||
}
|
||||
|
||||
/// Add predicates to route.
|
||||
pub fn predicates<P>(&mut self, preds: P) -> &mut Self
|
||||
where P: IntoIterator<Item=Box<Predicate<S>>>
|
||||
{
|
||||
self.preds.extend(preds.into_iter());
|
||||
self
|
||||
}
|
||||
|
||||
/// Add match predicate to route.
|
||||
pub fn p(&mut self, p: Box<Predicate<S>>) -> &mut Self {
|
||||
self.preds.push(p);
|
||||
|
Reference in New Issue
Block a user