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 }