@@ -21,16 +21,12 @@ pub fn append_headers(uri: &str, resp: &mut Response<Body>) {
2121 // Default max-age value in seconds (one day)
2222 let mut max_age = MAX_AGE_ONE_DAY ;
2323
24- if CACHE_EXT_ONE_HOUR
25- . iter ( )
26- . any ( |x| uri. ends_with ( & [ "." , * x] . concat ( ) ) )
27- {
28- max_age = MAX_AGE_ONE_HOUR ;
29- } else if CACHE_EXT_ONE_YEAR
30- . iter ( )
31- . any ( |x| uri. ends_with ( & [ "." , * x] . concat ( ) ) )
32- {
33- max_age = MAX_AGE_ONE_YEAR ;
24+ if let Some ( extension) = uri_file_extension ( uri) {
25+ if CACHE_EXT_ONE_HOUR . binary_search ( & extension) . is_ok ( ) {
26+ max_age = MAX_AGE_ONE_HOUR ;
27+ } else if CACHE_EXT_ONE_YEAR . binary_search ( & extension) . is_ok ( ) {
28+ max_age = MAX_AGE_ONE_YEAR ;
29+ }
3430 }
3531
3632 let cache_control = CacheControl :: new ( )
@@ -44,13 +40,20 @@ fn duration_from_secs(secs: u64) -> std::time::Duration {
4440 std:: time:: Duration :: from_secs ( std:: cmp:: min ( secs, u32:: MAX as u64 ) )
4541}
4642
43+ /// Gets the file extension for a URI.
44+ ///
45+ /// This assumes the extension contains a single dot. e.g. for "/file.tar.gz" it returns "gz".
46+ fn uri_file_extension ( uri : & str ) -> Option < & str > {
47+ uri. rsplit_once ( '.' ) . map ( |( _, rest) | rest)
48+ }
49+
4750#[ cfg( test) ]
4851mod tests {
4952 use hyper:: { Body , Response , StatusCode } ;
5053
5154 use super :: {
52- append_headers, CACHE_EXT_ONE_HOUR , CACHE_EXT_ONE_YEAR , MAX_AGE_ONE_DAY , MAX_AGE_ONE_HOUR ,
53- MAX_AGE_ONE_YEAR ,
55+ append_headers, uri_file_extension , CACHE_EXT_ONE_HOUR , CACHE_EXT_ONE_YEAR ,
56+ MAX_AGE_ONE_DAY , MAX_AGE_ONE_HOUR , MAX_AGE_ONE_YEAR ,
5457 } ;
5558
5659 #[ tokio:: test]
@@ -101,4 +104,11 @@ mod tests {
101104 ) ;
102105 }
103106 }
107+
108+ #[ test]
109+ fn find_uri_extension ( ) {
110+ assert_eq ! ( uri_file_extension( "/potato.zip" ) , Some ( "zip" ) ) ;
111+ assert_eq ! ( uri_file_extension( "/potato." ) , Some ( "" ) ) ;
112+ assert_eq ! ( uri_file_extension( "/" ) , None ) ;
113+ }
104114}
0 commit comments