goa
goa copied to clipboard
Allow implementing `io.WriterTo` for `SkipResponseBodyEncodeDecode` responses.
When a server uses SkipResponseBodyEncodeDecode
, the response must be of the type io.ReadCloser
. In most cases I've come across, an io.Writer
would be more ergonomic to use. I often find myself needing to use io.Pipe
to create an io.Reader
I can write to. It's made worse by the fact that it's abstracting the http.ResponseWriter
and pushing it through a bufio.Reader
, so there's lots of extra copying going on.
I propose to have the generated code check if the io.ReadCloser
implements io.WriterTo
, and if it does, call that instead.
Additionally, it'd be nice to have a helper in the goa package to implement the interface from an io.WriterTo
, to make it easier to switch to, eg: If used as the response to a handler, the Read
would never be called, and the pipe would never be created.
func SkipResponseWriter(wt io.WriterTo) io.ReadCloser {
return writerToReaderAdapter{wt, nil}
}
type writerToReaderAdapter struct {
io.WriterTo
pr *io.PipeReader
}
func (a *writerToReaderAdapter) initPipe() {
if a.pr != nil {
return
}
r, w := io.Pipe()
go func() {
_, err := wt.WriteTo(w)
w.CloseWithError(err)
}()
a.pr = r
}
func (a *writerToReaderAdapter) Read(b []byte) (n int, err error) {
a.initPipe()
return a.pr.Read(b)
}
func (a *writerToReaderAdapter) Close() error {
a.initPipe()
return a.pr.Close()
}
As an alternate suggestion, you could have some way in the DSL that changes the expected type.