diff options
Diffstat (limited to 'src/pkg/http/chunked.go')
-rw-r--r-- | src/pkg/http/chunked.go | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/src/pkg/http/chunked.go b/src/pkg/http/chunked.go new file mode 100644 index 000000000..6c23e691f --- /dev/null +++ b/src/pkg/http/chunked.go @@ -0,0 +1,77 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package http + +import ( + "io" + "log" + "os" + "strconv" + "bufio" +) + +// NewChunkedWriter returns a new writer that translates writes into HTTP +// "chunked" format before writing them to w. Closing the returned writer +// sends the final 0-length chunk that marks the end of the stream. +// +// NewChunkedWriter is not needed by normal applications. The http +// package adds chunking automatically if handlers don't set a +// Content-Length header. Using NewChunkedWriter inside a handler +// would result in double chunking or chunking with a Content-Length +// length, both of which are wrong. +func NewChunkedWriter(w io.Writer) io.WriteCloser { + if _, bad := w.(*response); bad { + log.Printf("warning: using NewChunkedWriter in an http.Handler; expect corrupt output") + } + return &chunkedWriter{w} +} + +// Writing to ChunkedWriter translates to writing in HTTP chunked Transfer +// Encoding wire format to the underlying Wire writer. +type chunkedWriter struct { + Wire io.Writer +} + +// Write the contents of data as one chunk to Wire. +// NOTE: Note that the corresponding chunk-writing procedure in Conn.Write has +// a bug since it does not check for success of io.WriteString +func (cw *chunkedWriter) Write(data []byte) (n int, err os.Error) { + + // Don't send 0-length data. It looks like EOF for chunked encoding. + if len(data) == 0 { + return 0, nil + } + + head := strconv.Itob(len(data), 16) + "\r\n" + + if _, err = io.WriteString(cw.Wire, head); err != nil { + return 0, err + } + if n, err = cw.Wire.Write(data); err != nil { + return + } + if n != len(data) { + err = io.ErrShortWrite + return + } + _, err = io.WriteString(cw.Wire, "\r\n") + + return +} + +func (cw *chunkedWriter) Close() os.Error { + _, err := io.WriteString(cw.Wire, "0\r\n") + return err +} + +// NewChunkedReader returns a new reader that translates the data read from r +// out of HTTP "chunked" format before returning it. +// The reader returns os.EOF when the final 0-length chunk is read. +// +// NewChunkedReader is not needed by normal applications. The http package +// automatically decodes chunking when reading response bodies. +func NewChunkedReader(r *bufio.Reader) io.Reader { + return &chunkedReader{r: r} +} |