// NewStreamReader returns a reader, which replays all the data generated by sw.
//
// The returned reader may be passed to Response.SetBodyStream.
//
// Close must be called on the returned reader after all the required data
// has been read. Otherwise goroutine leak may occur.
//
// See also Response.SetBodyStreamWriter.
func NewStreamReader(sw StreamWriter) io.ReadCloser {
	pc := fasthttputil.NewPipeConns()
	pw := pc.Conn1()
	pr := pc.Conn2()

	var bw *bufio.Writer
	v := streamWriterBufPool.Get()
	if v == nil {
		bw = bufio.NewWriter(pw)
	} else {
		bw = v.(*bufio.Writer)
		bw.Reset(pw)
	}

	go func() {
		defer func() {
			if r := recover(); r != nil {
				defaultLogger.Printf("panic in StreamWriter: %s\nStack trace:\n%s", r, debug.Stack())
			}
		}()

		sw(bw)
		bw.Flush()
		pw.Close()

		streamWriterBufPool.Put(bw)
	}()

	return pr
}
Example #2
0
// NewStreamReader returns a reader, which replays all the data generated by sw.
//
// The returned reader may be passed to Response.SetBodyStream.
//
// Close must be called on the returned reader after all the required data
// has been read. Otherwise goroutine leak may occur.
//
// See also Response.SetBodyStreamWriter.
func NewStreamReader(sw StreamWriter) io.ReadCloser {
	pc := fasthttputil.NewPipeConns()
	pw := pc.Conn1()
	pr := pc.Conn2()

	var bw *bufio.Writer
	v := streamWriterBufPool.Get()
	if v == nil {
		bw = bufio.NewWriter(pw)
	} else {
		bw = v.(*bufio.Writer)
		bw.Reset(pw)
	}

	go func() {
		sw(bw)
		bw.Flush()
		pw.Close()

		streamWriterBufPool.Put(bw)
	}()

	return pr
}