1
0
mirror of https://github.com/ipfs/kubo.git synced 2025-06-30 01:52:26 +08:00

cmds/http/handler: set stream error trailer

stream output might break. in these cases we need to notify the
client. this is after a 200 response has been sent. We do this
by setting a special trailer (header after the body):

  X-Stream-Error: <error cause>

This is similar to what's done by systems like gRPC. This still
needs to be read + handled on the other side.

License: MIT
Signed-off-by: Juan Batiz-Benet <juan@benet.ai>
This commit is contained in:
Juan Batiz-Benet
2015-07-24 14:45:13 -07:00
parent e3c35d8b76
commit 814f437fb4

View File

@ -32,6 +32,7 @@ type Handler struct {
var ErrNotFound = errors.New("404 page not found") var ErrNotFound = errors.New("404 page not found")
const ( const (
StreamErrHeader = "X-Stream-Error"
streamHeader = "X-Stream-Output" streamHeader = "X-Stream-Output"
channelHeader = "X-Chunked-Output" channelHeader = "X-Chunked-Output"
contentTypeHeader = "Content-Type" contentTypeHeader = "Content-Type"
@ -213,8 +214,8 @@ func copyChunks(contentType string, w http.ResponseWriter, out io.Reader) error
writer.WriteString(transferEncodingHeader + ": chunked\r\n") writer.WriteString(transferEncodingHeader + ": chunked\r\n")
writer.WriteString(channelHeader + ": 1\r\n\r\n") writer.WriteString(channelHeader + ": 1\r\n\r\n")
writeChunks := func() error {
buf := make([]byte, 32*1024) buf := make([]byte, 32*1024)
for { for {
n, err := out.Read(buf) n, err := out.Read(buf)
@ -238,13 +239,29 @@ func copyChunks(contentType string, w http.ResponseWriter, out io.Reader) error
break break
} }
} }
writer.WriteString("0\r\n\r\n")
writer.Flush()
return nil return nil
} }
streamErr := writeChunks()
writer.WriteString("0\r\n") // close body
// if there was a stream error, write out an error trailer. hopefully
// the client will pick it up!
if streamErr != nil {
writer.WriteString(StreamErrHeader + ": " + sanitizedErrStr(err) + "\r\n")
}
writer.WriteString("\r\n") // close response
writer.Flush()
return nil
}
func sanitizedErrStr(err error) string {
s := err.Error()
s = strings.Split(s, "\n")[0]
s = strings.Split(s, "\r")[0]
return s
}
type flushResponse struct { type flushResponse struct {
W http.ResponseWriter W http.ResponseWriter
} }