capture/capture.go

140 lines
2.6 KiB
Go
Raw Normal View History

2017-11-21 22:36:40 +01:00
package main
2018-11-22 22:45:20 +01:00
import (
2018-11-24 15:24:16 +01:00
"net/http"
2018-11-22 22:45:20 +01:00
"strconv"
"sync"
2019-03-23 23:13:16 +01:00
"time"
2018-11-22 22:45:20 +01:00
)
var captureID int
2019-06-21 01:09:58 +02:00
// CaptureService handles captures
type CaptureService struct {
2018-11-22 22:45:20 +01:00
items []Capture
2018-12-03 23:42:53 +01:00
mu sync.RWMutex
2018-11-22 22:45:20 +01:00
maxItems int
updated chan struct{} // signals any change in "items"
2018-11-22 22:45:20 +01:00
}
2019-06-21 01:09:58 +02:00
// Capture is our traffic data
2017-11-21 22:36:40 +01:00
type Capture struct {
2018-11-24 15:24:16 +01:00
ID int
2019-11-16 16:47:02 +01:00
Req Req
Res Res
2019-03-23 23:13:16 +01:00
// Elapsed time of the request, in milliseconds
Elapsed time.Duration
2017-11-21 22:36:40 +01:00
}
2019-11-16 16:47:02 +01:00
// CaptureDump is all the dumps shown in the dashboard
type CaptureDump struct {
Request string `json:"request"`
Response string `json:"response"`
Curl string `json:"curl"`
}
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
}
2019-06-21 01:09:58 +02:00
// DashboardItem is an item in the dashboard's list
type DashboardItem struct {
2018-09-16 16:18:39 +02:00
ID int `json:"id"`
Path string `json:"path"`
Method string `json:"method"`
Status int `json:"status"`
2019-03-23 23:13:16 +01:00
Elapsed time.Duration `json:"elapsed"`
2018-07-21 19:50:53 +02:00
}
2019-06-21 01:09:58 +02:00
// NewCaptureService creates a new service of captures
func NewCaptureService(maxItems int) *CaptureService {
return &CaptureService{
2018-11-22 22:45:20 +01:00
maxItems: maxItems,
updated: make(chan struct{}),
2018-11-22 22:45:20 +01:00
}
2018-08-04 01:53:54 +02:00
}
2019-06-21 01:09:58 +02:00
// Insert inserts a new capture
func (s *CaptureService) Insert(capture Capture) {
s.mu.Lock()
defer s.mu.Unlock()
2018-12-03 23:42:53 +01:00
captureID++
capture.ID = captureID
2019-06-21 01:09:58 +02:00
s.items = append(s.items, capture)
if len(s.items) > s.maxItems {
s.items = s.items[1:]
2018-07-21 19:50:53 +02:00
}
2019-06-21 01:09:58 +02:00
s.signalsUpdate()
2017-11-21 22:36:40 +01:00
}
2018-12-01 23:59:33 +01:00
// Find finds a capture by its id
2019-06-21 01:09:58 +02:00
func (s *CaptureService) Find(captureID string) *Capture {
s.mu.RLock()
defer s.mu.RUnlock()
2018-11-22 22:45:20 +01:00
idInt, _ := strconv.Atoi(captureID)
2019-06-21 01:09:58 +02:00
for _, c := range s.items {
2018-11-22 22:45:20 +01:00
if c.ID == idInt {
return &c
2018-07-21 19:50:53 +02:00
}
2017-11-21 22:36:40 +01:00
}
2018-11-22 22:45:20 +01:00
return nil
}
2018-12-01 23:59:33 +01:00
// RemoveAll removes all the captures
2019-06-21 01:09:58 +02:00
func (s *CaptureService) RemoveAll() {
s.mu.Lock()
defer s.mu.Unlock()
2018-11-22 22:45:20 +01:00
2019-06-21 01:09:58 +02:00
s.items = nil
s.signalsUpdate()
2018-11-22 22:45:20 +01:00
}
2019-06-21 01:09:58 +02:00
// 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,
2019-11-16 16:47:02 +01:00
Path: capture.Req.Path,
2019-06-21 01:09:58 +02:00
Method: capture.Req.Method,
2019-11-16 16:47:02 +01:00
Status: capture.Res.Code,
2019-06-21 01:09:58 +02:00
Elapsed: capture.Elapsed,
}
2018-11-25 18:10:10 +01:00
}
return metadatas
}
2019-06-21 01:09:58 +02:00
// signalsUpdate fires an update signal
func (s *CaptureService) signalsUpdate() {
close(s.updated)
s.updated = make(chan struct{})
}
2019-06-21 01:09:58 +02:00
// 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
2018-11-25 18:10:10 +01:00
}