17
17
use std:: path:: { PathBuf , Path } ;
18
18
19
19
use rocket:: { Request , Data , Route } ;
20
- use rocket:: http:: { Method , Status , uri:: Segments } ;
20
+ use rocket:: http:: { Method , uri:: Segments } ;
21
21
use rocket:: handler:: { Handler , Outcome } ;
22
22
use rocket:: response:: NamedFile ;
23
- use rocket:: outcome:: IntoOutcome ;
24
23
25
24
/// A bitset representing configurable options for the [`StaticFiles`] handler.
26
25
///
@@ -101,19 +100,21 @@ impl std::ops::BitOr for Options {
101
100
/// local file system. To use it, construct a `StaticFiles` using either
102
101
/// [`StaticFiles::from()`] or [`StaticFiles::new()`] then simply `mount` the
103
102
/// handler at a desired path. When mounted, the handler will generate route(s)
104
- /// that serve the desired static files.
103
+ /// that serve the desired static files. If a requested file is not found, the
104
+ /// routes _forward_ the incoming request. The default rank of the generated
105
+ /// routes is `10`. To customize route ranking, use the [`StaticFiles::rank()`]
106
+ /// method.
105
107
///
106
108
/// # Options
107
109
///
108
110
/// The handler's functionality can be customized by passing an [`Options`] to
109
- /// [`StaticFiles::new()`]. Additionally, the rank of generate routes, which
110
- /// defaults to `10`, can be set via the [`StaticFiles::rank()`] builder method.
111
+ /// [`StaticFiles::new()`].
111
112
///
112
113
/// # Example
113
114
///
114
- /// To serve files from the `/static` directory at the `/public` path, allowing
115
- /// `index.html` files to be used to respond to requests for a directory (the
116
- /// default), you might write the following:
115
+ /// To serve files from the `/static` local file system directory at the
116
+ /// `/public` path, allowing ` index.html` files to be used to respond to
117
+ /// requests for a directory (the default), you might write the following:
117
118
///
118
119
/// ```rust
119
120
/// # extern crate rocket;
@@ -129,10 +130,10 @@ impl std::ops::BitOr for Options {
129
130
/// }
130
131
/// ```
131
132
///
132
- /// With this set-up , requests for files at `/public/<path..>` will be handled
133
- /// by returning the contents of `/static/<path..>`. Requests for _directories_
134
- /// at `/public/<directory>` will be handled by returning the contents of
135
- /// `/static/<directory>/index.html`.
133
+ /// With this, requests for files at `/public/<path..>` will be handled by
134
+ /// returning the contents of `. /static/<path..>`. Requests for _directories_ at
135
+ /// `/public/<directory>` will be handled by returning the contents of
136
+ /// `. /static/<directory>/index.html`.
136
137
///
137
138
/// If your static files are stored relative to your crate and your project is
138
139
/// managed by Cargo, you should either use a relative path and ensure that your
@@ -272,21 +273,22 @@ impl Into<Vec<Route>> for StaticFiles {
272
273
}
273
274
274
275
impl Handler for StaticFiles {
275
- fn handle < ' r > ( & self , req : & ' r Request < ' _ > , _ : Data ) -> Outcome < ' r > {
276
- fn handle_index < ' r > ( opt : Options , r : & ' r Request < ' _ > , path : & Path ) -> Outcome < ' r > {
276
+ fn handle < ' r > ( & self , req : & ' r Request < ' _ > , data : Data ) -> Outcome < ' r > {
277
+ fn handle_dir < ' r > ( opt : Options , r : & ' r Request < ' _ > , d : Data , path : & Path ) -> Outcome < ' r > {
277
278
if !opt. contains ( Options :: Index ) {
278
- return Outcome :: failure ( Status :: NotFound ) ;
279
+ return Outcome :: forward ( d ) ;
279
280
}
280
281
281
- Outcome :: from ( r, NamedFile :: open ( path. join ( "index.html" ) ) . ok ( ) )
282
+ let file = NamedFile :: open ( path. join ( "index.html" ) ) . ok ( ) ;
283
+ Outcome :: from_or_forward ( r, d, file)
282
284
}
283
285
284
286
// If this is not the route with segments, handle it only if the user
285
287
// requested a handling of index files.
286
288
let current_route = req. route ( ) . expect ( "route while handling" ) ;
287
289
let is_segments_route = current_route. uri . path ( ) . ends_with ( ">" ) ;
288
290
if !is_segments_route {
289
- return handle_index ( self . options , req, & self . root ) ;
291
+ return handle_dir ( self . options , req, data , & self . root ) ;
290
292
}
291
293
292
294
// Otherwise, we're handling segments. Get the segments as a `PathBuf`,
@@ -295,13 +297,12 @@ impl Handler for StaticFiles {
295
297
let path = req. get_segments :: < Segments < ' _ > > ( 0 )
296
298
. and_then ( |res| res. ok ( ) )
297
299
. and_then ( |segments| segments. into_path_buf ( allow_dotfiles) . ok ( ) )
298
- . map ( |path| self . root . join ( path) )
299
- . into_outcome ( Status :: NotFound ) ?;
300
+ . map ( |path| self . root . join ( path) ) ;
300
301
301
- if path. is_dir ( ) {
302
- handle_index ( self . options , req, & path)
303
- } else {
304
- Outcome :: from ( req , NamedFile :: open ( & path ) . ok ( ) )
302
+ match & path {
303
+ Some ( path ) if path . is_dir ( ) => handle_dir ( self . options , req, data , path) ,
304
+ Some ( path ) => Outcome :: from_or_forward ( req , data , NamedFile :: open ( path ) . ok ( ) ) ,
305
+ None => Outcome :: forward ( data )
305
306
}
306
307
}
307
308
}
0 commit comments