/
response.go
105 lines (88 loc) · 2.14 KB
/
response.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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package response
import (
"errors"
"fmt"
"io"
"net/http"
"github.com/chronos-tachyon/morehttp/body"
)
var headerPush = http.CanonicalHeaderKey("Push")
// Response represents an HTTP response.
type Response struct {
code int
hdrs http.Header
body body.Body
err error
}
// Status returns the HTTP status code of the response.
//
// The returned value lies between 200 and 999 inclusive.
//
func (resp *Response) Status() int {
return resp.code
}
// Headers returns the HTTP headers of the response.
//
// The caller MUST NOT modify the returned map or its contents.
//
func (resp *Response) Headers() http.Header {
return resp.hdrs
}
// Body returns this Response's Body.
//
// The caller must not read from or modify the returned Body. Call Body.Copy()
// and operate on the copy when performing such actions.
//
func (resp *Response) Body() body.Body {
return resp.body
}
// Err returns the Go error which provoked this Response, if any.
func (resp *Response) Err() error {
return resp.err
}
// String returns a programmer-friendly string description.
func (resp *Response) String() string {
if bodyLen := resp.body.BytesRemaining(); bodyLen >= 0 {
return fmt.Sprintf("[HTTP %03d - %d bytes]", resp.code, bodyLen)
}
return fmt.Sprintf("[HTTP %03d - unknown length]", resp.code)
}
// Copy returns a copy of this Response.
func (resp *Response) Copy() (*Response, error) {
body2, err := copyBody(resp.body)
if err != nil {
return nil, err
}
out := &Response{
code: resp.code,
hdrs: resp.hdrs,
body: body2,
err: resp.err,
}
return out, nil
}
// Serve serves the Response via the given ResponseWriter, consuming its Body.
func (resp *Response) Serve(w http.ResponseWriter) error {
if x, ok := w.(http.Pusher); ok {
vlist := resp.hdrs[headerPush]
for _, url := range vlist {
err := x.Push(url, &http.PushOptions{})
if err != nil && !errors.Is(err, http.ErrNotSupported) {
return err
}
}
}
h := w.Header()
for k, vlist := range resp.hdrs {
if k != headerPush {
h[k] = vlist
}
}
w.WriteHeader(resp.code)
_, err := io.Copy(w, resp.body)
err2 := resp.body.Close()
if err == nil {
err = err2
}
return err
}