mirror of
https://github.com/fafhrd91/actix-web
synced 2025-06-27 15:29:03 +02:00
refactor HttpRequest mutability
This commit is contained in:
@ -60,6 +60,7 @@ use httprequest::HttpRequest;
|
||||
use httpresponse::HttpResponse;
|
||||
use middleware::{Middleware, Response, Started};
|
||||
use resource::ResourceHandler;
|
||||
use server::Request;
|
||||
|
||||
/// A set of errors that can occur during processing CORS
|
||||
#[derive(Debug, Fail)]
|
||||
@ -279,11 +280,13 @@ impl Cors {
|
||||
/// `ResourceHandler::middleware()` method, but in that case *Cors*
|
||||
/// middleware wont be able to handle *OPTIONS* requests.
|
||||
pub fn register<S: 'static>(self, resource: &mut ResourceHandler<S>) {
|
||||
resource.method(Method::OPTIONS).h(|_| HttpResponse::Ok());
|
||||
resource
|
||||
.method(Method::OPTIONS)
|
||||
.h(|_: &_| HttpResponse::Ok());
|
||||
resource.middleware(self);
|
||||
}
|
||||
|
||||
fn validate_origin<S>(&self, req: &mut HttpRequest<S>) -> Result<(), CorsError> {
|
||||
fn validate_origin(&self, req: &Request) -> Result<(), CorsError> {
|
||||
if let Some(hdr) = req.headers().get(header::ORIGIN) {
|
||||
if let Ok(origin) = hdr.to_str() {
|
||||
return match self.inner.origins {
|
||||
@ -303,9 +306,7 @@ impl Cors {
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_allowed_method<S>(
|
||||
&self, req: &mut HttpRequest<S>,
|
||||
) -> Result<(), CorsError> {
|
||||
fn validate_allowed_method(&self, req: &Request) -> Result<(), CorsError> {
|
||||
if let Some(hdr) = req.headers().get(header::ACCESS_CONTROL_REQUEST_METHOD) {
|
||||
if let Ok(meth) = hdr.to_str() {
|
||||
if let Ok(method) = Method::try_from(meth) {
|
||||
@ -323,9 +324,7 @@ impl Cors {
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_allowed_headers<S>(
|
||||
&self, req: &mut HttpRequest<S>,
|
||||
) -> Result<(), CorsError> {
|
||||
fn validate_allowed_headers(&self, req: &Request) -> Result<(), CorsError> {
|
||||
match self.inner.headers {
|
||||
AllOrSome::All => Ok(()),
|
||||
AllOrSome::Some(ref allowed_headers) => {
|
||||
@ -356,11 +355,11 @@ impl Cors {
|
||||
}
|
||||
|
||||
impl<S> Middleware<S> for Cors {
|
||||
fn start(&self, req: &mut HttpRequest<S>) -> Result<Started> {
|
||||
fn start(&self, req: &HttpRequest<S>) -> Result<Started> {
|
||||
if self.inner.preflight && Method::OPTIONS == *req.method() {
|
||||
self.validate_origin(req)?;
|
||||
self.validate_allowed_method(req)?;
|
||||
self.validate_allowed_headers(req)?;
|
||||
self.validate_allowed_method(&req)?;
|
||||
self.validate_allowed_headers(&req)?;
|
||||
|
||||
// allowed headers
|
||||
let headers = if let Some(headers) = self.inner.headers.as_ref() {
|
||||
@ -434,7 +433,7 @@ impl<S> Middleware<S> for Cors {
|
||||
}
|
||||
|
||||
fn response(
|
||||
&self, req: &mut HttpRequest<S>, mut resp: HttpResponse,
|
||||
&self, req: &HttpRequest<S>, mut resp: HttpResponse,
|
||||
) -> Result<Response> {
|
||||
match self.inner.origins {
|
||||
AllOrSome::All => {
|
||||
@ -945,10 +944,9 @@ mod tests {
|
||||
#[test]
|
||||
fn validate_origin_allows_all_origins() {
|
||||
let cors = Cors::default();
|
||||
let mut req =
|
||||
TestRequest::with_header("Origin", "https://www.example.com").finish();
|
||||
let req = TestRequest::with_header("Origin", "https://www.example.com").finish();
|
||||
|
||||
assert!(cors.start(&mut req).ok().unwrap().is_done())
|
||||
assert!(cors.start(&req).ok().unwrap().is_done())
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -961,20 +959,20 @@ mod tests {
|
||||
.allowed_header(header::CONTENT_TYPE)
|
||||
.finish();
|
||||
|
||||
let mut req = TestRequest::with_header("Origin", "https://www.example.com")
|
||||
let req = TestRequest::with_header("Origin", "https://www.example.com")
|
||||
.method(Method::OPTIONS)
|
||||
.finish();
|
||||
|
||||
assert!(cors.start(&mut req).is_err());
|
||||
assert!(cors.start(&req).is_err());
|
||||
|
||||
let mut req = TestRequest::with_header("Origin", "https://www.example.com")
|
||||
let req = TestRequest::with_header("Origin", "https://www.example.com")
|
||||
.header(header::ACCESS_CONTROL_REQUEST_METHOD, "put")
|
||||
.method(Method::OPTIONS)
|
||||
.finish();
|
||||
|
||||
assert!(cors.start(&mut req).is_err());
|
||||
assert!(cors.start(&req).is_err());
|
||||
|
||||
let mut req = TestRequest::with_header("Origin", "https://www.example.com")
|
||||
let req = TestRequest::with_header("Origin", "https://www.example.com")
|
||||
.header(header::ACCESS_CONTROL_REQUEST_METHOD, "POST")
|
||||
.header(
|
||||
header::ACCESS_CONTROL_REQUEST_HEADERS,
|
||||
@ -983,7 +981,7 @@ mod tests {
|
||||
.method(Method::OPTIONS)
|
||||
.finish();
|
||||
|
||||
let resp = cors.start(&mut req).unwrap().response();
|
||||
let resp = cors.start(&req).unwrap().response();
|
||||
assert_eq!(
|
||||
&b"*"[..],
|
||||
resp.headers()
|
||||
@ -1007,7 +1005,7 @@ mod tests {
|
||||
// as_bytes());
|
||||
|
||||
Rc::get_mut(&mut cors.inner).unwrap().preflight = false;
|
||||
assert!(cors.start(&mut req).unwrap().is_done());
|
||||
assert!(cors.start(&req).unwrap().is_done());
|
||||
}
|
||||
|
||||
// #[test]
|
||||
@ -1017,7 +1015,7 @@ mod tests {
|
||||
// .allowed_origin("https://www.example.com")
|
||||
// .finish();
|
||||
// let mut req = HttpRequest::default();
|
||||
// cors.start(&mut req).unwrap();
|
||||
// cors.start(&req).unwrap();
|
||||
// }
|
||||
|
||||
#[test]
|
||||
@ -1027,10 +1025,10 @@ mod tests {
|
||||
.allowed_origin("https://www.example.com")
|
||||
.finish();
|
||||
|
||||
let mut req = TestRequest::with_header("Origin", "https://www.unknown.com")
|
||||
let req = TestRequest::with_header("Origin", "https://www.unknown.com")
|
||||
.method(Method::GET)
|
||||
.finish();
|
||||
cors.start(&mut req).unwrap();
|
||||
cors.start(&req).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1039,30 +1037,30 @@ mod tests {
|
||||
.allowed_origin("https://www.example.com")
|
||||
.finish();
|
||||
|
||||
let mut req = TestRequest::with_header("Origin", "https://www.example.com")
|
||||
let req = TestRequest::with_header("Origin", "https://www.example.com")
|
||||
.method(Method::GET)
|
||||
.finish();
|
||||
|
||||
assert!(cors.start(&mut req).unwrap().is_done());
|
||||
assert!(cors.start(&req).unwrap().is_done());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_no_origin_response() {
|
||||
let cors = Cors::build().finish();
|
||||
|
||||
let mut req = TestRequest::default().method(Method::GET).finish();
|
||||
let req = TestRequest::default().method(Method::GET).finish();
|
||||
let resp: HttpResponse = HttpResponse::Ok().into();
|
||||
let resp = cors.response(&mut req, resp).unwrap().response();
|
||||
let resp = cors.response(&req, resp).unwrap().response();
|
||||
assert!(
|
||||
resp.headers()
|
||||
.get(header::ACCESS_CONTROL_ALLOW_ORIGIN)
|
||||
.is_none()
|
||||
);
|
||||
|
||||
let mut req = TestRequest::with_header("Origin", "https://www.example.com")
|
||||
let req = TestRequest::with_header("Origin", "https://www.example.com")
|
||||
.method(Method::OPTIONS)
|
||||
.finish();
|
||||
let resp = cors.response(&mut req, resp).unwrap().response();
|
||||
let resp = cors.response(&req, resp).unwrap().response();
|
||||
assert_eq!(
|
||||
&b"https://www.example.com"[..],
|
||||
resp.headers()
|
||||
@ -1083,12 +1081,12 @@ mod tests {
|
||||
.allowed_header(header::CONTENT_TYPE)
|
||||
.finish();
|
||||
|
||||
let mut req = TestRequest::with_header("Origin", "https://www.example.com")
|
||||
let req = TestRequest::with_header("Origin", "https://www.example.com")
|
||||
.method(Method::OPTIONS)
|
||||
.finish();
|
||||
|
||||
let resp: HttpResponse = HttpResponse::Ok().into();
|
||||
let resp = cors.response(&mut req, resp).unwrap().response();
|
||||
let resp = cors.response(&req, resp).unwrap().response();
|
||||
assert_eq!(
|
||||
&b"*"[..],
|
||||
resp.headers()
|
||||
@ -1103,7 +1101,7 @@ mod tests {
|
||||
|
||||
let resp: HttpResponse =
|
||||
HttpResponse::Ok().header(header::VARY, "Accept").finish();
|
||||
let resp = cors.response(&mut req, resp).unwrap().response();
|
||||
let resp = cors.response(&req, resp).unwrap().response();
|
||||
assert_eq!(
|
||||
&b"Accept, Origin"[..],
|
||||
resp.headers().get(header::VARY).unwrap().as_bytes()
|
||||
@ -1114,7 +1112,7 @@ mod tests {
|
||||
.allowed_origin("https://www.example.com")
|
||||
.finish();
|
||||
let resp: HttpResponse = HttpResponse::Ok().into();
|
||||
let resp = cors.response(&mut req, resp).unwrap().response();
|
||||
let resp = cors.response(&req, resp).unwrap().response();
|
||||
assert_eq!(
|
||||
&b"https://www.example.com"[..],
|
||||
resp.headers()
|
||||
|
@ -25,7 +25,7 @@
|
||||
//! use actix_web::middleware::csrf;
|
||||
//! use actix_web::{http, App, HttpRequest, HttpResponse};
|
||||
//!
|
||||
//! fn handle_post(_: HttpRequest) -> &'static str {
|
||||
//! fn handle_post(_: &HttpRequest) -> &'static str {
|
||||
//! "This action should only be triggered with requests from the same site"
|
||||
//! }
|
||||
//!
|
||||
@ -54,6 +54,7 @@ use httpmessage::HttpMessage;
|
||||
use httprequest::HttpRequest;
|
||||
use httpresponse::HttpResponse;
|
||||
use middleware::{Middleware, Started};
|
||||
use server::Request;
|
||||
|
||||
/// Potential cross-site request forgery detected.
|
||||
#[derive(Debug, Fail)]
|
||||
@ -187,7 +188,7 @@ impl CsrfFilter {
|
||||
self
|
||||
}
|
||||
|
||||
fn validate<S>(&self, req: &mut HttpRequest<S>) -> Result<(), CsrfError> {
|
||||
fn validate(&self, req: &Request) -> Result<(), CsrfError> {
|
||||
let is_upgrade = req.headers().contains_key(header::UPGRADE);
|
||||
let is_safe = req.method().is_safe() && (self.allow_upgrade || !is_upgrade);
|
||||
|
||||
@ -209,7 +210,7 @@ impl CsrfFilter {
|
||||
}
|
||||
|
||||
impl<S> Middleware<S> for CsrfFilter {
|
||||
fn start(&self, req: &mut HttpRequest<S>) -> Result<Started> {
|
||||
fn start(&self, req: &HttpRequest<S>) -> Result<Started> {
|
||||
self.validate(req)?;
|
||||
Ok(Started::Done)
|
||||
}
|
||||
@ -225,35 +226,35 @@ mod tests {
|
||||
fn test_safe() {
|
||||
let csrf = CsrfFilter::new().allowed_origin("https://www.example.com");
|
||||
|
||||
let mut req = TestRequest::with_header("Origin", "https://www.w3.org")
|
||||
let req = TestRequest::with_header("Origin", "https://www.w3.org")
|
||||
.method(Method::HEAD)
|
||||
.finish();
|
||||
|
||||
assert!(csrf.start(&mut req).is_ok());
|
||||
assert!(csrf.start(&req).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_csrf() {
|
||||
let csrf = CsrfFilter::new().allowed_origin("https://www.example.com");
|
||||
|
||||
let mut req = TestRequest::with_header("Origin", "https://www.w3.org")
|
||||
let req = TestRequest::with_header("Origin", "https://www.w3.org")
|
||||
.method(Method::POST)
|
||||
.finish();
|
||||
|
||||
assert!(csrf.start(&mut req).is_err());
|
||||
assert!(csrf.start(&req).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_referer() {
|
||||
let csrf = CsrfFilter::new().allowed_origin("https://www.example.com");
|
||||
|
||||
let mut req = TestRequest::with_header(
|
||||
let req = TestRequest::with_header(
|
||||
"Referer",
|
||||
"https://www.example.com/some/path?query=param",
|
||||
).method(Method::POST)
|
||||
.finish();
|
||||
|
||||
assert!(csrf.start(&mut req).is_ok());
|
||||
assert!(csrf.start(&req).is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -264,13 +265,13 @@ mod tests {
|
||||
.allowed_origin("https://www.example.com")
|
||||
.allow_upgrade();
|
||||
|
||||
let mut req = TestRequest::with_header("Origin", "https://cswsh.com")
|
||||
let req = TestRequest::with_header("Origin", "https://cswsh.com")
|
||||
.header("Connection", "Upgrade")
|
||||
.header("Upgrade", "websocket")
|
||||
.method(Method::GET)
|
||||
.finish();
|
||||
|
||||
assert!(strict_csrf.start(&mut req).is_err());
|
||||
assert!(lax_csrf.start(&mut req).is_ok());
|
||||
assert!(strict_csrf.start(&req).is_err());
|
||||
assert!(lax_csrf.start(&req).is_ok());
|
||||
}
|
||||
}
|
||||
|
@ -74,9 +74,7 @@ impl DefaultHeaders {
|
||||
}
|
||||
|
||||
impl<S> Middleware<S> for DefaultHeaders {
|
||||
fn response(
|
||||
&self, _: &mut HttpRequest<S>, mut resp: HttpResponse,
|
||||
) -> Result<Response> {
|
||||
fn response(&self, _: &HttpRequest<S>, mut resp: HttpResponse) -> Result<Response> {
|
||||
for (key, value) in self.headers.iter() {
|
||||
if !resp.headers().contains_key(key) {
|
||||
resp.headers_mut().insert(key, value.clone());
|
||||
@ -97,22 +95,23 @@ impl<S> Middleware<S> for DefaultHeaders {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use http::header::CONTENT_TYPE;
|
||||
use test::TestRequest;
|
||||
|
||||
#[test]
|
||||
fn test_default_headers() {
|
||||
let mw = DefaultHeaders::new().header(CONTENT_TYPE, "0001");
|
||||
|
||||
let mut req = HttpRequest::default();
|
||||
let req = TestRequest::default().finish();
|
||||
|
||||
let resp = HttpResponse::Ok().finish();
|
||||
let resp = match mw.response(&mut req, resp) {
|
||||
let resp = match mw.response(&req, resp) {
|
||||
Ok(Response::Done(resp)) => resp,
|
||||
_ => panic!(),
|
||||
};
|
||||
assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001");
|
||||
|
||||
let resp = HttpResponse::Ok().header(CONTENT_TYPE, "0002").finish();
|
||||
let resp = match mw.response(&mut req, resp) {
|
||||
let resp = match mw.response(&req, resp) {
|
||||
Ok(Response::Done(resp)) => resp,
|
||||
_ => panic!(),
|
||||
};
|
||||
|
@ -6,7 +6,7 @@ use httprequest::HttpRequest;
|
||||
use httpresponse::HttpResponse;
|
||||
use middleware::{Middleware, Response};
|
||||
|
||||
type ErrorHandler<S> = Fn(&mut HttpRequest<S>, HttpResponse) -> Result<Response>;
|
||||
type ErrorHandler<S> = Fn(&HttpRequest<S>, HttpResponse) -> Result<Response>;
|
||||
|
||||
/// `Middleware` for allowing custom handlers for responses.
|
||||
///
|
||||
@ -21,7 +21,7 @@ type ErrorHandler<S> = Fn(&mut HttpRequest<S>, HttpResponse) -> Result<Response>
|
||||
/// use actix_web::middleware::{ErrorHandlers, Response};
|
||||
/// use actix_web::{http, App, HttpRequest, HttpResponse, Result};
|
||||
///
|
||||
/// fn render_500<S>(_: &mut HttpRequest<S>, resp: HttpResponse) -> Result<Response> {
|
||||
/// fn render_500<S>(_: &HttpRequest<S>, resp: HttpResponse) -> Result<Response> {
|
||||
/// let mut builder = resp.into_builder();
|
||||
/// builder.header(http::header::CONTENT_TYPE, "application/json");
|
||||
/// Ok(Response::Done(builder.into()))
|
||||
@ -62,7 +62,7 @@ impl<S> ErrorHandlers<S> {
|
||||
/// Register error handler for specified status code
|
||||
pub fn handler<F>(mut self, status: StatusCode, handler: F) -> Self
|
||||
where
|
||||
F: Fn(&mut HttpRequest<S>, HttpResponse) -> Result<Response> + 'static,
|
||||
F: Fn(&HttpRequest<S>, HttpResponse) -> Result<Response> + 'static,
|
||||
{
|
||||
self.handlers.insert(status, Box::new(handler));
|
||||
self
|
||||
@ -70,9 +70,7 @@ impl<S> ErrorHandlers<S> {
|
||||
}
|
||||
|
||||
impl<S: 'static> Middleware<S> for ErrorHandlers<S> {
|
||||
fn response(
|
||||
&self, req: &mut HttpRequest<S>, resp: HttpResponse,
|
||||
) -> Result<Response> {
|
||||
fn response(&self, req: &HttpRequest<S>, resp: HttpResponse) -> Result<Response> {
|
||||
if let Some(handler) = self.handlers.get(&resp.status()) {
|
||||
handler(req, resp)
|
||||
} else {
|
||||
@ -91,7 +89,10 @@ mod tests {
|
||||
use middleware::Started;
|
||||
use test;
|
||||
|
||||
fn render_500<S>(_: &mut HttpRequest<S>, resp: HttpResponse) -> Result<Response> {
|
||||
use server::Request;
|
||||
use test::TestRequest;
|
||||
|
||||
fn render_500<S>(_: &HttpRequest<S>, resp: HttpResponse) -> Result<Response> {
|
||||
let mut builder = resp.into_builder();
|
||||
builder.header(CONTENT_TYPE, "0001");
|
||||
Ok(Response::Done(builder.into()))
|
||||
@ -102,7 +103,7 @@ mod tests {
|
||||
let mw =
|
||||
ErrorHandlers::new().handler(StatusCode::INTERNAL_SERVER_ERROR, render_500);
|
||||
|
||||
let mut req = HttpRequest::default();
|
||||
let mut req = TestRequest::default().finish();
|
||||
let resp = HttpResponse::InternalServerError().finish();
|
||||
let resp = match mw.response(&mut req, resp) {
|
||||
Ok(Response::Done(resp)) => resp,
|
||||
@ -121,7 +122,7 @@ mod tests {
|
||||
struct MiddlewareOne;
|
||||
|
||||
impl<S> Middleware<S> for MiddlewareOne {
|
||||
fn start(&self, _req: &mut HttpRequest<S>) -> Result<Started, Error> {
|
||||
fn start(&self, _: &HttpRequest<S>) -> Result<Started, Error> {
|
||||
Err(ErrorInternalServerError("middleware error"))
|
||||
}
|
||||
}
|
||||
|
@ -46,6 +46,7 @@
|
||||
//! ));
|
||||
//! }
|
||||
//! ```
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use cookie::{Cookie, CookieJar, Key};
|
||||
@ -58,6 +59,7 @@ use http::header::{self, HeaderValue};
|
||||
use httprequest::HttpRequest;
|
||||
use httpresponse::HttpResponse;
|
||||
use middleware::{Middleware, Response, Started};
|
||||
use server::Request;
|
||||
|
||||
/// The helper trait to obtain your identity from a request.
|
||||
///
|
||||
@ -88,32 +90,32 @@ use middleware::{Middleware, Response, Started};
|
||||
pub trait RequestIdentity {
|
||||
/// Return the claimed identity of the user associated request or
|
||||
/// ``None`` if no identity can be found associated with the request.
|
||||
fn identity(&self) -> Option<&str>;
|
||||
fn identity(&self) -> Option<String>;
|
||||
|
||||
/// Remember identity.
|
||||
fn remember(&mut self, identity: String);
|
||||
fn remember(&self, identity: String);
|
||||
|
||||
/// This method is used to 'forget' the current identity on subsequent
|
||||
/// requests.
|
||||
fn forget(&mut self);
|
||||
fn forget(&self);
|
||||
}
|
||||
|
||||
impl<S> RequestIdentity for HttpRequest<S> {
|
||||
fn identity(&self) -> Option<&str> {
|
||||
fn identity(&self) -> Option<String> {
|
||||
if let Some(id) = self.extensions().get::<IdentityBox>() {
|
||||
return id.0.identity();
|
||||
return id.0.identity().map(|s| s.to_owned());
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn remember(&mut self, identity: String) {
|
||||
if let Some(id) = self.extensions_mut().get_mut::<IdentityBox>() {
|
||||
return id.0.remember(identity);
|
||||
fn remember(&self, identity: String) {
|
||||
if let Some(mut id) = self.extensions_mut().get_mut::<IdentityBox>() {
|
||||
return id.0.as_mut().remember(identity);
|
||||
}
|
||||
}
|
||||
|
||||
fn forget(&mut self) {
|
||||
if let Some(id) = self.extensions_mut().get_mut::<IdentityBox>() {
|
||||
fn forget(&self) {
|
||||
if let Some(mut id) = self.extensions_mut().get_mut::<IdentityBox>() {
|
||||
return id.0.forget();
|
||||
}
|
||||
}
|
||||
@ -145,7 +147,7 @@ pub trait IdentityPolicy<S>: Sized + 'static {
|
||||
type Future: Future<Item = Self::Identity, Error = Error>;
|
||||
|
||||
/// Parse the session from request and load data from a service identity.
|
||||
fn from_request(&self, request: &mut HttpRequest<S>) -> Self::Future;
|
||||
fn from_request(&self, request: &HttpRequest<S>) -> Self::Future;
|
||||
}
|
||||
|
||||
/// Request identity middleware
|
||||
@ -178,27 +180,21 @@ impl<T> IdentityService<T> {
|
||||
struct IdentityBox(Box<Identity>);
|
||||
|
||||
impl<S: 'static, T: IdentityPolicy<S>> Middleware<S> for IdentityService<T> {
|
||||
fn start(&self, req: &mut HttpRequest<S>) -> Result<Started> {
|
||||
let mut req = req.clone();
|
||||
|
||||
let fut = self
|
||||
.backend
|
||||
.from_request(&mut req)
|
||||
.then(move |res| match res {
|
||||
Ok(id) => {
|
||||
req.extensions_mut().insert(IdentityBox(Box::new(id)));
|
||||
FutOk(None)
|
||||
}
|
||||
Err(err) => FutErr(err),
|
||||
});
|
||||
fn start(&self, req: &HttpRequest<S>) -> Result<Started> {
|
||||
let req = req.clone();
|
||||
let fut = self.backend.from_request(&req).then(move |res| match res {
|
||||
Ok(id) => {
|
||||
req.extensions_mut().insert(IdentityBox(Box::new(id)));
|
||||
FutOk(None)
|
||||
}
|
||||
Err(err) => FutErr(err),
|
||||
});
|
||||
Ok(Started::Future(Box::new(fut)))
|
||||
}
|
||||
|
||||
fn response(
|
||||
&self, req: &mut HttpRequest<S>, resp: HttpResponse,
|
||||
) -> Result<Response> {
|
||||
if let Some(mut id) = req.extensions_mut().remove::<IdentityBox>() {
|
||||
id.0.write(resp)
|
||||
fn response(&self, req: &HttpRequest<S>, resp: HttpResponse) -> Result<Response> {
|
||||
if let Some(ref mut id) = req.extensions_mut().get_mut::<IdentityBox>() {
|
||||
id.0.as_mut().write(resp)
|
||||
} else {
|
||||
Ok(Response::Done(resp))
|
||||
}
|
||||
@ -291,9 +287,9 @@ impl CookieIdentityInner {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn load<S>(&self, req: &mut HttpRequest<S>) -> Option<String> {
|
||||
fn load<S>(&self, req: &HttpRequest<S>) -> Option<String> {
|
||||
if let Ok(cookies) = req.cookies() {
|
||||
for cookie in cookies {
|
||||
for cookie in cookies.iter() {
|
||||
if cookie.name() == self.name {
|
||||
let mut jar = CookieJar::new();
|
||||
jar.add_original(cookie.clone());
|
||||
@ -382,7 +378,7 @@ impl<S> IdentityPolicy<S> for CookieIdentityPolicy {
|
||||
type Identity = CookieIdentity;
|
||||
type Future = FutureResult<CookieIdentity, Error>;
|
||||
|
||||
fn from_request(&self, req: &mut HttpRequest<S>) -> Self::Future {
|
||||
fn from_request(&self, req: &HttpRequest<S>) -> Self::Future {
|
||||
let identity = self.0.load(req);
|
||||
FutOk(CookieIdentity {
|
||||
identity,
|
||||
|
@ -11,6 +11,7 @@ use httpmessage::HttpMessage;
|
||||
use httprequest::HttpRequest;
|
||||
use httpresponse::HttpResponse;
|
||||
use middleware::{Finished, Middleware, Started};
|
||||
use server::Request;
|
||||
|
||||
/// `Middleware` for logging request and response info to the terminal.
|
||||
///
|
||||
@ -107,7 +108,7 @@ impl Default for Logger {
|
||||
struct StartTime(time::Tm);
|
||||
|
||||
impl Logger {
|
||||
fn log<S>(&self, req: &mut HttpRequest<S>, resp: &HttpResponse) {
|
||||
fn log<S>(&self, req: &HttpRequest<S>, resp: &HttpResponse) {
|
||||
if let Some(entry_time) = req.extensions().get::<StartTime>() {
|
||||
let render = |fmt: &mut Formatter| {
|
||||
for unit in &self.format.0 {
|
||||
@ -121,14 +122,14 @@ impl Logger {
|
||||
}
|
||||
|
||||
impl<S> Middleware<S> for Logger {
|
||||
fn start(&self, req: &mut HttpRequest<S>) -> Result<Started> {
|
||||
fn start(&self, req: &HttpRequest<S>) -> Result<Started> {
|
||||
if !self.exclude.contains(req.path()) {
|
||||
req.extensions_mut().insert(StartTime(time::now()));
|
||||
}
|
||||
Ok(Started::Done)
|
||||
}
|
||||
|
||||
fn finish(&self, req: &mut HttpRequest<S>, resp: &HttpResponse) -> Finished {
|
||||
fn finish(&self, req: &HttpRequest<S>, resp: &HttpResponse) -> Finished {
|
||||
self.log(req, resp);
|
||||
Finished::Done
|
||||
}
|
||||
@ -312,34 +313,27 @@ mod tests {
|
||||
use http::header::{self, HeaderMap};
|
||||
use http::{Method, StatusCode, Uri, Version};
|
||||
use std::str::FromStr;
|
||||
use test::TestRequest;
|
||||
use time;
|
||||
|
||||
#[test]
|
||||
fn test_logger() {
|
||||
let logger = Logger::new("%% %{User-Agent}i %{X-Test}o %{HOME}e %D test");
|
||||
|
||||
let mut headers = HeaderMap::new();
|
||||
headers.insert(
|
||||
let req = TestRequest::with_header(
|
||||
header::USER_AGENT,
|
||||
header::HeaderValue::from_static("ACTIX-WEB"),
|
||||
);
|
||||
let mut req = HttpRequest::new(
|
||||
Method::GET,
|
||||
Uri::from_str("/").unwrap(),
|
||||
Version::HTTP_11,
|
||||
headers,
|
||||
None,
|
||||
);
|
||||
).finish();
|
||||
let resp = HttpResponse::build(StatusCode::OK)
|
||||
.header("X-Test", "ttt")
|
||||
.force_close()
|
||||
.finish();
|
||||
|
||||
match logger.start(&mut req) {
|
||||
match logger.start(&req) {
|
||||
Ok(Started::Done) => (),
|
||||
_ => panic!(),
|
||||
};
|
||||
match logger.finish(&mut req, &resp) {
|
||||
match logger.finish(&req, &resp) {
|
||||
Finished::Done => (),
|
||||
_ => panic!(),
|
||||
}
|
||||
@ -358,18 +352,10 @@ mod tests {
|
||||
fn test_default_format() {
|
||||
let format = Format::default();
|
||||
|
||||
let mut headers = HeaderMap::new();
|
||||
headers.insert(
|
||||
let req = TestRequest::with_header(
|
||||
header::USER_AGENT,
|
||||
header::HeaderValue::from_static("ACTIX-WEB"),
|
||||
);
|
||||
let req = HttpRequest::new(
|
||||
Method::GET,
|
||||
Uri::from_str("/").unwrap(),
|
||||
Version::HTTP_11,
|
||||
headers,
|
||||
None,
|
||||
);
|
||||
).finish();
|
||||
let resp = HttpResponse::build(StatusCode::OK).force_close().finish();
|
||||
let entry_time = time::now();
|
||||
|
||||
@ -384,13 +370,7 @@ mod tests {
|
||||
assert!(s.contains("200 0"));
|
||||
assert!(s.contains("ACTIX-WEB"));
|
||||
|
||||
let req = HttpRequest::new(
|
||||
Method::GET,
|
||||
Uri::from_str("/?test").unwrap(),
|
||||
Version::HTTP_11,
|
||||
HeaderMap::new(),
|
||||
None,
|
||||
);
|
||||
let req = TestRequest::with_uri("/?test").finish();
|
||||
let resp = HttpResponse::build(StatusCode::OK).force_close().finish();
|
||||
let entry_time = time::now();
|
||||
|
||||
|
@ -4,6 +4,7 @@ use futures::Future;
|
||||
use error::{Error, Result};
|
||||
use httprequest::HttpRequest;
|
||||
use httpresponse::HttpResponse;
|
||||
use server::Request;
|
||||
|
||||
mod logger;
|
||||
|
||||
@ -51,20 +52,18 @@ pub enum Finished {
|
||||
pub trait Middleware<S>: 'static {
|
||||
/// Method is called when request is ready. It may return
|
||||
/// future, which should resolve before next middleware get called.
|
||||
fn start(&self, req: &mut HttpRequest<S>) -> Result<Started> {
|
||||
fn start(&self, req: &HttpRequest<S>) -> Result<Started> {
|
||||
Ok(Started::Done)
|
||||
}
|
||||
|
||||
/// Method is called when handler returns response,
|
||||
/// but before sending http message to peer.
|
||||
fn response(
|
||||
&self, req: &mut HttpRequest<S>, resp: HttpResponse,
|
||||
) -> Result<Response> {
|
||||
fn response(&self, req: &HttpRequest<S>, resp: HttpResponse) -> Result<Response> {
|
||||
Ok(Response::Done(resp))
|
||||
}
|
||||
|
||||
/// Method is called after body stream get sent to peer.
|
||||
fn finish(&self, req: &mut HttpRequest<S>, resp: &HttpResponse) -> Finished {
|
||||
fn finish(&self, req: &HttpRequest<S>, resp: &HttpResponse) -> Finished {
|
||||
Finished::Done
|
||||
}
|
||||
}
|
||||
|
@ -83,6 +83,7 @@ use handler::FromRequest;
|
||||
use httprequest::HttpRequest;
|
||||
use httpresponse::HttpResponse;
|
||||
use middleware::{Middleware, Response, Started};
|
||||
use server::Request;
|
||||
|
||||
/// The helper trait to obtain your session data from a request.
|
||||
///
|
||||
@ -246,7 +247,7 @@ impl<S, T: SessionBackend<S>> SessionStorage<T, S> {
|
||||
}
|
||||
|
||||
impl<S: 'static, T: SessionBackend<S>> Middleware<S> for SessionStorage<T, S> {
|
||||
fn start(&self, req: &mut HttpRequest<S>) -> Result<Started> {
|
||||
fn start(&self, req: &HttpRequest<S>) -> Result<Started> {
|
||||
let mut req = req.clone();
|
||||
|
||||
let fut = self.0.from_request(&mut req).then(move |res| match res {
|
||||
@ -260,10 +261,8 @@ impl<S: 'static, T: SessionBackend<S>> Middleware<S> for SessionStorage<T, S> {
|
||||
Ok(Started::Future(Box::new(fut)))
|
||||
}
|
||||
|
||||
fn response(
|
||||
&self, req: &mut HttpRequest<S>, resp: HttpResponse,
|
||||
) -> Result<Response> {
|
||||
if let Some(s_box) = req.extensions_mut().remove::<Arc<SessionImplCell>>() {
|
||||
fn response(&self, req: &HttpRequest<S>, resp: HttpResponse) -> Result<Response> {
|
||||
if let Some(s_box) = req.extensions().get::<Arc<SessionImplCell>>() {
|
||||
s_box.0.borrow_mut().write(resp)
|
||||
} else {
|
||||
Ok(Response::Done(resp))
|
||||
@ -421,7 +420,7 @@ impl CookieSessionInner {
|
||||
|
||||
fn load<S>(&self, req: &mut HttpRequest<S>) -> HashMap<String, String> {
|
||||
if let Ok(cookies) = req.cookies() {
|
||||
for cookie in cookies {
|
||||
for cookie in cookies.iter() {
|
||||
if cookie.name() == self.name {
|
||||
let mut jar = CookieJar::new();
|
||||
jar.add_original(cookie.clone());
|
||||
|
Reference in New Issue
Block a user