@@ -13,39 +13,52 @@ use status;
13
13
use version;
14
14
use rfc7230:: { CR , LF , LINE_ENDING } ;
15
15
16
+ /// Phantom type indicating Headers and StatusCode have not been written.
17
+ pub struct Fresh ;
18
+
19
+ /// Phantom type indicating Headers and StatusCode have been written.
20
+ pub struct Streaming ;
21
+
22
+ /// The status of a Response, indicating if the headers and status have been written.
23
+ pub trait WriteStatus { }
24
+
25
+ impl WriteStatus for Streaming { }
26
+ impl WriteStatus for Fresh { }
16
27
17
28
/// The outgoing half for a Tcp connection, created by a `Server` and given to a `Handler`.
18
- pub struct Response {
19
- /// The status code for the request.
20
- pub status : status:: StatusCode ,
21
- /// The outgoing headers on this response.
22
- pub headers : header:: Headers ,
29
+ pub struct Response < W : WriteStatus > {
23
30
/// The HTTP version of this response.
24
31
pub version : version:: HttpVersion ,
25
-
26
- headers_written : bool , // TODO: can this check be moved to compile time?
32
+ // Stream the Response is writing to, not accessible through UnwrittenResponse
27
33
body : BufferedWriter < TcpStream > , // TODO: use a HttpWriter from rfc7230
34
+ // The status code for the request.
35
+ status : status:: StatusCode ,
36
+ // The outgoing headers on this response.
37
+ headers : header:: Headers
28
38
}
29
39
30
- impl Response {
40
+ impl < W : WriteStatus > Response < W > {
41
+ /// The status of this response.
42
+ #[ inline]
43
+ pub fn status ( & self ) -> status:: StatusCode { self . status }
31
44
45
+ /// The headers of this response.
46
+ pub fn headers ( & self ) -> & header:: Headers { & self . headers }
47
+ }
48
+
49
+ impl Response < Fresh > {
32
50
/// Creates a new Response that can be used to write to a network stream.
33
- pub fn new ( tcp : TcpStream ) -> Response {
51
+ pub fn new ( tcp : TcpStream ) -> Response < Fresh > {
34
52
Response {
35
53
status : status:: Ok ,
36
54
version : version:: Http11 ,
37
55
headers : header:: Headers :: new ( ) ,
38
- headers_written : false ,
39
56
body : BufferedWriter :: new ( tcp)
40
57
}
41
58
}
42
59
43
- fn write_head ( & mut self ) -> IoResult < ( ) > {
44
- if self . headers_written {
45
- debug ! ( "headers previously written, nooping" ) ;
46
- return Ok ( ( ) ) ;
47
- }
48
- self . headers_written = true ;
60
+ /// Consume this Response<Fresh>, writing the Headers and Status and creating a Response<Streaming>
61
+ pub fn start ( mut self ) -> IoResult < Response < Streaming > > {
49
62
debug ! ( "writing head: {} {}" , self . version, self . status) ;
50
63
try!( write ! ( self . body, "{} {}{}{}" , self . version, self . status, CR as char , LF as char ) ) ;
51
64
@@ -59,30 +72,41 @@ impl Response {
59
72
try!( self . body . write ( LINE_ENDING ) ) ;
60
73
}
61
74
62
- self . body . write ( LINE_ENDING )
75
+ try!( self . body . write ( LINE_ENDING ) ) ;
76
+
77
+ // "copy" to change the phantom type
78
+ Ok ( Response {
79
+ version : self . version ,
80
+ body : self . body ,
81
+ status : self . status ,
82
+ headers : self . headers
83
+ } )
63
84
}
64
85
86
+ /// Get a mutable reference to the status.
87
+ #[ inline]
88
+ pub fn status_mut ( & mut self ) -> & mut status:: StatusCode { & mut self . status }
89
+
90
+ /// Get a mutable reference to the Headers.
91
+ pub fn headers_mut ( & mut self ) -> & mut header:: Headers { & mut self . headers }
92
+ }
93
+
94
+ impl Response < Streaming > {
65
95
/// Flushes all writing of a response to the client.
66
96
pub fn end ( mut self ) -> IoResult < ( ) > {
67
97
debug ! ( "ending" ) ;
68
98
self . flush ( )
69
99
}
70
100
}
71
101
72
-
73
- impl Writer for Response {
102
+ impl Writer for Response < Streaming > {
74
103
fn write ( & mut self , msg : & [ u8 ] ) -> IoResult < ( ) > {
75
- if !self . headers_written {
76
- try!( self . write_head ( ) ) ;
77
- }
78
104
debug ! ( "write {:u} bytes" , msg. len( ) ) ;
79
105
self . body . write ( msg)
80
106
}
81
107
82
108
fn flush ( & mut self ) -> IoResult < ( ) > {
83
- if !self . headers_written {
84
- try!( self . write_head ( ) ) ;
85
- }
86
109
self . body . flush ( )
87
110
}
88
111
}
112
+
0 commit comments