github.com/coreos/goproxy@v0.0.0-20190513173959-f8dc2d7ba04e/chunked.go (about)

     1  // Taken from $GOROOT/src/pkg/net/http/chunked
     2  // needed to write https responses to client.
     3  package goproxy
     4  
     5  import (
     6  	"io"
     7  	"strconv"
     8  )
     9  
    10  // newChunkedWriter returns a new chunkedWriter that translates writes into HTTP
    11  // "chunked" format before writing them to w. Closing the returned chunkedWriter
    12  // sends the final 0-length chunk that marks the end of the stream.
    13  //
    14  // newChunkedWriter is not needed by normal applications. The http
    15  // package adds chunking automatically if handlers don't set a
    16  // Content-Length header. Using newChunkedWriter inside a handler
    17  // would result in double chunking or chunking with a Content-Length
    18  // length, both of which are wrong.
    19  func newChunkedWriter(w io.Writer) io.WriteCloser {
    20  	return &chunkedWriter{w}
    21  }
    22  
    23  // Writing to chunkedWriter translates to writing in HTTP chunked Transfer
    24  // Encoding wire format to the underlying Wire chunkedWriter.
    25  type chunkedWriter struct {
    26  	Wire io.Writer
    27  }
    28  
    29  // Write the contents of data as one chunk to Wire.
    30  // NOTE: Note that the corresponding chunk-writing procedure in Conn.Write has
    31  // a bug since it does not check for success of io.WriteString
    32  func (cw *chunkedWriter) Write(data []byte) (n int, err error) {
    33  
    34  	// Don't send 0-length data. It looks like EOF for chunked encoding.
    35  	if len(data) == 0 {
    36  		return 0, nil
    37  	}
    38  
    39  	head := strconv.FormatInt(int64(len(data)), 16) + "\r\n"
    40  
    41  	if _, err = io.WriteString(cw.Wire, head); err != nil {
    42  		return 0, err
    43  	}
    44  	if n, err = cw.Wire.Write(data); err != nil {
    45  		return
    46  	}
    47  	if n != len(data) {
    48  		err = io.ErrShortWrite
    49  		return
    50  	}
    51  	_, err = io.WriteString(cw.Wire, "\r\n")
    52  
    53  	return
    54  }
    55  
    56  func (cw *chunkedWriter) Close() error {
    57  	_, err := io.WriteString(cw.Wire, "0\r\n")
    58  	return err
    59  }