1- extern crate mime = "mime-types" ;
21extern crate conduit;
2+ extern crate mime = "mime-types" ;
3+ extern crate time;
34
45use std:: fmt:: Show ;
56use std:: collections:: HashMap ;
@@ -36,10 +37,28 @@ impl Handler for Static {
3637 }
3738
3839 let mime = self . types . mime_for_path ( & path) ;
39- let file = try!( File :: open ( & path) . map_err ( |e| box e as Box < Show > ) ) ;
40+ let mut file = match File :: open ( & path) {
41+ Ok ( f) => f,
42+ Err ( ..) => {
43+ return Ok ( Response {
44+ status : ( 404 , "Not Found" ) ,
45+ headers : HashMap :: new ( ) ,
46+ body : box NullReader ,
47+ } )
48+ }
49+ } ;
50+ let stat = try!( file. stat ( ) . map_err ( |e| box e as Box < Show > ) ) ;
51+ let ts = time:: Timespec {
52+ sec : ( stat. modified as i64 ) / 1000 ,
53+ nsec : ( ( stat. modified as i32 ) % 1000 ) * 1000
54+ } ;
55+ let tm = time:: at ( ts) . to_utc ( ) ;
4056
4157 let mut headers = HashMap :: new ( ) ;
42- headers. insert ( "Content-Type" . to_str ( ) , vec ! ( mime. to_str( ) ) ) ;
58+ headers. insert ( "Content-Type" . to_str ( ) , vec ! [ mime. to_str( ) ] ) ;
59+ headers. insert ( "Content-Length" . to_str ( ) , vec ! [ stat. size. to_str( ) ] ) ;
60+ headers. insert ( "Last-Modified" . to_str ( ) ,
61+ vec ! [ tm. strftime( "%a, %d %b %Y %T GMT" ) ] ) ;
4362
4463 Ok ( Response {
4564 status : ( 200 , "OK" ) ,
@@ -52,27 +71,65 @@ impl Handler for Static {
5271#[ cfg( test) ]
5372mod tests {
5473 extern crate test = "conduit-test" ;
74+
75+ use std:: io:: { fs, File , TempDir , UserRWX } ;
76+
5577 use conduit;
5678 use conduit:: Handler ;
5779 use Static ;
5880
5981 #[ test]
6082 fn test_static ( ) {
61- let root = Path :: new ( file ! ( ) ) . dir_path ( ) . dir_path ( ) ;
62- let handler = Static :: new ( root) ;
83+ let td = TempDir :: new ( "conduit-static" ) . unwrap ( ) ;
84+ let root = td. path ( ) ;
85+ let handler = Static :: new ( root. clone ( ) ) ;
86+ File :: create ( & root. join ( "Cargo.toml" ) ) . write ( b"[package]" ) . unwrap ( ) ;
6387 let mut req = test:: MockRequest :: new ( conduit:: Get , "/Cargo.toml" ) ;
6488 let mut res = handler. call ( & mut req) . ok ( ) . expect ( "No response" ) ;
6589 let body = res. body . read_to_str ( ) . ok ( ) . expect ( "No body" ) ;
66- assert ! ( body. as_slice( ) . contains( "[package]" ) , "The Cargo.toml was provided" ) ;
67- assert_eq ! ( res. headers. find_equiv( & "Content-Type" ) . expect( "No content-type" ) , & vec!( "text/plain" . to_str( ) ) ) ;
90+ assert_eq ! ( body. as_slice( ) , "[package]" ) ;
91+ assert_eq ! ( res. headers. find_equiv( & "Content-Type" ) ,
92+ Some ( & vec!( "text/plain" . to_str( ) ) ) ) ;
93+ assert_eq ! ( res. headers. find_equiv( & "Content-Length" ) ,
94+ Some ( & vec![ "9" . to_str( ) ] ) ) ;
6895 }
6996
7097 #[ test]
7198 fn test_mime_types ( ) {
72- let root = Path :: new ( file ! ( ) ) . dir_path ( ) . dir_path ( ) ;
73- let handler = Static :: new ( root) ;
99+ let td = TempDir :: new ( "conduit-static" ) . unwrap ( ) ;
100+ let root = td. path ( ) ;
101+ fs:: mkdir ( & root. join ( "src" ) , UserRWX ) . unwrap ( ) ;
102+ File :: create ( & root. join ( "src/fixture.css" ) ) . unwrap ( ) ;
103+
104+ let handler = Static :: new ( root. clone ( ) ) ;
74105 let mut req = test:: MockRequest :: new ( conduit:: Get , "/src/fixture.css" ) ;
75106 let res = handler. call ( & mut req) . ok ( ) . expect ( "No response" ) ;
76- assert_eq ! ( res. headers. find_equiv( & "Content-Type" ) . expect( "No content-type" ) , & vec!( "text/css" . to_str( ) ) ) ;
107+ assert_eq ! ( res. headers. find_equiv( & "Content-Type" ) ,
108+ Some ( & vec!( "text/css" . to_str( ) ) ) ) ;
109+ assert_eq ! ( res. headers. find_equiv( & "Content-Length" ) ,
110+ Some ( & vec![ "0" . to_str( ) ] ) ) ;
111+ }
112+
113+ #[ test]
114+ fn test_missing ( ) {
115+ let td = TempDir :: new ( "conduit-static" ) . unwrap ( ) ;
116+ let root = td. path ( ) ;
117+
118+ let handler = Static :: new ( root. clone ( ) ) ;
119+ let mut req = test:: MockRequest :: new ( conduit:: Get , "/nope" ) ;
120+ let res = handler. call ( & mut req) . ok ( ) . expect ( "No response" ) ;
121+ assert_eq ! ( res. status. val0( ) , 404 ) ;
122+ }
123+
124+ #[ test]
125+ fn last_modified ( ) {
126+ let td = TempDir :: new ( "conduit-static" ) . unwrap ( ) ;
127+ let root = td. path ( ) ;
128+ File :: create ( & root. join ( "test" ) ) . unwrap ( ) ;
129+ let handler = Static :: new ( root. clone ( ) ) ;
130+ let mut req = test:: MockRequest :: new ( conduit:: Get , "/test" ) ;
131+ let res = handler. call ( & mut req) . ok ( ) . expect ( "No response" ) ;
132+ assert_eq ! ( res. status. val0( ) , 200 ) ;
133+ assert ! ( res. headers. find_equiv( & "Last-Modified" ) . is_some( ) ) ;
77134 }
78135}
0 commit comments