use std::cell::{Ref, RefMut}; use std::fmt; use std::marker::PhantomData; use std::rc::Rc; 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, Response, ResponseHead, }; use actix_router::{Path, Resource, Url}; use futures::future::{ok, FutureResult, IntoFuture}; use crate::config::{AppConfig, ServiceConfig}; use crate::data::RouteData; use crate::request::HttpRequest; use crate::rmap::ResourceMap; pub trait HttpServiceFactory

{ fn register(self, config: &mut ServiceConfig

); } pub(crate) trait ServiceFactory

{ fn register(&mut self, config: &mut ServiceConfig

); } pub(crate) struct ServiceFactoryWrapper { factory: Option, _t: PhantomData

, } impl ServiceFactoryWrapper { pub fn new(factory: T) -> Self { Self { factory: Some(factory), _t: PhantomData, } } } impl ServiceFactory

for ServiceFactoryWrapper where T: HttpServiceFactory

, { fn register(&mut self, config: &mut ServiceConfig

) { if let Some(item) = self.factory.take() { item.register(config) } } } pub struct ServiceRequest

{ req: HttpRequest, payload: Payload

, } impl

ServiceRequest

{ pub(crate) fn new( path: Path, request: Request

, rmap: Rc, config: AppConfig, ) -> Self { let (head, payload) = request.into_parts(); ServiceRequest { payload, req: HttpRequest::new(head, path, rmap, config), } } /// Construct service request from parts pub fn from_parts(req: HttpRequest, payload: Payload

) -> Self { ServiceRequest { req, payload } } /// Deconstruct request into parts pub fn into_parts(self) -> (HttpRequest, Payload

) { (self.req, self.payload) } /// Create service response #[inline] pub fn into_response(self, res: Response) -> ServiceResponse { ServiceResponse::new(self.req, res) } /// Create service response for error #[inline] pub fn error_response>(self, err: E) -> ServiceResponse { let res: Response = err.into().into(); ServiceResponse::new(self.req, res.into_body()) } /// This method returns reference to the request head #[inline] pub fn head(&self) -> &RequestHead { &self.req.head } /// This method returns reference to the request head #[inline] pub fn head_mut(&mut self) -> &mut RequestHead { &mut self.req.head } /// Request's uri. #[inline] pub fn uri(&self) -> &Uri { &self.head().uri } /// Read the Request method. #[inline] pub fn method(&self) -> &Method { &self.head().method } /// Read the Request Version. #[inline] pub fn version(&self) -> Version { self.head().version } #[inline] /// Returns mutable Request's headers. pub fn headers_mut(&mut self) -> &mut HeaderMap { &mut self.head_mut().headers } /// The target path of this Request. #[inline] pub fn path(&self) -> &str { self.head().uri.path() } /// The query string in the URL. /// /// E.g., id=10 #[inline] pub fn query_string(&self) -> &str { if let Some(query) = self.uri().query().as_ref() { query } else { "" } } /// Get a reference to the Path parameters. /// /// Params is a container for url parameters. /// A variable segment is specified in the form `{identifier}`, /// where the identifier can be used later in a request handler to /// access the matched value for that segment. #[inline] pub fn match_info(&self) -> &Path { &self.req.path } #[inline] pub fn match_info_mut(&mut self) -> &mut Path { &mut self.req.path } /// Service configuration #[inline] pub fn app_config(&self) -> &AppConfig { self.req.config() } } impl

Resource for ServiceRequest

{ fn resource_path(&mut self) -> &mut Path { self.match_info_mut() } } impl

HttpMessage for ServiceRequest

{ type Stream = P; #[inline] /// Returns Request's headers. fn headers(&self) -> &HeaderMap { &self.head().headers } /// Request extensions #[inline] fn extensions(&self) -> Ref { self.req.head.extensions() } /// Mutable reference to a the request's extensions #[inline] fn extensions_mut(&self) -> RefMut { self.req.head.extensions_mut() } #[inline] fn take_payload(&mut self) -> Payload { std::mem::replace(&mut self.payload, Payload::None) } } impl

std::ops::Deref for ServiceRequest

{ type Target = RequestHead; fn deref(&self) -> &RequestHead { self.req.head() } } impl

std::ops::DerefMut for ServiceRequest

{ fn deref_mut(&mut self) -> &mut RequestHead { self.head_mut() } } impl

fmt::Debug for ServiceRequest

{ 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

{ req: HttpRequest, payload: Payload

, data: Option>, } impl

ServiceFromRequest

{ pub(crate) fn new(req: ServiceRequest

, data: Option>) -> Self { Self { req: req.req, payload: req.payload, data, } } #[inline] pub fn into_request(self) -> HttpRequest { self.req } #[inline] pub fn match_info_mut(&mut self) -> &mut Path { &mut self.req.path } /// Create service response for error #[inline] pub fn error_response>(self, err: E) -> ServiceResponse { ServiceResponse::new(self.req, err.into().into()) } /// Load route data. Route data could be set during /// route configuration with `Route::data()` method. pub fn route_data(&self) -> Option<&RouteData> { if let Some(ref ext) = self.data { ext.get::>() } else { None } } } impl

std::ops::Deref for ServiceFromRequest

{ type Target = HttpRequest; fn deref(&self) -> &HttpRequest { &self.req } } impl

HttpMessage for ServiceFromRequest

{ type Stream = P; #[inline] fn headers(&self) -> &HeaderMap { self.req.headers() } /// Request extensions #[inline] fn extensions(&self) -> Ref { self.req.head.extensions() } /// Mutable reference to a the request's extensions #[inline] fn extensions_mut(&self) -> RefMut { self.req.head.extensions_mut() } #[inline] fn take_payload(&mut self) -> Payload { std::mem::replace(&mut self.payload, Payload::None) } } pub struct ServiceResponse { request: HttpRequest, response: Response, } impl ServiceResponse { /// Create service response instance pub fn new(request: HttpRequest, response: Response) -> Self { ServiceResponse { request, response } } /// Create service response from the error pub fn from_err>(err: E, request: HttpRequest) -> Self { let e: Error = err.into(); let res: Response = e.into(); ServiceResponse { request, response: res.into_body(), } } /// Create service response for error #[inline] pub fn error_response>(self, err: E) -> Self { Self::from_err(err, self.request) } /// Create service response #[inline] pub fn into_response(self, response: Response) -> ServiceResponse { ServiceResponse::new(self.request, response) } /// Get reference to original request #[inline] pub fn request(&self) -> &HttpRequest { &self.request } /// Get reference to response #[inline] pub fn response(&self) -> &Response { &self.response } /// Get mutable reference to response #[inline] pub fn response_mut(&mut self) -> &mut Response { &mut self.response } /// Execute closure and in case of error convert it to response. pub fn checked_expr(mut self, f: F) -> Self where F: FnOnce(&mut Self) -> Result<(), E>, E: Into, { match f(&mut self) { Ok(_) => self, Err(err) => { let res: Response = err.into().into(); ServiceResponse::new(self.request, res.into_body()) } } } /// Extract response body pub fn take_body(&mut self) -> ResponseBody { self.response.take_body() } } impl ServiceResponse { /// Set a new body pub fn map_body(self, f: F) -> ServiceResponse where F: FnOnce(&mut ResponseHead, ResponseBody) -> ResponseBody, { let response = self.response.map_body(f); ServiceResponse { response, request: self.request, } } } impl std::ops::Deref for ServiceResponse { type Target = Response; fn deref(&self) -> &Response { self.response() } } impl std::ops::DerefMut for ServiceResponse { fn deref_mut(&mut self) -> &mut Response { self.response_mut() } } impl Into> for ServiceResponse { fn into(self) -> Response { self.response } } impl IntoFuture for ServiceResponse { type Item = ServiceResponse; type Error = Error; type Future = FutureResult, Error>; fn into_future(self) -> Self::Future { ok(self) } } impl fmt::Debug for ServiceResponse { 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 } } #[cfg(test)] mod tests { use crate::test::TestRequest; use crate::HttpResponse; #[test] fn test_fmt_debug() { let req = TestRequest::get() .uri("/index.html?test=1") .header("x-test", "111") .to_srv_request(); let s = format!("{:?}", req); assert!(s.contains("ServiceRequest")); assert!(s.contains("test=1")); assert!(s.contains("x-test")); let res = HttpResponse::Ok().header("x-test", "111").finish(); let res = TestRequest::post() .uri("/index.html?test=1") .to_srv_response(res); let s = format!("{:?}", res); assert!(s.contains("ServiceResponse")); assert!(s.contains("x-test")); } }