This repository has been archived by the owner on Jan 5, 2023. It is now read-only.
/
http.go
58 lines (49 loc) · 1.65 KB
/
http.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
package iostream
import (
"github.com/juju/errgo"
"io"
"net/http"
)
// HttpStream streams the given reader to the given writer using the ResponseWriter
// flush and watch canceling the request.
//
// The ResponseWriter must implement `net/http.CloseNotifier` and `net/http.Flusher`.
// If the request is canceled, the reader will be closed.
// Any returned error of `io.Copy` is ignored, if the request is already canceled.
//
// github.com/juju/errgo.Mask() is used internally.
func HttpStream(res http.ResponseWriter, w io.Writer, r io.ReadCloser) error {
if w == nil {
w = res
}
// type assert to http.Flusher to be able to stream journald's output
f, ok := res.(http.Flusher)
if !ok {
return errgo.Newf("response writer is not a flusher")
}
wf := &WriteFlusher{W: w, Flusher: f}
// type assert to http.CloseNotifier to be able to handle disconnection of clients
cn, ok := res.(http.CloseNotifier)
if !ok {
return errgo.Newf("response writer is not a close notifier")
}
closeChan := cn.CloseNotify()
return Stream(wf, r, closeChan)
}
// WriteFlusher is a port of Docker's implementation used in their API (we dropped the Mutex).
// (https://github.com/docker/docker/blob/9ae3134dc9f0652ef48ec1fd445f42d8fe26de35/utils/utils.go#L269)
// It combines io.Writer and http.Flusher to enable streaming of constant data
// flows via http connections.
type WriteFlusher struct {
W io.Writer
Flusher http.Flusher
}
// Write flushes the data immediately after every write operation
func (wf *WriteFlusher) Write(b []byte) (n int, err error) {
n, err = wf.W.Write(b)
wf.Flusher.Flush()
return n, err
}
func (wf *WriteFlusher) Flush() {
wf.Flusher.Flush()
}