mirror of https://github.com/fafhrd91/actix-web
Add `ServiceConfig::default_service`
The `App` struct supports a "default" service which will be called when there are no other matching services available. I propose that we support adding this default service from the `ServiceConfig` struct, which will enable it to be used from `App::configure`. Currently if you want to test a default service (if you're creating a proxy for example) you must re-specify this default service each time you construct your app. This change will allow users to put their default services into the shared `App::configure` helper.
This commit is contained in:
parent
293c52c3ef
commit
75c3968e66
|
@ -205,6 +205,10 @@ where
|
||||||
self.services.extend(cfg.services);
|
self.services.extend(cfg.services);
|
||||||
self.external.extend(cfg.external);
|
self.external.extend(cfg.external);
|
||||||
self.extensions.extend(cfg.app_data);
|
self.extensions.extend(cfg.app_data);
|
||||||
|
if let Some(default) = cfg.default {
|
||||||
|
self.default = Some(default);
|
||||||
|
}
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::rc::Rc;
|
||||||
|
|
||||||
use actix_http::Extensions;
|
use actix_http::Extensions;
|
||||||
use actix_router::ResourceDef;
|
use actix_router::ResourceDef;
|
||||||
use actix_service::{boxed, IntoServiceFactory, ServiceFactory};
|
use actix_service::{boxed, IntoServiceFactory, ServiceFactory, ServiceFactoryExt};
|
||||||
|
|
||||||
use crate::data::Data;
|
use crate::data::Data;
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
|
@ -185,6 +185,7 @@ pub struct ServiceConfig {
|
||||||
pub(crate) services: Vec<Box<dyn AppServiceFactory>>,
|
pub(crate) services: Vec<Box<dyn AppServiceFactory>>,
|
||||||
pub(crate) external: Vec<ResourceDef>,
|
pub(crate) external: Vec<ResourceDef>,
|
||||||
pub(crate) app_data: Extensions,
|
pub(crate) app_data: Extensions,
|
||||||
|
pub(crate) default: Option<Rc<HttpNewService>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServiceConfig {
|
impl ServiceConfig {
|
||||||
|
@ -193,6 +194,7 @@ impl ServiceConfig {
|
||||||
services: Vec::new(),
|
services: Vec::new(),
|
||||||
external: Vec::new(),
|
external: Vec::new(),
|
||||||
app_data: Extensions::new(),
|
app_data: Extensions::new(),
|
||||||
|
default: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,6 +215,28 @@ impl ServiceConfig {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Default service to be used if no matching resource could be found.
|
||||||
|
///
|
||||||
|
/// Counterpart to [`App::default_service()`](crate::App::default_service).
|
||||||
|
pub fn default_service<F, U>(&mut self, f: F) -> &mut Self
|
||||||
|
where
|
||||||
|
F: IntoServiceFactory<U, ServiceRequest>,
|
||||||
|
U: ServiceFactory<
|
||||||
|
ServiceRequest,
|
||||||
|
Config = (),
|
||||||
|
Response = ServiceResponse,
|
||||||
|
Error = Error,
|
||||||
|
> + 'static,
|
||||||
|
U::InitError: std::fmt::Debug,
|
||||||
|
{
|
||||||
|
// create and configure default resource
|
||||||
|
self.default = Some(Rc::new(boxed::factory(f.into_factory().map_init_err(
|
||||||
|
|e| log::error!("Can not construct default service: {:?}", e),
|
||||||
|
))));
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Configure route for a specific path.
|
/// Configure route for a specific path.
|
||||||
///
|
///
|
||||||
/// Counterpart to [`App::route()`](crate::App::route).
|
/// Counterpart to [`App::route()`](crate::App::route).
|
||||||
|
@ -341,6 +365,21 @@ mod tests {
|
||||||
assert_eq!(body, Bytes::from_static(b"https://youtube.com/watch/12345"));
|
assert_eq!(body, Bytes::from_static(b"https://youtube.com/watch/12345"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[actix_rt::test]
|
||||||
|
async fn test_default_service() {
|
||||||
|
let srv = init_service(App::new().configure(|cfg| {
|
||||||
|
cfg.default_service(
|
||||||
|
web::get().to(|| HttpResponse::NotFound().body("four oh four")),
|
||||||
|
);
|
||||||
|
}))
|
||||||
|
.await;
|
||||||
|
let req = TestRequest::with_uri("/path/i/did/not-configure").to_request();
|
||||||
|
let resp = call_service(&srv, req).await;
|
||||||
|
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
|
||||||
|
let body = read_body(resp).await;
|
||||||
|
assert_eq!(body, Bytes::from_static(b"four oh four"));
|
||||||
|
}
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn test_service() {
|
async fn test_service() {
|
||||||
let srv = init_service(App::new().configure(|cfg| {
|
let srv = init_service(App::new().configure(|cfg| {
|
||||||
|
|
Loading…
Reference in New Issue