1
- extern crate mime = "mime-types" ;
2
1
extern crate conduit;
2
+ extern crate mime = "mime-types" ;
3
+ extern crate time;
3
4
4
5
use std:: fmt:: Show ;
5
6
use std:: collections:: HashMap ;
@@ -36,10 +37,28 @@ impl Handler for Static {
36
37
}
37
38
38
39
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 ( ) ;
40
56
41
57
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" ) ] ) ;
43
62
44
63
Ok ( Response {
45
64
status : ( 200 , "OK" ) ,
@@ -52,27 +71,65 @@ impl Handler for Static {
52
71
#[ cfg( test) ]
53
72
mod tests {
54
73
extern crate test = "conduit-test" ;
74
+
75
+ use std:: io:: { fs, File , TempDir , UserRWX } ;
76
+
55
77
use conduit;
56
78
use conduit:: Handler ;
57
79
use Static ;
58
80
59
81
#[ test]
60
82
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 ( ) ;
63
87
let mut req = test:: MockRequest :: new ( conduit:: Get , "/Cargo.toml" ) ;
64
88
let mut res = handler. call ( & mut req) . ok ( ) . expect ( "No response" ) ;
65
89
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( ) ] ) ) ;
68
95
}
69
96
70
97
#[ test]
71
98
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 ( ) ) ;
74
105
let mut req = test:: MockRequest :: new ( conduit:: Get , "/src/fixture.css" ) ;
75
106
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( ) ) ;
77
134
}
78
135
}
0 commit comments