LEFT | RIGHT |
(no file at all) | |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // HTTP server. See RFC 2616. | 5 // HTTP server. See RFC 2616. |
6 | 6 |
7 package http | 7 package http |
8 | 8 |
9 import ( | 9 import ( |
10 "bufio" | 10 "bufio" |
11 "crypto/tls" | 11 "crypto/tls" |
12 "errors" | 12 "errors" |
13 "fmt" | 13 "fmt" |
14 "io" | 14 "io" |
15 "io/ioutil" | 15 "io/ioutil" |
16 "log" | 16 "log" |
17 "net" | 17 "net" |
18 "net/url" | 18 "net/url" |
| 19 "os" |
19 "path" | 20 "path" |
20 "runtime" | 21 "runtime" |
21 "strconv" | 22 "strconv" |
22 "strings" | 23 "strings" |
23 "sync" | 24 "sync" |
24 "time" | 25 "time" |
25 ) | 26 ) |
26 | 27 |
27 // Errors introduced by the HTTP server. | 28 // Errors introduced by the HTTP server. |
28 var ( | 29 var ( |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
338 if !w.wroteHeader { | 339 if !w.wroteHeader { |
339 w.Header().Set("Connection", "close") | 340 w.Header().Set("Connection", "close") |
340 } | 341 } |
341 } | 342 } |
342 | 343 |
343 // needsSniff reports whether a Content-Type still needs to be sniffed. | 344 // needsSniff reports whether a Content-Type still needs to be sniffed. |
344 func (w *response) needsSniff() bool { | 345 func (w *response) needsSniff() bool { |
345 return !w.cw.wroteHeader && w.handlerHeader.Get("Content-Type") == "" &&
w.written < sniffLen | 346 return !w.cw.wroteHeader && w.handlerHeader.Get("Content-Type") == "" &&
w.written < sniffLen |
346 } | 347 } |
347 | 348 |
| 349 // writerOnly hides an io.Writer value's optional ReadFrom method |
| 350 // from io.Copy. |
348 type writerOnly struct { | 351 type writerOnly struct { |
349 io.Writer | 352 io.Writer |
350 } | 353 } |
351 | 354 |
| 355 func srcIsRegularFile(src io.Reader) (isRegular bool, err error) { |
| 356 switch v := src.(type) { |
| 357 case *os.File: |
| 358 fi, err := v.Stat() |
| 359 if err != nil { |
| 360 return false, err |
| 361 } |
| 362 return fi.Mode().IsRegular(), nil |
| 363 case *io.LimitedReader: |
| 364 return srcIsRegularFile(v.R) |
| 365 default: |
| 366 return |
| 367 } |
| 368 } |
| 369 |
| 370 // ReadFrom is here to optimize copying from an *os.File regular file |
| 371 // to a *net.TCPConn with sendfile. |
352 func (w *response) ReadFrom(src io.Reader) (n int64, err error) { | 372 func (w *response) ReadFrom(src io.Reader) (n int64, err error) { |
| 373 // Our underlying w.conn.rwc is usually a *TCPConn (with its |
| 374 // own ReadFrom method). If not, or if our src isn't a regular |
| 375 // file, just fall back to the normal copy method. |
| 376 rf, ok := w.conn.rwc.(io.ReaderFrom) |
| 377 regFile, err := srcIsRegularFile(src) |
| 378 if err != nil { |
| 379 return 0, err |
| 380 } |
| 381 if !ok || !regFile { |
| 382 return io.Copy(writerOnly{w}, src) |
| 383 } |
| 384 |
| 385 // sendfile path: |
| 386 |
353 if !w.wroteHeader { | 387 if !w.wroteHeader { |
354 w.WriteHeader(StatusOK) | 388 w.WriteHeader(StatusOK) |
355 } | 389 } |
356 | 390 |
357 if w.needsSniff() { | 391 if w.needsSniff() { |
358 n0, err := io.Copy(writerOnly{w}, io.LimitReader(src, sniffLen)) | 392 n0, err := io.Copy(writerOnly{w}, io.LimitReader(src, sniffLen)) |
359 n += n0 | 393 n += n0 |
360 if err != nil { | 394 if err != nil { |
361 return n, err | 395 return n, err |
362 } | 396 } |
363 } | 397 } |
364 | 398 |
365 w.w.Flush() // get rid of any previous writes | 399 w.w.Flush() // get rid of any previous writes |
366 w.cw.flush() // make sure Header is written; flush data to rwc | 400 w.cw.flush() // make sure Header is written; flush data to rwc |
367 | 401 |
368 // Now that cw has been flushed, its chunking field is guaranteed initia
lized. | 402 // Now that cw has been flushed, its chunking field is guaranteed initia
lized. |
369 if !w.cw.chunking && w.bodyAllowed() { | 403 if !w.cw.chunking && w.bodyAllowed() { |
370 » » if rf, ok := w.conn.rwc.(io.ReaderFrom); ok { | 404 » » n0, err := rf.ReadFrom(src) |
371 » » » n0, err := rf.ReadFrom(src) | 405 » » n += n0 |
372 » » » n += n0 | 406 » » w.written += n0 |
373 » » » w.written += n0 | 407 » » return n, err |
374 » » » return n, err | 408 » } |
375 » » } | 409 |
376 » } | |
377 | |
378 » // Fall back to default io.Copy implementation. | |
379 » // Use wrapper to hide w.ReadFrom from io.Copy. | |
380 n0, err := io.Copy(writerOnly{w}, src) | 410 n0, err := io.Copy(writerOnly{w}, src) |
381 n += n0 | 411 n += n0 |
382 return n, err | 412 return n, err |
383 } | 413 } |
384 | 414 |
385 // noLimit is an effective infinite upper bound for io.LimitedReader | 415 // noLimit is an effective infinite upper bound for io.LimitedReader |
386 const noLimit int64 = (1 << 63) - 1 | 416 const noLimit int64 = (1 << 63) - 1 |
387 | 417 |
388 // debugServerConnections controls whether all server connections are wrapped | 418 // debugServerConnections controls whether all server connections are wrapped |
389 // with a verbose logging wrapper. | 419 // with a verbose logging wrapper. |
(...skipping 1501 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1891 log.Printf("%s.Read(%d) = %d, %v", c.name, len(p), n, err) | 1921 log.Printf("%s.Read(%d) = %d, %v", c.name, len(p), n, err) |
1892 return | 1922 return |
1893 } | 1923 } |
1894 | 1924 |
1895 func (c *loggingConn) Close() (err error) { | 1925 func (c *loggingConn) Close() (err error) { |
1896 log.Printf("%s.Close() = ...", c.name) | 1926 log.Printf("%s.Close() = ...", c.name) |
1897 err = c.Conn.Close() | 1927 err = c.Conn.Close() |
1898 log.Printf("%s.Close() = %v", c.name, err) | 1928 log.Printf("%s.Close() = %v", c.name, err) |
1899 return | 1929 return |
1900 } | 1930 } |
LEFT | RIGHT |