@@ -17,7 +17,6 @@ use std::io;
1717use std:: ops:: Bound ;
1818use std:: path:: PathBuf ;
1919use std:: pin:: Pin ;
20- use std:: sync:: Arc ;
2120use std:: task:: Poll ;
2221use std:: time:: { SystemTime , UNIX_EPOCH } ;
2322use std:: { cmp, path:: Path } ;
@@ -27,16 +26,6 @@ use tokio_util::io::poll_read_buf;
2726
2827use crate :: error:: Result ;
2928
30- /// A small Arch `PathBuf` wrapper since Arc<PathBuf> doesn't implement AsRef<Path>.
31- #[ derive( Clone , Debug ) ]
32- pub struct ArcPath ( pub Arc < PathBuf > ) ;
33-
34- impl AsRef < Path > for ArcPath {
35- fn as_ref ( & self ) -> & Path {
36- ( * self . 0 ) . as_ref ( )
37- }
38- }
39-
4029/// Entry point to handle web server requests which map to specific files
4130/// on file system and return a file response.
4231pub async fn handle_request (
@@ -51,14 +40,13 @@ pub async fn handle_request(
5140 return Err ( StatusCode :: METHOD_NOT_ALLOWED ) ;
5241 }
5342
54- let base = Arc :: new ( base. into ( ) ) ;
55- let ( path, meta, auto_index) = path_from_tail ( base, uri_path) . await ?;
43+ let ( path, meta, auto_index) = path_from_tail ( base. into ( ) , uri_path) . await ?;
5644
5745 // Directory listing
5846 // 1. Check if "directory listing" feature is enabled,
5947 // if current path is a valid directory and
6048 // if it does not contain an `index.html` file
61- if dir_listing && auto_index && !path. as_ref ( ) . exists ( ) {
49+ if dir_listing && auto_index && !path. exists ( ) {
6250 // Redirect if current path does not end with a slash
6351 let current_path = uri_path;
6452 if !current_path. ends_with ( '/' ) {
@@ -79,10 +67,10 @@ pub async fn handle_request(
7967}
8068
8169fn path_from_tail (
82- base : Arc < PathBuf > ,
70+ base : PathBuf ,
8371 tail : & str ,
84- ) -> impl Future < Output = Result < ( ArcPath , Metadata , bool ) , StatusCode > > + Send {
85- future:: ready ( sanitize_path ( base. as_ref ( ) , tail) ) . and_then ( |mut buf| async {
72+ ) -> impl Future < Output = Result < ( PathBuf , Metadata , bool ) , StatusCode > > + Send {
73+ future:: ready ( sanitize_path ( base, tail) ) . and_then ( |mut buf| async {
8674 match tokio:: fs:: metadata ( & buf) . await {
8775 Ok ( meta) => {
8876 let mut auto_index = false ;
@@ -92,7 +80,7 @@ fn path_from_tail(
9280 auto_index = true ;
9381 }
9482 tracing:: trace!( "dir: {:?}" , buf) ;
95- Ok ( ( ArcPath ( Arc :: new ( buf) ) , meta, auto_index) )
83+ Ok ( ( buf, meta, auto_index) )
9684 }
9785 Err ( err) => {
9886 tracing:: debug!( "file not found: {:?}" , err) ;
@@ -104,11 +92,11 @@ fn path_from_tail(
10492
10593fn directory_listing (
10694 method : & Method ,
107- res : ( String , ArcPath ) ,
95+ res : ( String , PathBuf ) ,
10896) -> impl Future < Output = Result < Response < Body > , StatusCode > > + Send {
10997 let ( current_path, path) = res;
11098 let is_head = method == Method :: HEAD ;
111- let parent = path. as_ref ( ) . parent ( ) . unwrap ( ) ;
99+ let parent = path. parent ( ) . unwrap ( ) ;
112100 let parent = PathBuf :: from ( parent) ;
113101
114102 tokio:: fs:: read_dir ( parent) . then ( move |res| match res {
@@ -118,7 +106,7 @@ fn directory_listing(
118106 Err ( err) => {
119107 tracing:: error!(
120108 "error during directory entries reading (path={:?}): {} " ,
121- path. as_ref ( ) . parent( ) . unwrap( ) . display( ) ,
109+ path. parent( ) . unwrap( ) . display( ) ,
122110 err
123111 ) ;
124112 Err ( StatusCode :: INTERNAL_SERVER_ERROR )
@@ -128,20 +116,17 @@ fn directory_listing(
128116 Err ( err) => {
129117 let status = match err. kind ( ) {
130118 io:: ErrorKind :: NotFound => {
131- tracing:: debug!( "entry file not found: {:?}" , path. as_ref ( ) . display( ) ) ;
119+ tracing:: debug!( "entry file not found: {:?}" , path. display( ) ) ;
132120 StatusCode :: NOT_FOUND
133121 }
134122 io:: ErrorKind :: PermissionDenied => {
135- tracing:: warn!(
136- "entry file permission denied: {:?}" ,
137- path. as_ref( ) . display( )
138- ) ;
123+ tracing:: warn!( "entry file permission denied: {:?}" , path. display( ) ) ;
139124 StatusCode :: FORBIDDEN
140125 }
141126 _ => {
142127 tracing:: error!(
143128 "directory entries error (path={:?}): {} " ,
144- path. as_ref ( ) . display( ) ,
129+ path. display( ) ,
145130 err
146131 ) ;
147132 StatusCode :: INTERNAL_SERVER_ERROR
@@ -249,7 +234,7 @@ fn parse_last_modified(modified: SystemTime) -> Result<time::Tm, Box<dyn std::er
249234/// Reply with a file content.
250235fn file_reply (
251236 headers : & HeaderMap < HeaderValue > ,
252- res : ( ArcPath , Metadata , bool ) ,
237+ res : ( PathBuf , Metadata , bool ) ,
253238) -> impl Future < Output = Result < Response < Body > , StatusCode > > + Send {
254239 let ( path, meta, auto_index) = res;
255240 let conditionals = get_conditional_headers ( headers) ;
@@ -258,19 +243,15 @@ fn file_reply(
258243 Err ( err) => {
259244 let status = match err. kind ( ) {
260245 io:: ErrorKind :: NotFound => {
261- tracing:: debug!( "file not found: {:?}" , path. as_ref ( ) . display( ) ) ;
246+ tracing:: debug!( "file not found: {:?}" , path. display( ) ) ;
262247 StatusCode :: NOT_FOUND
263248 }
264249 io:: ErrorKind :: PermissionDenied => {
265- tracing:: warn!( "file permission denied: {:?}" , path. as_ref ( ) . display( ) ) ;
250+ tracing:: warn!( "file permission denied: {:?}" , path. display( ) ) ;
266251 StatusCode :: FORBIDDEN
267252 }
268253 _ => {
269- tracing:: error!(
270- "file open error (path={:?}): {} " ,
271- path. as_ref( ) . display( ) ,
272- err
273- ) ;
254+ tracing:: error!( "file open error (path={:?}): {} " , path. display( ) , err) ;
274255 StatusCode :: INTERNAL_SERVER_ERROR
275256 }
276257 } ;
@@ -293,16 +274,15 @@ fn get_conditional_headers(header_list: &HeaderMap<HeaderValue>) -> Conditionals
293274 }
294275}
295276
296- fn sanitize_path ( base : impl AsRef < Path > , tail : & str ) -> Result < PathBuf , StatusCode > {
297- let mut buf = PathBuf :: from ( base. as_ref ( ) ) ;
277+ fn sanitize_path ( mut buf : PathBuf , tail : & str ) -> Result < PathBuf , StatusCode > {
298278 let p = match percent_decode_str ( tail) . decode_utf8 ( ) {
299279 Ok ( p) => p,
300280 Err ( err) => {
301281 tracing:: debug!( "dir: failed to decode route={:?}: {:?}" , tail, err) ;
302282 return Err ( StatusCode :: UNSUPPORTED_MEDIA_TYPE ) ;
303283 }
304284 } ;
305- tracing:: trace!( "dir? base={:?}, route={:?}" , base . as_ref ( ) , p) ;
285+ tracing:: trace!( "dir? base={:?}, route={:?}" , buf , p) ;
306286 for seg in p. split ( '/' ) {
307287 if seg. starts_with ( ".." ) {
308288 tracing:: warn!( "dir: rejecting segment starting with '..'" ) ;
@@ -381,13 +361,13 @@ impl Conditionals {
381361
382362fn file_conditional (
383363 f : TkFile ,
384- path : ArcPath ,
364+ path : PathBuf ,
385365 meta : Metadata ,
386366 auto_index : bool ,
387367 conditionals : Conditionals ,
388368) -> impl Future < Output = Result < Response < Body > , StatusCode > > + Send {
389369 file_metadata ( f, meta, auto_index)
390- . map_ok ( |( file, meta) | response_body ( file, meta, path, conditionals) )
370+ . map_ok ( |( file, meta) | response_body ( file, & meta, path, conditionals) )
391371}
392372
393373async fn file_metadata (
@@ -409,8 +389,8 @@ async fn file_metadata(
409389
410390fn response_body (
411391 file : TkFile ,
412- meta : Metadata ,
413- path : ArcPath ,
392+ meta : & Metadata ,
393+ path : PathBuf ,
414394 conditionals : Conditionals ,
415395) -> Response < Body > {
416396 let mut len = meta. len ( ) ;
@@ -421,7 +401,7 @@ fn response_body(
421401 bytes_range ( range, len)
422402 . map ( |( start, end) | {
423403 let sub_len = end - start;
424- let buf_size = optimal_buf_size ( & meta) ;
404+ let buf_size = optimal_buf_size ( meta) ;
425405 let stream = file_stream ( file, buf_size, ( start, end) ) ;
426406 let body = Body :: wrap_stream ( stream) ;
427407
@@ -436,7 +416,7 @@ fn response_body(
436416 len = sub_len;
437417 }
438418
439- let mime = mime_guess:: from_path ( path. as_ref ( ) ) . first_or_octet_stream ( ) ;
419+ let mime = mime_guess:: from_path ( path) . first_or_octet_stream ( ) ;
440420
441421 resp. headers_mut ( ) . typed_insert ( ContentLength ( len) ) ;
442422 resp. headers_mut ( ) . typed_insert ( ContentType :: from ( mime) ) ;
@@ -602,14 +582,14 @@ mod tests {
602582 }
603583
604584 assert_eq ! (
605- sanitize_path( base, "/foo.html" ) . unwrap( ) ,
585+ sanitize_path( base. into ( ) , "/foo.html" ) . unwrap( ) ,
606586 p( "/var/www/foo.html" )
607587 ) ;
608588
609589 // bad paths
610- sanitize_path ( base, "/../foo.html" ) . expect_err ( "dot dot" ) ;
590+ sanitize_path ( base. into ( ) , "/../foo.html" ) . expect_err ( "dot dot" ) ;
611591
612- sanitize_path ( base, "/C:\\ /foo.html" ) . expect_err ( "C:\\ " ) ;
592+ sanitize_path ( base. into ( ) , "/C:\\ /foo.html" ) . expect_err ( "C:\\ " ) ;
613593 }
614594
615595 #[ test]
0 commit comments