-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathcapture.go
139 lines (118 loc) · 2.66 KB
/
capture.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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package main
import (
"net/http"
"strconv"
"sync"
"time"
)
var captureID int
// CaptureService handles captures.
type CaptureService struct {
items []Capture
mu sync.RWMutex
maxItems int
updated chan struct{} // signals any change in "items".
}
// Capture is our traffic data.
type Capture struct {
ID int
Req Req
Res Res
// Elapsed time of the request, in milliseconds.
Elapsed time.Duration
}
type Req struct {
Proto string
Method string
Url string
Path string
Header http.Header
Body []byte
}
type Res struct {
Proto string
Status string
Code int
Header http.Header
Body []byte
}
// CaptureInfo is the capture info shown in the dashboard.
type CaptureInfo struct {
Request string `json:"request"`
Response string `json:"response"`
Curl string `json:"curl"`
}
// DashboardItem is an item in the dashboard's list.
type DashboardItem struct {
ID int `json:"id"`
Path string `json:"path"`
Method string `json:"method"`
Status int `json:"status"`
Elapsed time.Duration `json:"elapsed"`
}
// NewCaptureService creates a new service of captures.
func NewCaptureService(maxItems int) *CaptureService {
return &CaptureService{
maxItems: maxItems,
updated: make(chan struct{}),
}
}
// Insert inserts a new capture.
func (s *CaptureService) Insert(capture Capture) {
s.mu.Lock()
defer s.mu.Unlock()
captureID++
capture.ID = captureID
s.items = append(s.items, capture)
if len(s.items) > s.maxItems {
s.items = s.items[1:]
}
s.signalsUpdate()
}
// Find finds a capture by its ID.
func (s *CaptureService) Find(captureID string) *Capture {
s.mu.RLock()
defer s.mu.RUnlock()
idInt, _ := strconv.Atoi(captureID)
for _, c := range s.items {
if c.ID == idInt {
return &c
}
}
return nil
}
// RemoveAll removes all the captures.
func (s *CaptureService) RemoveAll() {
s.mu.Lock()
defer s.mu.Unlock()
s.items = nil
s.signalsUpdate()
}
// DashboardItems returns the dashboard's list of items.
func (s *CaptureService) DashboardItems() []DashboardItem {
s.mu.RLock()
defer s.mu.RUnlock()
metadatas := make([]DashboardItem, len(s.items))
for i, capture := range s.items {
metadatas[i] = DashboardItem{
ID: capture.ID,
Path: capture.Req.Path,
Method: capture.Req.Method,
Status: capture.Res.Code,
Elapsed: capture.Elapsed,
}
}
return metadatas
}
// signalsUpdate fires an update signal.
func (s *CaptureService) signalsUpdate() {
close(s.updated)
s.updated = make(chan struct{})
}
// Updated signals any change in this service,
// like inserting or removing captures.
func (s *CaptureService) Updated() <-chan struct{} {
s.mu.RLock()
defer s.mu.RUnlock()
return s.updated
}