@@ -32,8 +32,8 @@ use termcolor::{Color, ColorSpec};
3232
3333use color:: { build_spec, Printer } ;
3434use util:: {
35- enable_string, encode_link_path, error_io2iron, error_resp, now_string,
36- system_time_to_date_time, StringError , ROOT_LINK ,
35+ enable_string, encode_link_path, error_io2iron, error_resp, now_string, root_link ,
36+ system_time_to_date_time, StringError ,
3737} ;
3838
3939use middlewares:: { AuthChecker , CompressionHandler , RequestLogger } ;
@@ -209,6 +209,12 @@ fn main() {
209209 . long ( "open" )
210210 . short ( "o" )
211211 . help ( "Open the page in the default browser" ) )
212+ . arg ( clap:: Arg :: with_name ( "base-url" )
213+ . short ( "b" )
214+ . long ( "base-url" )
215+ . default_value ( "/" )
216+ . takes_value ( true )
217+ . help ( "Base URL to prepend in directory indexes. For reverse proxying. This prefix is supposed to be pre-stripped when reaching simple-http-server." ) )
212218 . get_matches ( ) ;
213219
214220 let root = matches
@@ -273,6 +279,7 @@ fn main() {
273279 }
274280
275281 let silent = matches. is_present ( "silent" ) ;
282+ let base_url: & str = matches. value_of ( "base-url" ) . unwrap ( ) ;
276283
277284 let upload: Option < Upload > = if upload_arg {
278285 let token: String = thread_rng ( )
@@ -353,6 +360,7 @@ fn main() {
353360 . map ( |exts| exts. iter ( ) . map ( |s| format ! ( ".{}" , s) ) . collect ( ) ) ,
354361 try_file_404 : try_file_404. map ( PathBuf :: from) ,
355362 upload_size_limit,
363+ base_url : base_url. to_string ( ) ,
356364 } ) ;
357365 if cors {
358366 chain. link_around ( CorsMiddleware :: with_allow_any ( ) ) ;
@@ -376,6 +384,7 @@ fn main() {
376384 if !silent {
377385 chain. link_after ( RequestLogger {
378386 printer : Printer :: new ( ) ,
387+ base_url : base_url. to_string ( ) ,
379388 } ) ;
380389 }
381390 let mut server = Iron :: new ( chain) ;
@@ -433,6 +442,7 @@ struct MainHandler {
433442 compress : Option < Vec < String > > ,
434443 try_file_404 : Option < PathBuf > ,
435444 upload_size_limit : u64 ,
445+ base_url : String ,
436446}
437447
438448impl Handler for MainHandler {
@@ -475,9 +485,19 @@ impl Handler for MainHandler {
475485
476486 if self . upload . is_some ( ) && req. method == method:: Post {
477487 if let Err ( ( s, msg) ) = self . save_files ( req, & fs_path) {
478- return Ok ( error_resp ( s, & msg) ) ;
479- } else {
488+ return Ok ( error_resp ( s, & msg, & self . base_url ) ) ;
489+ } else if self . base_url == "/" {
480490 return Ok ( Response :: with ( ( status:: Found , Redirect ( req. url . clone ( ) ) ) ) ) ;
491+ } else {
492+ let mut inner_url: iron:: url:: Url = req. url . clone ( ) . into ( ) ;
493+ let mut path: & str = inner_url. path ( ) ;
494+ if path. starts_with ( '/' ) {
495+ path = & path[ 1 ..] ;
496+ }
497+ let new_path = format ! ( "{}{}" , self . base_url, path) ;
498+ inner_url. set_path ( & new_path) ;
499+ let new_url = iron:: Url :: from_generic_url ( inner_url) . unwrap ( ) ;
500+ return Ok ( Response :: with ( ( status:: Found , Redirect ( new_url) ) ) ) ;
481501 }
482502 }
483503
@@ -505,7 +525,7 @@ impl Handler for MainHandler {
505525 . iter ( )
506526 . map ( |s| s. to_string_lossy ( ) . to_string ( ) )
507527 . collect ( ) ;
508- self . list_directory ( req, & fs_path, & path_prefix)
528+ self . list_directory ( req, & fs_path, & path_prefix, & self . base_url [ .. ] )
509529 } else {
510530 self . send_file ( req, & fs_path)
511531 }
@@ -602,6 +622,7 @@ impl MainHandler {
602622 req : & mut Request ,
603623 fs_path : & Path ,
604624 path_prefix : & [ String ] ,
625+ base_url : & str ,
605626 ) -> IronResult < Response > {
606627 struct Entry {
607628 filename : String ,
@@ -628,16 +649,17 @@ impl MainHandler {
628649 let mut bread_links: Vec < String > = vec ! [ breadcrumb. pop( ) . unwrap( ) ] ;
629650 while !breadcrumb. is_empty ( ) {
630651 bread_links. push ( format ! (
631- r#"<a href="/ {link}/"><strong>{label}</strong></a>"# ,
652+ r#"<a href="{base_url} {link}/"><strong>{label}</strong></a>"# ,
632653 link = encode_link_path( & breadcrumb) ,
633654 label = encode_minimal( & breadcrumb. pop( ) . unwrap( ) . to_owned( ) ) ,
655+ base_url = base_url,
634656 ) ) ;
635657 }
636- bread_links. push ( ROOT_LINK . to_owned ( ) ) ;
658+ bread_links. push ( root_link ( base_url ) ) ;
637659 bread_links. reverse ( ) ;
638660 bread_links. join ( " / " )
639661 } else {
640- ROOT_LINK . to_owned ( )
662+ root_link ( base_url )
641663 } ;
642664
643665 // Sort links
@@ -709,16 +731,17 @@ impl MainHandler {
709731 format ! (
710732 r#"
711733<tr>
712- <th><a href="/ {link}?sort=name&order={name_order}">Name</a></th>
713- <th><a href="/ {link}?sort=modified&order={modified_order}">Last modified</a></th>
714- <th><a href="/ {link}?sort=size&order={size_order}">Size</a></th>
734+ <th><a href="{base_url} {link}?sort=name&order={name_order}">Name</a></th>
735+ <th><a href="{base_url} {link}?sort=modified&order={modified_order}">Last modified</a></th>
736+ <th><a href="{base_url} {link}?sort=size&order={size_order}">Size</a></th>
715737</tr>
716738<tr><td style="border-top:1px dashed #BBB;" colspan="5"></td></tr>
717739"# ,
718740 link = encode_link_path( & current_link) ,
719741 name_order = order_labels. get( "name" ) . unwrap_or( & DEFAULT_ORDER ) ,
720742 modified_order = order_labels. get( "modified" ) . unwrap_or( & DEFAULT_ORDER ) ,
721- size_order = order_labels. get( "size" ) . unwrap_or( & DEFAULT_ORDER )
743+ size_order = order_labels. get( "size" ) . unwrap_or( & DEFAULT_ORDER ) ,
744+ base_url = base_url,
722745 )
723746 } else {
724747 "" . to_owned ( )
@@ -734,12 +757,13 @@ impl MainHandler {
734757 rows. push ( format ! (
735758 r#"
736759<tr>
737- <td><a href="/ {link}"><strong>[Up]</strong></a></td>
760+ <td><a href="{base_url} {link}"><strong>[Up]</strong></a></td>
738761 <td></td>
739762 <td></td>
740763</tr>
741764"# ,
742- link = encode_link_path( & link)
765+ link = encode_link_path( & link) ,
766+ base_url = base_url,
743767 ) ) ;
744768 } else {
745769 rows. push ( r#"<tr><td> </td></tr>"# . to_owned ( ) ) ;
@@ -789,7 +813,7 @@ impl MainHandler {
789813 rows. push ( format ! (
790814 r#"
791815<tr>
792- <td><a {linkstyle} href="/ {link}">{label}</a></td>
816+ <td><a {linkstyle} href="{base_url} {link}">{label}</a></td>
793817 <td style="color:#888;">[{modified}]</td>
794818 <td><bold>{filesize}</bold></td>
795819</tr>
@@ -798,22 +822,24 @@ impl MainHandler {
798822 link = encode_link_path( & link) ,
799823 label = encode_minimal( & file_name_label) ,
800824 modified = file_modified,
801- filesize = file_size
825+ filesize = file_size,
826+ base_url = base_url,
802827 ) ) ;
803828 }
804829
805830 // Optional upload form
806831 let upload_form = if self . upload . is_some ( ) {
807832 format ! (
808833 r#"
809- <form style="margin-top:1em; margin-bottom:1em;" action="/ {path}" method="POST" enctype="multipart/form-data">
834+ <form style="margin-top:1em; margin-bottom:1em;" action="{base_url} {path}" method="POST" enctype="multipart/form-data">
810835 <input type="file" name="files" accept="*" multiple />
811836 <input type="hidden" name="csrf" value="{csrf}"/>
812837 <input type="submit" value="Upload" />
813838</form>
814839"# ,
815840 path = encode_link_path( path_prefix) ,
816- csrf = self . upload. as_ref( ) . unwrap( ) . csrf_token
841+ csrf = self . upload. as_ref( ) . unwrap( ) . csrf_token,
842+ base_url = base_url,
817843 )
818844 } else {
819845 "" . to_owned ( )
0 commit comments