PageRenderTime 32ms CodeModel.GetById 0ms RepoModel.GetById 0ms app.codeStats 0ms

/third_party/gofrontend/libgo/go/net/http/transfer.go

http://github.com/axw/llgo
Go | 829 lines | 611 code | 72 blank | 146 comment | 237 complexity | 63e16a68851a9c959be1dfbd0243ea65 MD5 | raw file
Possible License(s): BSD-3-Clause, MIT
  1. // Copyright 2009 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package http
  5. import (
  6. "bufio"
  7. "bytes"
  8. "errors"
  9. "fmt"
  10. "io"
  11. "io/ioutil"
  12. "net/http/internal"
  13. "net/textproto"
  14. "sort"
  15. "strconv"
  16. "strings"
  17. "sync"
  18. )
  19. // ErrLineTooLong is returned when reading request or response bodies
  20. // with malformed chunked encoding.
  21. var ErrLineTooLong = internal.ErrLineTooLong
  22. type errorReader struct {
  23. err error
  24. }
  25. func (r errorReader) Read(p []byte) (n int, err error) {
  26. return 0, r.err
  27. }
  28. // transferWriter inspects the fields of a user-supplied Request or Response,
  29. // sanitizes them without changing the user object and provides methods for
  30. // writing the respective header, body and trailer in wire format.
  31. type transferWriter struct {
  32. Method string
  33. Body io.Reader
  34. BodyCloser io.Closer
  35. ResponseToHEAD bool
  36. ContentLength int64 // -1 means unknown, 0 means exactly none
  37. Close bool
  38. TransferEncoding []string
  39. Trailer Header
  40. IsResponse bool
  41. }
  42. func newTransferWriter(r interface{}) (t *transferWriter, err error) {
  43. t = &transferWriter{}
  44. // Extract relevant fields
  45. atLeastHTTP11 := false
  46. switch rr := r.(type) {
  47. case *Request:
  48. if rr.ContentLength != 0 && rr.Body == nil {
  49. return nil, fmt.Errorf("http: Request.ContentLength=%d with nil Body", rr.ContentLength)
  50. }
  51. t.Method = rr.Method
  52. t.Body = rr.Body
  53. t.BodyCloser = rr.Body
  54. t.ContentLength = rr.ContentLength
  55. t.Close = rr.Close
  56. t.TransferEncoding = rr.TransferEncoding
  57. t.Trailer = rr.Trailer
  58. atLeastHTTP11 = rr.ProtoAtLeast(1, 1)
  59. if t.Body != nil && len(t.TransferEncoding) == 0 && atLeastHTTP11 {
  60. if t.ContentLength == 0 {
  61. // Test to see if it's actually zero or just unset.
  62. var buf [1]byte
  63. n, rerr := io.ReadFull(t.Body, buf[:])
  64. if rerr != nil && rerr != io.EOF {
  65. t.ContentLength = -1
  66. t.Body = errorReader{rerr}
  67. } else if n == 1 {
  68. // Oh, guess there is data in this Body Reader after all.
  69. // The ContentLength field just wasn't set.
  70. // Stich the Body back together again, re-attaching our
  71. // consumed byte.
  72. t.ContentLength = -1
  73. t.Body = io.MultiReader(bytes.NewReader(buf[:]), t.Body)
  74. } else {
  75. // Body is actually empty.
  76. t.Body = nil
  77. t.BodyCloser = nil
  78. }
  79. }
  80. if t.ContentLength < 0 {
  81. t.TransferEncoding = []string{"chunked"}
  82. }
  83. }
  84. case *Response:
  85. t.IsResponse = true
  86. if rr.Request != nil {
  87. t.Method = rr.Request.Method
  88. }
  89. t.Body = rr.Body
  90. t.BodyCloser = rr.Body
  91. t.ContentLength = rr.ContentLength
  92. t.Close = rr.Close
  93. t.TransferEncoding = rr.TransferEncoding
  94. t.Trailer = rr.Trailer
  95. atLeastHTTP11 = rr.ProtoAtLeast(1, 1)
  96. t.ResponseToHEAD = noBodyExpected(t.Method)
  97. }
  98. // Sanitize Body,ContentLength,TransferEncoding
  99. if t.ResponseToHEAD {
  100. t.Body = nil
  101. if chunked(t.TransferEncoding) {
  102. t.ContentLength = -1
  103. }
  104. } else {
  105. if !atLeastHTTP11 || t.Body == nil {
  106. t.TransferEncoding = nil
  107. }
  108. if chunked(t.TransferEncoding) {
  109. t.ContentLength = -1
  110. } else if t.Body == nil { // no chunking, no body
  111. t.ContentLength = 0
  112. }
  113. }
  114. // Sanitize Trailer
  115. if !chunked(t.TransferEncoding) {
  116. t.Trailer = nil
  117. }
  118. return t, nil
  119. }
  120. func noBodyExpected(requestMethod string) bool {
  121. return requestMethod == "HEAD"
  122. }
  123. func (t *transferWriter) shouldSendContentLength() bool {
  124. if chunked(t.TransferEncoding) {
  125. return false
  126. }
  127. if t.ContentLength > 0 {
  128. return true
  129. }
  130. if t.ContentLength < 0 {
  131. return false
  132. }
  133. // Many servers expect a Content-Length for these methods
  134. if t.Method == "POST" || t.Method == "PUT" {
  135. return true
  136. }
  137. if t.ContentLength == 0 && isIdentity(t.TransferEncoding) {
  138. if t.Method == "GET" || t.Method == "HEAD" {
  139. return false
  140. }
  141. return true
  142. }
  143. return false
  144. }
  145. func (t *transferWriter) WriteHeader(w io.Writer) error {
  146. if t.Close {
  147. if _, err := io.WriteString(w, "Connection: close\r\n"); err != nil {
  148. return err
  149. }
  150. }
  151. // Write Content-Length and/or Transfer-Encoding whose values are a
  152. // function of the sanitized field triple (Body, ContentLength,
  153. // TransferEncoding)
  154. if t.shouldSendContentLength() {
  155. if _, err := io.WriteString(w, "Content-Length: "); err != nil {
  156. return err
  157. }
  158. if _, err := io.WriteString(w, strconv.FormatInt(t.ContentLength, 10)+"\r\n"); err != nil {
  159. return err
  160. }
  161. } else if chunked(t.TransferEncoding) {
  162. if _, err := io.WriteString(w, "Transfer-Encoding: chunked\r\n"); err != nil {
  163. return err
  164. }
  165. }
  166. // Write Trailer header
  167. if t.Trailer != nil {
  168. keys := make([]string, 0, len(t.Trailer))
  169. for k := range t.Trailer {
  170. k = CanonicalHeaderKey(k)
  171. switch k {
  172. case "Transfer-Encoding", "Trailer", "Content-Length":
  173. return &badStringError{"invalid Trailer key", k}
  174. }
  175. keys = append(keys, k)
  176. }
  177. if len(keys) > 0 {
  178. sort.Strings(keys)
  179. // TODO: could do better allocation-wise here, but trailers are rare,
  180. // so being lazy for now.
  181. if _, err := io.WriteString(w, "Trailer: "+strings.Join(keys, ",")+"\r\n"); err != nil {
  182. return err
  183. }
  184. }
  185. }
  186. return nil
  187. }
  188. func (t *transferWriter) WriteBody(w io.Writer) error {
  189. var err error
  190. var ncopy int64
  191. // Write body
  192. if t.Body != nil {
  193. if chunked(t.TransferEncoding) {
  194. if bw, ok := w.(*bufio.Writer); ok && !t.IsResponse {
  195. w = &internal.FlushAfterChunkWriter{bw}
  196. }
  197. cw := internal.NewChunkedWriter(w)
  198. _, err = io.Copy(cw, t.Body)
  199. if err == nil {
  200. err = cw.Close()
  201. }
  202. } else if t.ContentLength == -1 {
  203. ncopy, err = io.Copy(w, t.Body)
  204. } else {
  205. ncopy, err = io.Copy(w, io.LimitReader(t.Body, t.ContentLength))
  206. if err != nil {
  207. return err
  208. }
  209. var nextra int64
  210. nextra, err = io.Copy(ioutil.Discard, t.Body)
  211. ncopy += nextra
  212. }
  213. if err != nil {
  214. return err
  215. }
  216. if err = t.BodyCloser.Close(); err != nil {
  217. return err
  218. }
  219. }
  220. if !t.ResponseToHEAD && t.ContentLength != -1 && t.ContentLength != ncopy {
  221. return fmt.Errorf("http: ContentLength=%d with Body length %d",
  222. t.ContentLength, ncopy)
  223. }
  224. if chunked(t.TransferEncoding) {
  225. // Write Trailer header
  226. if t.Trailer != nil {
  227. if err := t.Trailer.Write(w); err != nil {
  228. return err
  229. }
  230. }
  231. // Last chunk, empty trailer
  232. _, err = io.WriteString(w, "\r\n")
  233. }
  234. return err
  235. }
  236. type transferReader struct {
  237. // Input
  238. Header Header
  239. StatusCode int
  240. RequestMethod string
  241. ProtoMajor int
  242. ProtoMinor int
  243. // Output
  244. Body io.ReadCloser
  245. ContentLength int64
  246. TransferEncoding []string
  247. Close bool
  248. Trailer Header
  249. }
  250. // bodyAllowedForStatus reports whether a given response status code
  251. // permits a body. See RFC2616, section 4.4.
  252. func bodyAllowedForStatus(status int) bool {
  253. switch {
  254. case status >= 100 && status <= 199:
  255. return false
  256. case status == 204:
  257. return false
  258. case status == 304:
  259. return false
  260. }
  261. return true
  262. }
  263. var (
  264. suppressedHeaders304 = []string{"Content-Type", "Content-Length", "Transfer-Encoding"}
  265. suppressedHeadersNoBody = []string{"Content-Length", "Transfer-Encoding"}
  266. )
  267. func suppressedHeaders(status int) []string {
  268. switch {
  269. case status == 304:
  270. // RFC 2616 section 10.3.5: "the response MUST NOT include other entity-headers"
  271. return suppressedHeaders304
  272. case !bodyAllowedForStatus(status):
  273. return suppressedHeadersNoBody
  274. }
  275. return nil
  276. }
  277. // msg is *Request or *Response.
  278. func readTransfer(msg interface{}, r *bufio.Reader) (err error) {
  279. t := &transferReader{RequestMethod: "GET"}
  280. // Unify input
  281. isResponse := false
  282. switch rr := msg.(type) {
  283. case *Response:
  284. t.Header = rr.Header
  285. t.StatusCode = rr.StatusCode
  286. t.ProtoMajor = rr.ProtoMajor
  287. t.ProtoMinor = rr.ProtoMinor
  288. t.Close = shouldClose(t.ProtoMajor, t.ProtoMinor, t.Header, true)
  289. isResponse = true
  290. if rr.Request != nil {
  291. t.RequestMethod = rr.Request.Method
  292. }
  293. case *Request:
  294. t.Header = rr.Header
  295. t.RequestMethod = rr.Method
  296. t.ProtoMajor = rr.ProtoMajor
  297. t.ProtoMinor = rr.ProtoMinor
  298. // Transfer semantics for Requests are exactly like those for
  299. // Responses with status code 200, responding to a GET method
  300. t.StatusCode = 200
  301. t.Close = rr.Close
  302. default:
  303. panic("unexpected type")
  304. }
  305. // Default to HTTP/1.1
  306. if t.ProtoMajor == 0 && t.ProtoMinor == 0 {
  307. t.ProtoMajor, t.ProtoMinor = 1, 1
  308. }
  309. // Transfer encoding, content length
  310. t.TransferEncoding, err = fixTransferEncoding(isResponse, t.RequestMethod, t.Header)
  311. if err != nil {
  312. return err
  313. }
  314. realLength, err := fixLength(isResponse, t.StatusCode, t.RequestMethod, t.Header, t.TransferEncoding)
  315. if err != nil {
  316. return err
  317. }
  318. if isResponse && t.RequestMethod == "HEAD" {
  319. if n, err := parseContentLength(t.Header.get("Content-Length")); err != nil {
  320. return err
  321. } else {
  322. t.ContentLength = n
  323. }
  324. } else {
  325. t.ContentLength = realLength
  326. }
  327. // Trailer
  328. t.Trailer, err = fixTrailer(t.Header, t.TransferEncoding)
  329. if err != nil {
  330. return err
  331. }
  332. // If there is no Content-Length or chunked Transfer-Encoding on a *Response
  333. // and the status is not 1xx, 204 or 304, then the body is unbounded.
  334. // See RFC2616, section 4.4.
  335. switch msg.(type) {
  336. case *Response:
  337. if realLength == -1 &&
  338. !chunked(t.TransferEncoding) &&
  339. bodyAllowedForStatus(t.StatusCode) {
  340. // Unbounded body.
  341. t.Close = true
  342. }
  343. }
  344. // Prepare body reader. ContentLength < 0 means chunked encoding
  345. // or close connection when finished, since multipart is not supported yet
  346. switch {
  347. case chunked(t.TransferEncoding):
  348. if noBodyExpected(t.RequestMethod) {
  349. t.Body = eofReader
  350. } else {
  351. t.Body = &body{src: internal.NewChunkedReader(r), hdr: msg, r: r, closing: t.Close}
  352. }
  353. case realLength == 0:
  354. t.Body = eofReader
  355. case realLength > 0:
  356. t.Body = &body{src: io.LimitReader(r, realLength), closing: t.Close}
  357. default:
  358. // realLength < 0, i.e. "Content-Length" not mentioned in header
  359. if t.Close {
  360. // Close semantics (i.e. HTTP/1.0)
  361. t.Body = &body{src: r, closing: t.Close}
  362. } else {
  363. // Persistent connection (i.e. HTTP/1.1)
  364. t.Body = eofReader
  365. }
  366. }
  367. // Unify output
  368. switch rr := msg.(type) {
  369. case *Request:
  370. rr.Body = t.Body
  371. rr.ContentLength = t.ContentLength
  372. rr.TransferEncoding = t.TransferEncoding
  373. rr.Close = t.Close
  374. rr.Trailer = t.Trailer
  375. case *Response:
  376. rr.Body = t.Body
  377. rr.ContentLength = t.ContentLength
  378. rr.TransferEncoding = t.TransferEncoding
  379. rr.Close = t.Close
  380. rr.Trailer = t.Trailer
  381. }
  382. return nil
  383. }
  384. // Checks whether chunked is part of the encodings stack
  385. func chunked(te []string) bool { return len(te) > 0 && te[0] == "chunked" }
  386. // Checks whether the encoding is explicitly "identity".
  387. func isIdentity(te []string) bool { return len(te) == 1 && te[0] == "identity" }
  388. // Sanitize transfer encoding
  389. func fixTransferEncoding(isResponse bool, requestMethod string, header Header) ([]string, error) {
  390. raw, present := header["Transfer-Encoding"]
  391. if !present {
  392. return nil, nil
  393. }
  394. delete(header, "Transfer-Encoding")
  395. encodings := strings.Split(raw[0], ",")
  396. te := make([]string, 0, len(encodings))
  397. // TODO: Even though we only support "identity" and "chunked"
  398. // encodings, the loop below is designed with foresight. One
  399. // invariant that must be maintained is that, if present,
  400. // chunked encoding must always come first.
  401. for _, encoding := range encodings {
  402. encoding = strings.ToLower(strings.TrimSpace(encoding))
  403. // "identity" encoding is not recorded
  404. if encoding == "identity" {
  405. break
  406. }
  407. if encoding != "chunked" {
  408. return nil, &badStringError{"unsupported transfer encoding", encoding}
  409. }
  410. te = te[0 : len(te)+1]
  411. te[len(te)-1] = encoding
  412. }
  413. if len(te) > 1 {
  414. return nil, &badStringError{"too many transfer encodings", strings.Join(te, ",")}
  415. }
  416. if len(te) > 0 {
  417. // RFC 7230 3.3.2 says "A sender MUST NOT send a
  418. // Content-Length header field in any message that
  419. // contains a Transfer-Encoding header field."
  420. //
  421. // but also:
  422. // "If a message is received with both a
  423. // Transfer-Encoding and a Content-Length header
  424. // field, the Transfer-Encoding overrides the
  425. // Content-Length. Such a message might indicate an
  426. // attempt to perform request smuggling (Section 9.5)
  427. // or response splitting (Section 9.4) and ought to be
  428. // handled as an error. A sender MUST remove the
  429. // received Content-Length field prior to forwarding
  430. // such a message downstream."
  431. //
  432. // Reportedly, these appear in the wild.
  433. delete(header, "Content-Length")
  434. return te, nil
  435. }
  436. return nil, nil
  437. }
  438. // Determine the expected body length, using RFC 2616 Section 4.4. This
  439. // function is not a method, because ultimately it should be shared by
  440. // ReadResponse and ReadRequest.
  441. func fixLength(isResponse bool, status int, requestMethod string, header Header, te []string) (int64, error) {
  442. contentLens := header["Content-Length"]
  443. isRequest := !isResponse
  444. // Logic based on response type or status
  445. if noBodyExpected(requestMethod) {
  446. // For HTTP requests, as part of hardening against request
  447. // smuggling (RFC 7230), don't allow a Content-Length header for
  448. // methods which don't permit bodies. As an exception, allow
  449. // exactly one Content-Length header if its value is "0".
  450. if isRequest && len(contentLens) > 0 && !(len(contentLens) == 1 && contentLens[0] == "0") {
  451. return 0, fmt.Errorf("http: method cannot contain a Content-Length; got %q", contentLens)
  452. }
  453. return 0, nil
  454. }
  455. if status/100 == 1 {
  456. return 0, nil
  457. }
  458. switch status {
  459. case 204, 304:
  460. return 0, nil
  461. }
  462. if len(contentLens) > 1 {
  463. // harden against HTTP request smuggling. See RFC 7230.
  464. return 0, errors.New("http: message cannot contain multiple Content-Length headers")
  465. }
  466. // Logic based on Transfer-Encoding
  467. if chunked(te) {
  468. return -1, nil
  469. }
  470. // Logic based on Content-Length
  471. var cl string
  472. if len(contentLens) == 1 {
  473. cl = strings.TrimSpace(contentLens[0])
  474. }
  475. if cl != "" {
  476. n, err := parseContentLength(cl)
  477. if err != nil {
  478. return -1, err
  479. }
  480. return n, nil
  481. } else {
  482. header.Del("Content-Length")
  483. }
  484. if !isResponse {
  485. // RFC 2616 neither explicitly permits nor forbids an
  486. // entity-body on a GET request so we permit one if
  487. // declared, but we default to 0 here (not -1 below)
  488. // if there's no mention of a body.
  489. // Likewise, all other request methods are assumed to have
  490. // no body if neither Transfer-Encoding chunked nor a
  491. // Content-Length are set.
  492. return 0, nil
  493. }
  494. // Body-EOF logic based on other methods (like closing, or chunked coding)
  495. return -1, nil
  496. }
  497. // Determine whether to hang up after sending a request and body, or
  498. // receiving a response and body
  499. // 'header' is the request headers
  500. func shouldClose(major, minor int, header Header, removeCloseHeader bool) bool {
  501. if major < 1 {
  502. return true
  503. } else if major == 1 && minor == 0 {
  504. vv := header["Connection"]
  505. if headerValuesContainsToken(vv, "close") || !headerValuesContainsToken(vv, "keep-alive") {
  506. return true
  507. }
  508. return false
  509. } else {
  510. if headerValuesContainsToken(header["Connection"], "close") {
  511. if removeCloseHeader {
  512. header.Del("Connection")
  513. }
  514. return true
  515. }
  516. }
  517. return false
  518. }
  519. // Parse the trailer header
  520. func fixTrailer(header Header, te []string) (Header, error) {
  521. raw := header.get("Trailer")
  522. if raw == "" {
  523. return nil, nil
  524. }
  525. header.Del("Trailer")
  526. trailer := make(Header)
  527. keys := strings.Split(raw, ",")
  528. for _, key := range keys {
  529. key = CanonicalHeaderKey(strings.TrimSpace(key))
  530. switch key {
  531. case "Transfer-Encoding", "Trailer", "Content-Length":
  532. return nil, &badStringError{"bad trailer key", key}
  533. }
  534. trailer[key] = nil
  535. }
  536. if len(trailer) == 0 {
  537. return nil, nil
  538. }
  539. if !chunked(te) {
  540. // Trailer and no chunking
  541. return nil, ErrUnexpectedTrailer
  542. }
  543. return trailer, nil
  544. }
  545. // body turns a Reader into a ReadCloser.
  546. // Close ensures that the body has been fully read
  547. // and then reads the trailer if necessary.
  548. type body struct {
  549. src io.Reader
  550. hdr interface{} // non-nil (Response or Request) value means read trailer
  551. r *bufio.Reader // underlying wire-format reader for the trailer
  552. closing bool // is the connection to be closed after reading body?
  553. doEarlyClose bool // whether Close should stop early
  554. mu sync.Mutex // guards closed, and calls to Read and Close
  555. sawEOF bool
  556. closed bool
  557. earlyClose bool // Close called and we didn't read to the end of src
  558. }
  559. // ErrBodyReadAfterClose is returned when reading a Request or Response
  560. // Body after the body has been closed. This typically happens when the body is
  561. // read after an HTTP Handler calls WriteHeader or Write on its
  562. // ResponseWriter.
  563. var ErrBodyReadAfterClose = errors.New("http: invalid Read on closed Body")
  564. func (b *body) Read(p []byte) (n int, err error) {
  565. b.mu.Lock()
  566. defer b.mu.Unlock()
  567. if b.closed {
  568. return 0, ErrBodyReadAfterClose
  569. }
  570. return b.readLocked(p)
  571. }
  572. // Must hold b.mu.
  573. func (b *body) readLocked(p []byte) (n int, err error) {
  574. if b.sawEOF {
  575. return 0, io.EOF
  576. }
  577. n, err = b.src.Read(p)
  578. if err == io.EOF {
  579. b.sawEOF = true
  580. // Chunked case. Read the trailer.
  581. if b.hdr != nil {
  582. if e := b.readTrailer(); e != nil {
  583. err = e
  584. // Something went wrong in the trailer, we must not allow any
  585. // further reads of any kind to succeed from body, nor any
  586. // subsequent requests on the server connection. See
  587. // golang.org/issue/12027
  588. b.sawEOF = false
  589. b.closed = true
  590. }
  591. b.hdr = nil
  592. } else {
  593. // If the server declared the Content-Length, our body is a LimitedReader
  594. // and we need to check whether this EOF arrived early.
  595. if lr, ok := b.src.(*io.LimitedReader); ok && lr.N > 0 {
  596. err = io.ErrUnexpectedEOF
  597. }
  598. }
  599. }
  600. // If we can return an EOF here along with the read data, do
  601. // so. This is optional per the io.Reader contract, but doing
  602. // so helps the HTTP transport code recycle its connection
  603. // earlier (since it will see this EOF itself), even if the
  604. // client doesn't do future reads or Close.
  605. if err == nil && n > 0 {
  606. if lr, ok := b.src.(*io.LimitedReader); ok && lr.N == 0 {
  607. err = io.EOF
  608. b.sawEOF = true
  609. }
  610. }
  611. return n, err
  612. }
  613. var (
  614. singleCRLF = []byte("\r\n")
  615. doubleCRLF = []byte("\r\n\r\n")
  616. )
  617. func seeUpcomingDoubleCRLF(r *bufio.Reader) bool {
  618. for peekSize := 4; ; peekSize++ {
  619. // This loop stops when Peek returns an error,
  620. // which it does when r's buffer has been filled.
  621. buf, err := r.Peek(peekSize)
  622. if bytes.HasSuffix(buf, doubleCRLF) {
  623. return true
  624. }
  625. if err != nil {
  626. break
  627. }
  628. }
  629. return false
  630. }
  631. var errTrailerEOF = errors.New("http: unexpected EOF reading trailer")
  632. func (b *body) readTrailer() error {
  633. // The common case, since nobody uses trailers.
  634. buf, err := b.r.Peek(2)
  635. if bytes.Equal(buf, singleCRLF) {
  636. b.r.Discard(2)
  637. return nil
  638. }
  639. if len(buf) < 2 {
  640. return errTrailerEOF
  641. }
  642. if err != nil {
  643. return err
  644. }
  645. // Make sure there's a header terminator coming up, to prevent
  646. // a DoS with an unbounded size Trailer. It's not easy to
  647. // slip in a LimitReader here, as textproto.NewReader requires
  648. // a concrete *bufio.Reader. Also, we can't get all the way
  649. // back up to our conn's LimitedReader that *might* be backing
  650. // this bufio.Reader. Instead, a hack: we iteratively Peek up
  651. // to the bufio.Reader's max size, looking for a double CRLF.
  652. // This limits the trailer to the underlying buffer size, typically 4kB.
  653. if !seeUpcomingDoubleCRLF(b.r) {
  654. return errors.New("http: suspiciously long trailer after chunked body")
  655. }
  656. hdr, err := textproto.NewReader(b.r).ReadMIMEHeader()
  657. if err != nil {
  658. if err == io.EOF {
  659. return errTrailerEOF
  660. }
  661. return err
  662. }
  663. switch rr := b.hdr.(type) {
  664. case *Request:
  665. mergeSetHeader(&rr.Trailer, Header(hdr))
  666. case *Response:
  667. mergeSetHeader(&rr.Trailer, Header(hdr))
  668. }
  669. return nil
  670. }
  671. func mergeSetHeader(dst *Header, src Header) {
  672. if *dst == nil {
  673. *dst = src
  674. return
  675. }
  676. for k, vv := range src {
  677. (*dst)[k] = vv
  678. }
  679. }
  680. // unreadDataSizeLocked returns the number of bytes of unread input.
  681. // It returns -1 if unknown.
  682. // b.mu must be held.
  683. func (b *body) unreadDataSizeLocked() int64 {
  684. if lr, ok := b.src.(*io.LimitedReader); ok {
  685. return lr.N
  686. }
  687. return -1
  688. }
  689. func (b *body) Close() error {
  690. b.mu.Lock()
  691. defer b.mu.Unlock()
  692. if b.closed {
  693. return nil
  694. }
  695. var err error
  696. switch {
  697. case b.sawEOF:
  698. // Already saw EOF, so no need going to look for it.
  699. case b.hdr == nil && b.closing:
  700. // no trailer and closing the connection next.
  701. // no point in reading to EOF.
  702. case b.doEarlyClose:
  703. // Read up to maxPostHandlerReadBytes bytes of the body, looking for
  704. // for EOF (and trailers), so we can re-use this connection.
  705. if lr, ok := b.src.(*io.LimitedReader); ok && lr.N > maxPostHandlerReadBytes {
  706. // There was a declared Content-Length, and we have more bytes remaining
  707. // than our maxPostHandlerReadBytes tolerance. So, give up.
  708. b.earlyClose = true
  709. } else {
  710. var n int64
  711. // Consume the body, or, which will also lead to us reading
  712. // the trailer headers after the body, if present.
  713. n, err = io.CopyN(ioutil.Discard, bodyLocked{b}, maxPostHandlerReadBytes)
  714. if err == io.EOF {
  715. err = nil
  716. }
  717. if n == maxPostHandlerReadBytes {
  718. b.earlyClose = true
  719. }
  720. }
  721. default:
  722. // Fully consume the body, which will also lead to us reading
  723. // the trailer headers after the body, if present.
  724. _, err = io.Copy(ioutil.Discard, bodyLocked{b})
  725. }
  726. b.closed = true
  727. return err
  728. }
  729. func (b *body) didEarlyClose() bool {
  730. b.mu.Lock()
  731. defer b.mu.Unlock()
  732. return b.earlyClose
  733. }
  734. // bodyLocked is a io.Reader reading from a *body when its mutex is
  735. // already held.
  736. type bodyLocked struct {
  737. b *body
  738. }
  739. func (bl bodyLocked) Read(p []byte) (n int, err error) {
  740. if bl.b.closed {
  741. return 0, ErrBodyReadAfterClose
  742. }
  743. return bl.b.readLocked(p)
  744. }
  745. // parseContentLength trims whitespace from s and returns -1 if no value
  746. // is set, or the value if it's >= 0.
  747. func parseContentLength(cl string) (int64, error) {
  748. cl = strings.TrimSpace(cl)
  749. if cl == "" {
  750. return -1, nil
  751. }
  752. n, err := strconv.ParseInt(cl, 10, 64)
  753. if err != nil || n < 0 {
  754. return 0, &badStringError{"bad Content-Length", cl}
  755. }
  756. return n, nil
  757. }