1
0
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:
Nikolay Kim
2019-03-05 22:10:08 -08:00
parent 1a80b70868
commit 6efc3438b8
18 changed files with 2198 additions and 2063 deletions

View File

@ -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

View File

@ -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;

View File

@ -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
}
}

View File

@ -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.