forked from pbnjay/harhar
-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.go
84 lines (71 loc) · 2.03 KB
/
server.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
package harhar
import (
"bytes"
"io"
"log"
"net/http"
"time"
)
// ServeHTTP implements http.Handler (aka a Server-side recorder)
func (c *Recorder) ServeHTTP(w http.ResponseWriter, req *http.Request) {
c.mu.Lock()
defer c.mu.Unlock()
var err error
ent := Entry{}
ent.Request, err = makeRequest(req)
if err != nil {
log.Println("unable to record HAR for request ", req.URL.String())
}
responseWrapper := &HARResponseWriter{}
startTime := time.Now()
c.Handler.ServeHTTP(responseWrapper, req)
ent.Time = float64(time.Since(startTime).Milliseconds())
ent.Start = startTime.Format(time.RFC3339Nano)
ent.Timings.Send = -1
ent.Timings.Receive = -1
// copy headers
for h, vals := range responseWrapper.header {
for _, val := range vals {
w.Header().Set(h, val)
}
}
w.WriteHeader(responseWrapper.statusCode)
w.Write(responseWrapper.body.Bytes())
resp := responseWrapper.AsResponse(req)
ent.Response, err = makeResponse(resp)
if err != nil {
log.Println("unable to record HAR for response ", req.URL.String())
}
c.HAR.Log.Entries = append(c.HAR.Log.Entries, ent)
}
type HARResponseWriter struct {
body bytes.Buffer
statusCode int
header http.Header
didWriteHeaders bool
}
func (w *HARResponseWriter) Header() http.Header {
if w.header == nil {
w.header = make(http.Header, 5)
}
return w.header
}
func (w *HARResponseWriter) Write(b []byte) (int, error) {
if !w.didWriteHeaders {
w.WriteHeader(http.StatusOK)
}
return w.body.Write(b)
}
func (w *HARResponseWriter) WriteHeader(statusCode int) {
w.statusCode = statusCode
w.didWriteHeaders = true
}
func (w *HARResponseWriter) AsResponse(req *http.Request) *http.Response {
resp := &http.Response{
StatusCode: w.statusCode,
Proto: req.Proto,
Header: w.header.Clone(),
Body: io.NopCloser(bytes.NewReader(w.body.Bytes())),
}
return resp
}