mirror of
https://github.com/fafhrd91/actix-web
synced 2024-11-27 17:52:56 +01:00
Add Normalization middleware for in place (#783)
This commit is contained in:
parent
bc40f5ae40
commit
1e7f97a111
@ -6,6 +6,7 @@ pub mod cors;
|
|||||||
mod defaultheaders;
|
mod defaultheaders;
|
||||||
pub mod errhandlers;
|
pub mod errhandlers;
|
||||||
mod logger;
|
mod logger;
|
||||||
|
pub mod normalize;
|
||||||
|
|
||||||
pub use self::defaultheaders::DefaultHeaders;
|
pub use self::defaultheaders::DefaultHeaders;
|
||||||
pub use self::logger::Logger;
|
pub use self::logger::Logger;
|
||||||
|
109
src/middleware/normalize.rs
Normal file
109
src/middleware/normalize.rs
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
//! `Middleware` to normalize request's URI
|
||||||
|
|
||||||
|
use regex::Regex;
|
||||||
|
use actix_service::{Service, Transform};
|
||||||
|
use futures::future::{self, FutureResult};
|
||||||
|
|
||||||
|
use crate::service::{ServiceRequest, ServiceResponse};
|
||||||
|
|
||||||
|
#[derive(Default, Clone, Copy)]
|
||||||
|
/// `Middleware` to normalize request's URI in place
|
||||||
|
///
|
||||||
|
/// Performs following:
|
||||||
|
///
|
||||||
|
/// - Merges multiple slashes into one.
|
||||||
|
pub struct NormalizePath;
|
||||||
|
|
||||||
|
impl<S> Transform<S> for NormalizePath
|
||||||
|
where
|
||||||
|
S: Service<Request = ServiceRequest, Response = ServiceResponse>,
|
||||||
|
{
|
||||||
|
type Request = ServiceRequest;
|
||||||
|
type Response = ServiceResponse;
|
||||||
|
type Error = S::Error;
|
||||||
|
type InitError = ();
|
||||||
|
type Transform = NormalizePathNormalization<S>;
|
||||||
|
type Future = FutureResult<Self::Transform, Self::InitError>;
|
||||||
|
|
||||||
|
fn new_transform(&self, service: S) -> Self::Future {
|
||||||
|
future::ok(NormalizePathNormalization {
|
||||||
|
service,
|
||||||
|
merge_slash: Regex::new("//+").unwrap()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct NormalizePathNormalization<S> {
|
||||||
|
service: S,
|
||||||
|
merge_slash: Regex,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S> Service for NormalizePathNormalization<S>
|
||||||
|
where
|
||||||
|
S: Service<Request = ServiceRequest, Response = ServiceResponse>,
|
||||||
|
{
|
||||||
|
type Request = ServiceRequest;
|
||||||
|
type Response = ServiceResponse;
|
||||||
|
type Error = S::Error;
|
||||||
|
type Future = S::Future;
|
||||||
|
|
||||||
|
fn poll_ready(&mut self) -> futures::Poll<(), Self::Error> {
|
||||||
|
self.service.poll_ready()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn call(&mut self, mut req: ServiceRequest) -> Self::Future {
|
||||||
|
let head = req.head_mut();
|
||||||
|
|
||||||
|
let path = head.uri.path();
|
||||||
|
let original_len = path.len();
|
||||||
|
let path = self.merge_slash.replace_all(path, "/");
|
||||||
|
|
||||||
|
if original_len != path.len() {
|
||||||
|
head.uri = path.parse().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.service.call(req)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use actix_service::FnService;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use crate::dev::ServiceRequest;
|
||||||
|
use crate::http::header::CONTENT_TYPE;
|
||||||
|
use crate::test::{block_on, TestRequest};
|
||||||
|
use crate::HttpResponse;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_in_place_normalization() {
|
||||||
|
let srv = FnService::new(|req: ServiceRequest| {
|
||||||
|
assert_eq!("/v1/something/", req.path());
|
||||||
|
req.into_response(HttpResponse::Ok().finish())
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut normalize = block_on(NormalizePath.new_transform(srv)).unwrap();
|
||||||
|
|
||||||
|
let req = TestRequest::with_uri("/v1//something////").to_srv_request();
|
||||||
|
let res = block_on(normalize.call(req)).unwrap();
|
||||||
|
assert!(res.status().is_success());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_normalize_nothing() {
|
||||||
|
const URI: &str = "/v1/something/";
|
||||||
|
|
||||||
|
let srv = FnService::new(|req: ServiceRequest| {
|
||||||
|
assert_eq!(URI, req.path());
|
||||||
|
req.into_response(HttpResponse::Ok().finish())
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut normalize = block_on(NormalizePath.new_transform(srv)).unwrap();
|
||||||
|
|
||||||
|
let req = TestRequest::with_uri(URI).to_srv_request();
|
||||||
|
let res = block_on(normalize.call(req)).unwrap();
|
||||||
|
assert!(res.status().is_success());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user