@@ -10,7 +10,7 @@ use std::net::TcpStream;
10
10
use std:: net:: { SocketAddr , ToSocketAddrs } ;
11
11
use std:: sync:: { Arc , Mutex } ;
12
12
use std:: time:: { Duration , Instant } ;
13
- use std:: { error, fmt, io, net, thread} ;
13
+ use std:: { error, fmt, io, net, num , thread} ;
14
14
15
15
use base64;
16
16
use serde;
@@ -157,12 +157,21 @@ impl SimpleHttpTransport {
157
157
158
158
// Parse first HTTP response header line
159
159
let http_response = get_line ( & mut reader, request_deadline) ?;
160
- if http_response. len ( ) < 12 || !http_response. starts_with ( "HTTP/1.1 " ) {
161
- return Err ( Error :: HttpParseError ) ;
160
+ if http_response. len ( ) < 12 {
161
+ return Err ( Error :: HttpResponseTooShort { actual : http_response. len ( ) , needed : 12 } ) ;
162
+ }
163
+ if !http_response. starts_with ( "HTTP/1.1 " ) {
164
+ return Err ( Error :: HttpResponseBadHello {
165
+ actual : String :: from_utf8_lossy ( & http_response. as_bytes ( ) [ 0 ..9 ] ) . into ( ) ,
166
+ expected : "HTTP/1.1 " . into ( ) ,
167
+ } ) ;
162
168
}
163
169
let response_code = match http_response[ 9 ..12 ] . parse :: < u16 > ( ) {
164
170
Ok ( n) => n,
165
- Err ( _) => return Err ( Error :: HttpParseError ) ,
171
+ Err ( e) => return Err ( Error :: HttpResponseBadStatus (
172
+ String :: from_utf8_lossy ( & http_response. as_bytes ( ) [ 9 ..12 ] ) . into ( ) ,
173
+ e,
174
+ ) ) ,
166
175
} ;
167
176
168
177
// Parse response header fields
@@ -180,7 +189,7 @@ impl SimpleHttpTransport {
180
189
line[ CONTENT_LENGTH . len ( ) ..]
181
190
. trim ( )
182
191
. parse :: < usize > ( )
183
- . map_err ( |_ | Error :: HttpParseError ) ? ,
192
+ . map_err ( |e | Error :: HttpResponseBadContentLength ( line [ CONTENT_LENGTH . len ( ) .. ] . into ( ) , e ) ) ?
184
193
) ;
185
194
}
186
195
}
@@ -224,6 +233,24 @@ pub enum Error {
224
233
} ,
225
234
/// An error occurred on the socket layer.
226
235
SocketError ( io:: Error ) ,
236
+ /// The HTTP response was too short to even fit a HTTP 1.1 header
237
+ HttpResponseTooShort {
238
+ /// The total length of the response
239
+ actual : usize ,
240
+ /// Minimum length we can parse
241
+ needed : usize ,
242
+ } ,
243
+ /// The HTTP response did not start with HTTP/1.1
244
+ HttpResponseBadHello {
245
+ /// Actual HTTP-whatever string
246
+ actual : String ,
247
+ /// The hello string of the HTTP version we support
248
+ expected : String ,
249
+ } ,
250
+ /// Could not parse the status value as a number
251
+ HttpResponseBadStatus ( String , num:: ParseIntError ) ,
252
+ /// Could not parse the status value as a number
253
+ HttpResponseBadContentLength ( String , num:: ParseIntError ) ,
227
254
/// The HTTP header of the response couldn't be parsed.
228
255
HttpParseError ,
229
256
/// Unexpected HTTP error code (non-200).
@@ -252,6 +279,18 @@ impl fmt::Display for Error {
252
279
ref reason,
253
280
} => write ! ( f, "invalid URL '{}': {}" , url, reason) ,
254
281
Error :: SocketError ( ref e) => write ! ( f, "Couldn't connect to host: {}" , e) ,
282
+ Error :: HttpResponseTooShort { ref actual, ref needed } => {
283
+ write ! ( f, "HTTP response too short: length {}, needed {}." , actual, needed)
284
+ } ,
285
+ Error :: HttpResponseBadHello { ref actual, ref expected } => {
286
+ write ! ( f, "HTTP response started with `{}`; expected `{}`." , actual, expected)
287
+ } ,
288
+ Error :: HttpResponseBadStatus ( ref status, ref err) => {
289
+ write ! ( f, "HTTP response had bad status code `{}`: {}." , status, err)
290
+ } ,
291
+ Error :: HttpResponseBadContentLength ( ref len, ref err) => {
292
+ write ! ( f, "HTTP response had bad content length `{}`: {}." , len, err)
293
+ } ,
255
294
Error :: HttpParseError => f. write_str ( "Couldn't parse response header." ) ,
256
295
Error :: HttpErrorCode ( c) => write ! ( f, "unexpected HTTP code: {}" , c) ,
257
296
Error :: Timeout => f. write_str ( "Didn't receive response data in time, timed out." ) ,
@@ -268,6 +307,10 @@ impl error::Error for Error {
268
307
InvalidUrl {
269
308
..
270
309
}
310
+ | HttpResponseTooShort { .. }
311
+ | HttpResponseBadHello { .. }
312
+ | HttpResponseBadStatus ( ..)
313
+ | HttpResponseBadContentLength ( ..)
271
314
| HttpParseError
272
315
| HttpErrorCode ( _)
273
316
| Timeout => None ,
0 commit comments