relative path and request head

This commit is contained in:
Ali MJ Al-Nasrawy 2021-06-23 00:59:42 +03:00
parent 13ff7759d3
commit 173ea9acf2
3 changed files with 19 additions and 15 deletions

View File

@ -8,7 +8,10 @@ use std::{
use actix_service::{boxed, IntoServiceFactory, ServiceFactory, ServiceFactoryExt};
use actix_utils::future::ok;
use actix_web::{
dev::{AppService, HttpServiceFactory, ResourceDef, ServiceRequest, ServiceResponse},
dev::{
AppService, HttpServiceFactory, RequestHead, ResourceDef, ServiceRequest,
ServiceResponse,
},
error::Error,
guard::Guard,
http::header::DispositionType,
@ -163,7 +166,7 @@ impl Files {
/// `404 NotFound` is returned.
pub fn path_filter<F>(mut self, f: F) -> Self
where
F: Fn(&Path) -> bool + 'static,
F: Fn(&Path, &RequestHead) -> bool + 'static,
{
self.path_filter = Some(Rc::new(f));
self

View File

@ -16,7 +16,7 @@
use actix_service::boxed::{BoxService, BoxServiceFactory};
use actix_web::{
dev::{ServiceRequest, ServiceResponse},
dev::{RequestHead, ServiceRequest, ServiceResponse},
error::Error,
http::header::DispositionType,
};
@ -57,7 +57,7 @@ pub fn file_extension_to_mime(ext: &str) -> mime::Mime {
type MimeOverride = dyn Fn(&mime::Name<'_>) -> DispositionType;
type PathFilter = dyn Fn(&Path) -> bool;
type PathFilter = dyn Fn(&Path, &RequestHead) -> bool;
#[cfg(test)]
mod tests {
@ -907,17 +907,18 @@ mod tests {
#[actix_rt::test]
async fn test_path_filter() {
// prevent searching subdirectories
let st = Files::new("/", ".")
.path_filter(|path| path.extension() == Some("png".as_ref()))
.path_filter(|path, _| path.components().count() == 1)
.new_service(())
.await
.unwrap();
let req = TestRequest::with_uri("/tests/test.png").to_srv_request();
let req = TestRequest::with_uri("/Cargo.toml").to_srv_request();
let resp = test::call_service(&st, req).await;
assert_eq!(resp.status(), StatusCode::OK);
let req = TestRequest::with_uri("/Cargo.toml").to_srv_request();
let req = TestRequest::with_uri("/tests/test.png").to_srv_request();
let resp = test::call_service(&st, req).await;
assert_eq!(resp.status(), StatusCode::NOT_FOUND);
}
@ -928,7 +929,7 @@ mod tests {
.default_handler(|req: ServiceRequest| {
ok(req.into_response(HttpResponse::Ok().body("default content")))
})
.path_filter(|path| path.extension() == Some("png".as_ref()))
.path_filter(|path, _| path.extension() == Some("png".as_ref()))
.new_service(())
.await
.unwrap();

View File

@ -83,14 +83,8 @@ impl Service<ServiceRequest> for FilesService {
Err(e) => return Box::pin(ok(req.error_response(e))),
};
// full file path
let path = self.directory.join(&real_path);
if let Err(err) = path.canonicalize() {
return Box::pin(self.handle_err(err, req));
}
if let Some(filter) = &self.path_filter {
if !filter(real_path.as_ref()) {
if !filter(real_path.as_ref(), req.head()) {
if let Some(ref default) = self.default {
return Box::pin(default.call(req));
} else {
@ -101,6 +95,12 @@ impl Service<ServiceRequest> for FilesService {
}
}
// full file path
let path = self.directory.join(&real_path);
if let Err(err) = path.canonicalize() {
return Box::pin(self.handle_err(err, req));
}
if path.is_dir() {
if self.redirect_to_slash
&& !req.path().ends_with('/')