-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathresponse.go
103 lines (84 loc) · 1.84 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
package rtsp
import (
"bufio"
"fmt"
"io"
"net/http"
"net/textproto"
"strconv"
"strings"
)
type Response struct {
Proto string
StatusCode int
Status string
Header http.Header
Body []byte
}
func parseResponseLine(line string) (proto, status string, code int, ok bool) {
proto, status, ok = strings.Cut(line, " ")
if !ok {
return
}
status = strings.TrimSpace(status)
statusCode, _, _ := strings.Cut(status, " ")
var err error
code, err = strconv.Atoi(statusCode)
ok = (err == nil) && (code >= 100) && (code <= 999)
return
}
// ReadResponse reads a response from the server.
func ReadResponse(reader *bufio.Reader) (response *Response, err error) {
tp := textproto.NewReader(reader)
defer func() {
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
}()
var line string
line, err = tp.ReadLine()
if err != nil {
return nil, err
}
proto, status, code, ok := parseResponseLine(line)
if !ok {
return nil, fmt.Errorf("invalid response line %q", line)
}
// Parse the response headers.
mimeHeader, err := tp.ReadMIMEHeader()
if err != nil {
return nil, err
}
response = &Response{
Proto: proto,
StatusCode: code,
Status: status,
Header: http.Header(mimeHeader),
}
return response, nil
}
// ReadBody reads the body after response.
func (r *Response) ReadBody(reader *bufio.Reader) error {
v := r.Header.Get("content-length")
if v == "" {
return nil
}
contentLength, err := strconv.Atoi(v)
if err != nil {
return fmt.Errorf("invalid content-length %q", v)
}
if contentLength == 0 {
return nil
}
if contentLength > (64 * 1024) {
return fmt.Errorf("content-length too large %d", contentLength)
}
r.Body = make([]byte, contentLength)
if _, err = io.ReadFull(reader, r.Body); err != nil {
if err == io.EOF {
err = io.ErrUnexpectedEOF
}
return err
}
return nil
}