Skip to content

Commit

Permalink
Merge pull request #55 from joepio/master
Browse files Browse the repository at this point in the history
#54 Add `skip_handler_when_not_found` option
  • Loading branch information
kilork authored Feb 12, 2023
2 parents 4187120 + 3b4b2e3 commit c363721
Showing 1 changed file with 40 additions and 4 deletions.
44 changes: 40 additions & 4 deletions src/resource_files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ use actix_web::{
header::{self, ContentType},
Method, StatusCode,
},
HttpMessage, HttpRequest, HttpResponse, ResponseError,
HttpMessage, HttpRequest, HttpResponse, ResponseError, guard::{Guard, GuardContext},
};
use derive_more::{Deref, Display, Error};
use futures_util::future::{ok, FutureExt, LocalBoxFuture, Ready};
use static_files::Resource;
use std::{collections::HashMap, ops::Deref, rc::Rc};
use std::{collections::{HashMap, HashSet}, ops::Deref, rc::Rc};

/// Static resource files handling
///
Expand All @@ -38,8 +38,10 @@ use std::{collections::HashMap, ops::Deref, rc::Rc};
/// }
/// ```
#[allow(clippy::needless_doctest_main)]
#[derive(Clone)]
pub struct ResourceFiles {
not_resolve_defaults: bool,
use_guard: bool,
not_found_resolves_to: Option<String>,
inner: Rc<ResourceFilesInner>,
}
Expand All @@ -61,6 +63,7 @@ impl ResourceFiles {
inner: Rc::new(inner),
not_resolve_defaults: false,
not_found_resolves_to: None,
use_guard: false,
}
}

Expand All @@ -85,6 +88,15 @@ impl ResourceFiles {
pub fn resolve_not_found_to_root(self) -> Self {
self.resolve_not_found_to(INDEX_HTML)
}

/// If this is called, we will use an [actix_web::guard::Guard] to check if this request should be handled.
/// If set to true, we skip using the handler for files that haven't been found, instead of sending 404s.
///
/// Can be useful if you want to share files on a (sub)path that's also used by a different route handler.
pub fn skip_handler_when_not_found(mut self) -> Self {
self.use_guard = true;
self
}
}

impl Deref for ResourceFiles {
Expand All @@ -95,6 +107,24 @@ impl Deref for ResourceFiles {
}
}

struct ResourceFilesGuard {
filenames: HashSet<String>,
}

impl Guard for ResourceFilesGuard {
fn check(&self, ctx: &GuardContext<'_>) -> bool {
self.filenames.contains(ctx.head().uri.path().trim_start_matches('/'))
}
}

impl From<&ResourceFiles> for ResourceFilesGuard {
fn from(files: &ResourceFiles) -> Self {
Self {
filenames: files.files.keys().map(|s| s.to_string()).collect(),
}
}
}

impl HttpServiceFactory for ResourceFiles {
fn register(self, config: &mut AppService) {
let prefix = self.path.trim_start_matches('/');
Expand All @@ -103,7 +133,13 @@ impl HttpServiceFactory for ResourceFiles {
} else {
ResourceDef::prefix(prefix)
};
config.register_service(rdef, None, self, None)
let guards: Option<Vec<Box<dyn Guard>>> = if self.use_guard {
let guard: ResourceFilesGuard = (&self).into();
Some(vec!(Box::new(guard)))
} else {
None
};
config.register_service(rdef, guards, self, None);
}
}

Expand Down Expand Up @@ -133,7 +169,7 @@ pub struct ResourceFilesService {
inner: Rc<ResourceFilesInner>,
}

impl<'a> Service<ServiceRequest> for ResourceFilesService {
impl Service<ServiceRequest> for ResourceFilesService {
type Response = ServiceResponse;
type Error = Error;
type Future = Ready<Result<Self::Response, Self::Error>>;
Expand Down

0 comments on commit c363721

Please sign in to comment.