mirror of
https://github.com/meilisearch/MeiliSearch
synced 2024-12-24 13:40:31 +01:00
add normalize_slashes middleware
This commit is contained in:
parent
36abcb3976
commit
7a8e64be30
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -1641,6 +1641,7 @@ dependencies = [
|
||||
"actix-web",
|
||||
"actix-web-macros",
|
||||
"assert-json-diff",
|
||||
"bytes 0.5.4",
|
||||
"chrono",
|
||||
"crossbeam-channel",
|
||||
"env_logger",
|
||||
@ -1660,6 +1661,7 @@ dependencies = [
|
||||
"pretty-bytes",
|
||||
"rand 0.7.3",
|
||||
"sentry",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_qs",
|
||||
|
@ -24,6 +24,7 @@ actix-rt = "1"
|
||||
actix-service = "1.0.5"
|
||||
actix-web = "2"
|
||||
actix-web-macros = "0.1.0"
|
||||
bytes = "0.5.4"
|
||||
chrono = { version = "0.4.11", features = ["serde"] }
|
||||
crossbeam-channel = "0.4.2"
|
||||
env_logger = "0.7.1"
|
||||
@ -39,6 +40,7 @@ meilisearch-tokenizer = {path = "../meilisearch-tokenizer", version = "0.10.1"}
|
||||
mime = "0.3.16"
|
||||
pretty-bytes = "0.2.2"
|
||||
rand = "0.7.3"
|
||||
regex = "1.3.6"
|
||||
serde = { version = "1.0.105", features = ["derive"] }
|
||||
serde_json = { version = "1.0.50", features = ["preserve_order"] }
|
||||
serde_qs = "0.5.2"
|
||||
|
@ -134,7 +134,7 @@ impl Data {
|
||||
|
||||
let db_opt = DatabaseOptions {
|
||||
main_map_size: opt.main_map_size,
|
||||
update_map_size: opt.update_map_size
|
||||
update_map_size: opt.update_map_size,
|
||||
};
|
||||
|
||||
let db = Arc::new(Database::open_or_create(opt.db_path, db_opt).unwrap());
|
||||
|
@ -17,7 +17,6 @@ pub enum Authentication {
|
||||
Admin,
|
||||
}
|
||||
|
||||
|
||||
impl<S: 'static, B> Transform<S> for Authentication
|
||||
where
|
||||
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
||||
|
@ -1,4 +1,6 @@
|
||||
pub mod authentication;
|
||||
pub mod meilisearch;
|
||||
pub mod normalize_slashes;
|
||||
|
||||
pub use authentication::Authentication;
|
||||
pub use normalize_slashes::NormalizeSlashes;
|
||||
|
87
meilisearch-http/src/helpers/normalize_slashes.rs
Normal file
87
meilisearch-http/src/helpers/normalize_slashes.rs
Normal file
@ -0,0 +1,87 @@
|
||||
///
|
||||
/// This middleware normalizes slashes in paths
|
||||
/// * consecutive instances of `/` get collapsed into one `/`
|
||||
/// * any ending `/` is removed.
|
||||
///
|
||||
/// Ex:
|
||||
/// /this///url/
|
||||
/// becomes : /this/url
|
||||
///
|
||||
use actix_service::{Service, Transform};
|
||||
use actix_web::{
|
||||
dev::ServiceRequest,
|
||||
dev::ServiceResponse,
|
||||
http::uri::{PathAndQuery, Uri},
|
||||
Error as ActixError,
|
||||
};
|
||||
use futures::future::{ok, Ready};
|
||||
use regex::Regex;
|
||||
use std::task::{Context, Poll};
|
||||
|
||||
pub struct NormalizeSlashes;
|
||||
|
||||
impl<S, B> Transform<S> for NormalizeSlashes
|
||||
where
|
||||
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = ActixError>,
|
||||
S::Future: 'static,
|
||||
{
|
||||
type Request = ServiceRequest;
|
||||
type Response = ServiceResponse<B>;
|
||||
type Error = ActixError;
|
||||
type InitError = ();
|
||||
type Transform = SlashNormalization<S>;
|
||||
type Future = Ready<Result<Self::Transform, Self::InitError>>;
|
||||
|
||||
fn new_transform(&self, service: S) -> Self::Future {
|
||||
ok(SlashNormalization { service })
|
||||
}
|
||||
}
|
||||
|
||||
pub struct SlashNormalization<S> {
|
||||
service: S,
|
||||
}
|
||||
|
||||
impl<S, B> Service for SlashNormalization<S>
|
||||
where
|
||||
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = ActixError>,
|
||||
S::Future: 'static,
|
||||
{
|
||||
type Request = ServiceRequest;
|
||||
type Response = ServiceResponse<B>;
|
||||
type Error = ActixError;
|
||||
type Future = S::Future;
|
||||
|
||||
fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
|
||||
self.service.poll_ready(cx)
|
||||
}
|
||||
|
||||
fn call(&mut self, mut req: ServiceRequest) -> Self::Future {
|
||||
let head = req.head();
|
||||
|
||||
let path = head.uri.path();
|
||||
let original_len = path.len();
|
||||
let slash_regex = Regex::new("//+").unwrap();
|
||||
let new_path = slash_regex.replace_all(path, "/");
|
||||
let new_path = new_path.trim_end_matches("/");
|
||||
|
||||
if original_len != new_path.len() {
|
||||
let mut parts = head.uri.clone().into_parts();
|
||||
|
||||
let path = match parts.path_and_query.as_ref().map(|pq| pq.query()).flatten() {
|
||||
Some(q) => bytes::Bytes::from(format!("{}?{}", new_path, q)),
|
||||
None =>bytes::Bytes::from(format!("{}", new_path))
|
||||
};
|
||||
|
||||
if let Ok(pq) = PathAndQuery::from_maybe_shared(path) {
|
||||
parts.path_and_query = Some(pq);
|
||||
|
||||
if let Ok(uri) = Uri::from_parts(parts) {
|
||||
req.match_info_mut().get_mut().update(&uri);
|
||||
req.head_mut().uri = uri;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.service.call(req)
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ use actix_web::{middleware, HttpServer};
|
||||
use log::info;
|
||||
use main_error::MainError;
|
||||
use meilisearch_http::data::Data;
|
||||
use meilisearch_http::helpers::NormalizeSlashes;
|
||||
use meilisearch_http::option::Opt;
|
||||
use meilisearch_http::{create_app, index_update_callback};
|
||||
use structopt::StructOpt;
|
||||
@ -72,6 +73,7 @@ async fn main() -> Result<(), MainError> {
|
||||
)
|
||||
.wrap(middleware::Logger::default())
|
||||
.wrap(middleware::Compress::default())
|
||||
.wrap(NormalizeSlashes)
|
||||
})
|
||||
.bind(opt.http_addr)?
|
||||
.run()
|
||||
|
@ -33,5 +33,5 @@ pub struct Opt {
|
||||
|
||||
/// The maximum size, in bytes, of the update lmdb database directory
|
||||
#[structopt(long, env = "MEILI_UPDATE_MAP_SIZE", default_value = "107374182400")] // 100GB
|
||||
pub update_map_size: usize
|
||||
pub update_map_size: usize,
|
||||
}
|
||||
|
@ -4,9 +4,9 @@ use serde_json::{json, Value};
|
||||
use std::time::Duration;
|
||||
|
||||
use actix_web::{http::StatusCode, test};
|
||||
use meilisearch_core::DatabaseOptions;
|
||||
use meilisearch_http::data::Data;
|
||||
use meilisearch_http::option::Opt;
|
||||
use meilisearch_core::DatabaseOptions;
|
||||
use tempdir::TempDir;
|
||||
use tokio::time::delay_for;
|
||||
|
||||
@ -28,7 +28,7 @@ impl Server {
|
||||
env: "development".to_owned(),
|
||||
no_analytics: true,
|
||||
main_map_size: default_db_options.main_map_size,
|
||||
update_map_size: default_db_options.update_map_size
|
||||
update_map_size: default_db_options.update_map_size,
|
||||
};
|
||||
|
||||
let data = Data::new(opt.clone());
|
||||
|
Loading…
x
Reference in New Issue
Block a user