-
Notifications
You must be signed in to change notification settings - Fork 3
/
generator.go
88 lines (78 loc) · 1.87 KB
/
generator.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
package fuzzsupport
import (
"bytes"
"io"
"net/http"
)
// GeneratedHTTPResponse is a well-formed http.Response that can be unmarshalled from random bytes.
type GeneratedHTTPResponse http.Response
// statusMap is list of all known HTTP status codes.
var statusMap []int
// interestingHeaders is a list of interesting HTTP headers
var interestingHeaders = []string{
"",
"Authorization",
"Proxy-Authorization",
"Content-Type",
}
func init() {
for i := 100; i < 600; i++ {
if str := http.StatusText(i); str != "" {
statusMap = append(statusMap, i)
}
}
statusMap = append(statusMap, 242, 442, 542) // some invalid ones!
}
type generatorState int
const (
statusState generatorState = iota
headerKeyState
headerValueState
bodyState
)
func (res *GeneratedHTTPResponse) UnmarshalText(in []byte) error {
res.Header = make(http.Header)
res.StatusCode = http.StatusOK
buf := new(bytes.Buffer)
res.Body = io.NopCloser(buf)
state := statusState
var k, v []byte
for _, b := range in {
switch state {
case statusState:
res.StatusCode = statusMap[int(b)%len(statusMap)]
state = headerKeyState
case headerKeyState:
switch {
case b == 0:
state = headerValueState
case len(k) == 0 && int(b) < len(interestingHeaders):
k = []byte(interestingHeaders[int(b)])
state = headerValueState
default:
k = append(k, b)
}
case headerValueState:
switch {
case b == 0:
state = bodyState
res.Header.Add(string(k), string(v))
k, v = nil, nil
case b == 1:
state = headerKeyState
res.Header.Add(string(k), string(v))
k, v = nil, nil
default:
v = append(v, b)
}
case bodyState:
buf.WriteByte(b)
}
}
res.Status = http.StatusText(res.StatusCode)
if res.StatusCode >= 300 && res.StatusCode < 400 {
res.Header.Set("Location", "http://example.invalid/redirect")
}
res.ContentLength = int64(buf.Len())
return nil
}