mirror of
https://github.com/fafhrd91/actix-web
synced 2025-06-25 22:49:21 +02:00
refactor and enable some tests for staticfiles
This commit is contained in:
45
src/app.rs
45
src/app.rs
@ -24,8 +24,13 @@ type HttpService<P> = BoxedService<ServiceRequest<P>, ServiceResponse, ()>;
|
||||
type HttpNewService<P> = BoxedNewService<(), ServiceRequest<P>, ServiceResponse, (), ()>;
|
||||
type BoxedResponse = Box<Future<Item = ServiceResponse, Error = ()>>;
|
||||
|
||||
pub trait HttpServiceFactory<Request> {
|
||||
type Factory: NewService<Request>;
|
||||
pub trait HttpServiceFactory<P> {
|
||||
type Factory: NewService<
|
||||
ServiceRequest<P>,
|
||||
Response = ServiceResponse,
|
||||
Error = (),
|
||||
InitError = (),
|
||||
>;
|
||||
|
||||
fn rdef(&self) -> &ResourceDef;
|
||||
|
||||
@ -293,6 +298,29 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Register resource handler service.
|
||||
pub fn service<F>(self, service: F) -> AppRouter<T, P, Body, AppEntry<P>>
|
||||
where
|
||||
F: HttpServiceFactory<P> + 'static,
|
||||
{
|
||||
let fref = Rc::new(RefCell::new(None));
|
||||
AppRouter {
|
||||
chain: self.chain,
|
||||
services: vec![(
|
||||
service.rdef().clone(),
|
||||
boxed::new_service(service.create().map_init_err(|_| ())),
|
||||
None,
|
||||
)],
|
||||
default: None,
|
||||
defaults: vec![],
|
||||
endpoint: AppEntry::new(fref.clone()),
|
||||
factory_ref: fref,
|
||||
extensions: self.extensions,
|
||||
state: self.state,
|
||||
_t: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Set server host name.
|
||||
///
|
||||
/// Host name is used by application router aa a hostname for url
|
||||
@ -445,16 +473,15 @@ where
|
||||
}
|
||||
|
||||
/// Register resource handler service.
|
||||
pub fn service<R, F, U>(mut self, rdef: R, factory: F) -> Self
|
||||
pub fn service<F>(mut self, factory: F) -> Self
|
||||
where
|
||||
R: Into<ResourceDef>,
|
||||
F: IntoNewService<U, ServiceRequest<P>>,
|
||||
U: NewService<ServiceRequest<P>, Response = ServiceResponse, Error = ()>
|
||||
+ 'static,
|
||||
F: HttpServiceFactory<P> + 'static,
|
||||
{
|
||||
let rdef = factory.rdef().clone();
|
||||
|
||||
self.services.push((
|
||||
rdef.into(),
|
||||
boxed::new_service(factory.into_new_service().map_init_err(|_| ())),
|
||||
rdef,
|
||||
boxed::new_service(factory.create().map_init_err(|_| ())),
|
||||
None,
|
||||
));
|
||||
self
|
||||
|
24
src/lib.rs
24
src/lib.rs
@ -19,9 +19,9 @@ pub mod test;
|
||||
|
||||
// re-export for convenience
|
||||
pub use actix_http::Response as HttpResponse;
|
||||
pub use actix_http::{error, http, Error, HttpMessage, ResponseError, Result};
|
||||
pub use actix_http::{body, error, http, Error, HttpMessage, ResponseError, Result};
|
||||
|
||||
pub use crate::app::{App, AppRouter};
|
||||
pub use crate::app::App;
|
||||
pub use crate::extract::{FromRequest, Json};
|
||||
pub use crate::request::HttpRequest;
|
||||
pub use crate::resource::Resource;
|
||||
@ -32,6 +32,26 @@ pub use crate::server::HttpServer;
|
||||
pub use crate::service::{ServiceFromRequest, ServiceRequest, ServiceResponse};
|
||||
pub use crate::state::State;
|
||||
|
||||
pub mod dev {
|
||||
//! The `actix-web` prelude for library developers
|
||||
//!
|
||||
//! The purpose of this module is to alleviate imports of many common actix
|
||||
//! traits by adding a glob import to the top of actix heavy modules:
|
||||
//!
|
||||
//! ```
|
||||
//! # #![allow(unused_imports)]
|
||||
//! use actix_web::dev::*;
|
||||
//! ```
|
||||
|
||||
pub use crate::app::{AppRouter, HttpServiceFactory};
|
||||
pub use actix_http::body::{Body, MessageBody, ResponseBody};
|
||||
pub use actix_http::dev::ResponseBuilder as HttpResponseBuilder;
|
||||
pub use actix_http::{
|
||||
Extensions, Payload, PayloadStream, RequestHead, ResponseHead,
|
||||
};
|
||||
pub use actix_router::{Path, ResourceDef, Url};
|
||||
}
|
||||
|
||||
pub mod web {
|
||||
use actix_http::{http::Method, Error, Response};
|
||||
use futures::IntoFuture;
|
||||
|
@ -1,8 +1,9 @@
|
||||
use std::borrow::Cow;
|
||||
use std::cell::{Ref, RefMut};
|
||||
use std::fmt;
|
||||
use std::rc::Rc;
|
||||
|
||||
use actix_http::body::{Body, ResponseBody};
|
||||
use actix_http::body::{Body, MessageBody, ResponseBody};
|
||||
use actix_http::http::{HeaderMap, Method, Uri, Version};
|
||||
use actix_http::{
|
||||
Error, Extensions, HttpMessage, Payload, PayloadStream, Request, RequestHead,
|
||||
@ -123,6 +124,11 @@ impl<P> ServiceRequest<P> {
|
||||
pub fn app_extensions(&self) -> &Extensions {
|
||||
self.req.app_extensions()
|
||||
}
|
||||
|
||||
/// Deconstruct request into parts
|
||||
pub fn into_parts(self) -> (HttpRequest, Payload<P>) {
|
||||
(self.req, self.payload)
|
||||
}
|
||||
}
|
||||
|
||||
impl<P> Resource<Url> for ServiceRequest<P> {
|
||||
@ -172,6 +178,29 @@ impl<P> std::ops::DerefMut for ServiceRequest<P> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<P> fmt::Debug for ServiceRequest<P> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
writeln!(
|
||||
f,
|
||||
"\nServiceRequest {:?} {}:{}",
|
||||
self.head().version,
|
||||
self.head().method,
|
||||
self.path()
|
||||
)?;
|
||||
if !self.query_string().is_empty() {
|
||||
writeln!(f, " query: ?{:?}", self.query_string())?;
|
||||
}
|
||||
if !self.match_info().is_empty() {
|
||||
writeln!(f, " params: {:?}", self.match_info())?;
|
||||
}
|
||||
writeln!(f, " headers:")?;
|
||||
for (key, val) in self.headers().iter() {
|
||||
writeln!(f, " {:?}: {:?}", key, val)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ServiceFromRequest<P> {
|
||||
req: HttpRequest,
|
||||
payload: Payload<P>,
|
||||
@ -259,6 +288,16 @@ impl<B> ServiceResponse<B> {
|
||||
ServiceResponse { request, response }
|
||||
}
|
||||
|
||||
/// Create service response from the error
|
||||
pub fn from_err<E: Into<Error>>(err: E, request: HttpRequest) -> Self {
|
||||
let e: Error = err.into();
|
||||
let res: Response = e.into();
|
||||
ServiceResponse {
|
||||
request,
|
||||
response: res.into_body(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get reference to original request
|
||||
#[inline]
|
||||
pub fn request(&self) -> &HttpRequest {
|
||||
@ -303,6 +342,11 @@ impl<B> ServiceResponse<B> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract response body
|
||||
pub fn take_body(&mut self) -> ResponseBody<B> {
|
||||
self.response.take_body()
|
||||
}
|
||||
}
|
||||
|
||||
impl<B> ServiceResponse<B> {
|
||||
@ -349,3 +393,21 @@ impl<B> IntoFuture for ServiceResponse<B> {
|
||||
ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: MessageBody> fmt::Debug for ServiceResponse<B> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let res = writeln!(
|
||||
f,
|
||||
"\nServiceResponse {:?} {}{}",
|
||||
self.response.head().version,
|
||||
self.response.head().status,
|
||||
self.response.head().reason.unwrap_or(""),
|
||||
);
|
||||
let _ = writeln!(f, " headers:");
|
||||
for (key, val) in self.response.head().headers.iter() {
|
||||
let _ = writeln!(f, " {:?}: {:?}", key, val);
|
||||
}
|
||||
let _ = writeln!(f, " body: {:?}", self.response.body().length());
|
||||
res
|
||||
}
|
||||
}
|
||||
|
28
src/test.rs
28
src/test.rs
@ -70,6 +70,34 @@ where
|
||||
block_on(app.into_new_service().new_service(&())).unwrap()
|
||||
}
|
||||
|
||||
/// Calls service and waits for response future completion.
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// use actix_web::{test, App, HttpResponse, http::StatusCode};
|
||||
/// use actix_service::Service;
|
||||
///
|
||||
/// fn main() {
|
||||
/// let mut app = test::init_service(
|
||||
/// App::new()
|
||||
/// .resource("/test", |r| r.to(|| HttpResponse::Ok()))
|
||||
/// );
|
||||
///
|
||||
/// // Create request object
|
||||
/// let req = test::TestRequest::with_uri("/test").to_request();
|
||||
///
|
||||
/// // Call application
|
||||
/// let resp = test::call_succ_service(&mut app, req);
|
||||
/// assert_eq!(resp.status(), StatusCode::OK);
|
||||
/// }
|
||||
/// ```
|
||||
pub fn call_success<S, R, B, E>(app: &mut S, req: R) -> S::Response
|
||||
where
|
||||
S: Service<R, Response = ServiceResponse<B>, Error = E>,
|
||||
E: std::fmt::Debug,
|
||||
{
|
||||
block_on(app.call(req)).unwrap()
|
||||
}
|
||||
|
||||
/// Test `Request` builder.
|
||||
///
|
||||
/// For unit testing, actix provides a request builder type and a simple handler runner. TestRequest implements a builder-like pattern.
|
||||
|
Reference in New Issue
Block a user