give better names to stuff

This commit is contained in:
Fabricio 2019-06-20 20:09:58 -03:00
parent b94d20865d
commit 0613222b4b
2 changed files with 73 additions and 79 deletions

View file

@ -9,26 +9,25 @@ import (
var captureID int
// CaptureList stores all captures
type CaptureList struct {
// CaptureService handles captures
type CaptureService struct {
items []Capture
mu sync.RWMutex
maxItems int
updated chan struct{} // signals any change in "items"
}
// Capture saves our traffic data
// Capture is our traffic data
type Capture struct {
ID int
Req *http.Request
Res *http.Response
// Elapsed time of the request, in milliseconds
Elapsed time.Duration
}
// CaptureMetadata is the data for each list item in the dashboard
type CaptureMetadata struct {
// DashboardItem is an item in the dashboard's list
type DashboardItem struct {
ID int `json:"id"`
Path string `json:"path"`
Method string `json:"method"`
@ -37,51 +36,42 @@ type CaptureMetadata struct {
Elapsed time.Duration `json:"elapsed"`
}
// CaptureDump saves all the dumps shown in the dashboard
// CaptureDump is all the dumps shown in the dashboard
type CaptureDump struct {
Request string `json:"request"`
Response string `json:"response"`
Curl string `json:"curl"`
}
// Metadata returns the metadada of a capture
func (c *Capture) Metadata() CaptureMetadata {
return CaptureMetadata{
ID: c.ID,
Path: c.Req.URL.Path,
Method: c.Req.Method,
Status: c.Res.StatusCode,
Elapsed: c.Elapsed,
}
}
// NewCaptureList creates a new list of captures
func NewCaptureList(maxItems int) *CaptureList {
return &CaptureList{
// NewCaptureService creates a new service of captures
func NewCaptureService(maxItems int) *CaptureService {
return &CaptureService{
maxItems: maxItems,
updated: make(chan struct{}),
}
}
// Insert adds a new capture
func (c *CaptureList) Insert(capture Capture) {
c.mu.Lock()
defer c.mu.Unlock()
// Insert inserts a new capture
func (s *CaptureService) Insert(capture Capture) {
s.mu.Lock()
defer s.mu.Unlock()
captureID++
capture.ID = captureID
c.items = append(c.items, capture)
if len(c.items) > c.maxItems {
c.items = c.items[1:]
s.items = append(s.items, capture)
if len(s.items) > s.maxItems {
s.items = s.items[1:]
}
c.signalsChange()
s.signalsUpdate()
}
// Find finds a capture by its id
func (c *CaptureList) Find(captureID string) *Capture {
c.mu.RLock()
defer c.mu.RUnlock()
func (s *CaptureService) Find(captureID string) *Capture {
s.mu.RLock()
defer s.mu.RUnlock()
idInt, _ := strconv.Atoi(captureID)
for _, c := range c.items {
for _, c := range s.items {
if c.ID == idInt {
return &c
}
@ -90,39 +80,43 @@ func (c *CaptureList) Find(captureID string) *Capture {
}
// RemoveAll removes all the captures
func (c *CaptureList) RemoveAll() {
c.mu.Lock()
defer c.mu.Unlock()
c.items = nil
c.signalsChange()
func (s *CaptureService) RemoveAll() {
s.mu.Lock()
defer s.mu.Unlock()
s.items = nil
s.signalsUpdate()
}
// Items returns all the captures
func (c *CaptureList) Items() []Capture {
c.mu.RLock()
defer c.mu.RUnlock()
return c.items
}
// DashboardItems returns the dashboard's list of items
func (s *CaptureService) DashboardItems() []DashboardItem {
s.mu.RLock()
defer s.mu.RUnlock()
// ItemsAsMetadata returns all the captures as metadata
func (c *CaptureList) ItemsAsMetadata() []CaptureMetadata {
c.mu.RLock()
defer c.mu.RUnlock()
metadatas := make([]CaptureMetadata, len(c.items))
for i, capture := range c.items {
metadatas[i] = capture.Metadata()
metadatas := make([]DashboardItem, len(s.items))
for i, capture := range s.items {
metadatas[i] = DashboardItem{
ID: capture.ID,
Path: capture.Req.URL.Path,
Method: capture.Req.Method,
Status: capture.Res.StatusCode,
Elapsed: capture.Elapsed,
}
}
return metadatas
}
func (c *CaptureList) signalsChange() {
close(c.updated)
c.updated = make(chan struct{})
// signalsUpdate fires an update signal
func (s *CaptureService) signalsUpdate() {
close(s.updated)
s.updated = make(chan struct{})
}
// Updated signals any change in the list
func (c *CaptureList) Updated() <-chan struct{} {
c.mu.RLock()
defer c.mu.RUnlock()
return c.updated
// 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
}

40
main.go
View file

@ -31,15 +31,15 @@ func main() {
func startCapture(config Config) {
list := NewCaptureList(config.MaxCaptures)
srv := NewCaptureService(config.MaxCaptures)
handler := NewRecorder(list, NewPlugin(NewProxyHandler(config.TargetURL)))
handler := NewRecorderHandler(srv, NewPluginHandler(NewProxyHandler(config.TargetURL)))
http.HandleFunc(config.DashboardPath, NewDashboardHTMLHandler(config))
http.HandleFunc(config.DashboardConnPath, NewDashboardConnHandler(list))
http.HandleFunc(config.DashboardInfoPath, NewDashboardInfoHandler(list))
http.HandleFunc(config.DashboardClearPath, NewDashboardClearHandler(list))
http.HandleFunc(config.DashboardRetryPath, NewDashboardRetryHandler(list, handler))
http.HandleFunc(config.DashboardConnPath, NewDashboardConnHandler(srv))
http.HandleFunc(config.DashboardInfoPath, NewDashboardInfoHandler(srv))
http.HandleFunc(config.DashboardClearPath, NewDashboardClearHandler(srv))
http.HandleFunc(config.DashboardRetryPath, NewDashboardRetryHandler(srv, handler))
http.HandleFunc("/", handler)
captureHost := fmt.Sprintf("http://localhost:%s", config.ProxyPort)
@ -52,7 +52,7 @@ func startCapture(config Config) {
// NewDashboardConnHandler opens an event stream connection with the dashboard
// so that it is notified everytime a new capture arrives
func NewDashboardConnHandler(list *CaptureList) http.HandlerFunc {
func NewDashboardConnHandler(srv *CaptureService) http.HandlerFunc {
return func(rw http.ResponseWriter, req *http.Request) {
if _, ok := rw.(http.Flusher); !ok {
fmt.Printf("streaming not supported at %s\n", req.URL)
@ -62,12 +62,12 @@ func NewDashboardConnHandler(list *CaptureList) http.HandlerFunc {
rw.Header().Set("Content-Type", "text/event-stream")
rw.Header().Set("Cache-Control", "no-cache")
for {
jsn, _ := json.Marshal(list.ItemsAsMetadata())
jsn, _ := json.Marshal(srv.DashboardItems())
fmt.Fprintf(rw, "event: captures\ndata: %s\n\n", jsn)
rw.(http.Flusher).Flush()
select {
case <-list.Updated():
case <-srv.Updated():
case <-req.Context().Done():
return
}
@ -76,9 +76,9 @@ func NewDashboardConnHandler(list *CaptureList) http.HandlerFunc {
}
// NewDashboardClearHandler clears all the captures
func NewDashboardClearHandler(list *CaptureList) http.HandlerFunc {
func NewDashboardClearHandler(srv *CaptureService) http.HandlerFunc {
return func(rw http.ResponseWriter, req *http.Request) {
list.RemoveAll()
srv.RemoveAll()
rw.WriteHeader(http.StatusOK)
}
}
@ -99,10 +99,10 @@ func NewDashboardHTMLHandler(config Config) http.HandlerFunc {
}
// NewDashboardRetryHandler retries a request
func NewDashboardRetryHandler(list *CaptureList, next http.HandlerFunc) http.HandlerFunc {
func NewDashboardRetryHandler(srv *CaptureService, next http.HandlerFunc) http.HandlerFunc {
return func(rw http.ResponseWriter, req *http.Request) {
id := req.URL.Path[strings.LastIndex(req.URL.Path, "/")+1:]
capture := list.Find(id)
capture := srv.Find(id)
var reqBody []byte
capture.Req.Body, reqBody = drain(capture.Req.Body)
r, _ := http.NewRequest(capture.Req.Method, capture.Req.URL.String(), bytes.NewReader(reqBody))
@ -112,17 +112,17 @@ func NewDashboardRetryHandler(list *CaptureList, next http.HandlerFunc) http.Han
}
// NewDashboardInfoHandler returns the full capture info
func NewDashboardInfoHandler(list *CaptureList) http.HandlerFunc {
func NewDashboardInfoHandler(srv *CaptureService) http.HandlerFunc {
return func(rw http.ResponseWriter, req *http.Request) {
id := req.URL.Path[strings.LastIndex(req.URL.Path, "/")+1:]
capture := list.Find(id)
capture := srv.Find(id)
rw.Header().Add("Content-Type", "application/json")
json.NewEncoder(rw).Encode(dump(capture))
}
}
// NewPlugin loads plugin files in the current directory. They are loaded sorted by filename.
func NewPlugin(next http.HandlerFunc) http.HandlerFunc {
// NewPluginHandler loads plugin files in the current directory. They are loaded sorted by filename.
func NewPluginHandler(next http.HandlerFunc) http.HandlerFunc {
ex, err := os.Executable()
if err != nil {
fmt.Println("error: could not get executable:", err)
@ -161,8 +161,8 @@ func NewPlugin(next http.HandlerFunc) http.HandlerFunc {
return next
}
// NewRecorder saves all the traffic data
func NewRecorder(list *CaptureList, next http.HandlerFunc) http.HandlerFunc {
// NewRecorderHandler saves all the traffic data
func NewRecorderHandler(srv *CaptureService, next http.HandlerFunc) http.HandlerFunc {
return func(rw http.ResponseWriter, req *http.Request) {
// save req body for later
@ -187,7 +187,7 @@ func NewRecorder(list *CaptureList, next http.HandlerFunc) http.HandlerFunc {
// record req and res
req.Body = ioutil.NopCloser(bytes.NewReader(reqBody))
res := rec.Result()
list.Insert(Capture{Req: req, Res: res, Elapsed: elapsed})
srv.Insert(Capture{Req: req, Res: res, Elapsed: elapsed})
}
}