summarizer.NewResultSummarizer   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 5
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nop 2
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
package summarizer
2
3
import (
4
	"fmt"
5
	"net/http"
6
	"sort"
7
	"sync"
8
9
	"github.com/sirupsen/logrus"
10
	"github.com/stefanoj3/dirstalk/pkg/scan"
11
)
12
13
const (
14
	breakingText = "Found something breaking"
15
	foundText    = "Found"
16
)
17
18
func NewResultSummarizer(treePrinter ResultTree, logger *logrus.Logger) *ResultSummarizer {
19
	return &ResultSummarizer{
20
		treePrinter: treePrinter,
21
		logger:      logger,
22
		resultMap:   make(map[string]struct{}),
23
	}
24
}
25
26
type ResultSummarizer struct {
27
	treePrinter ResultTree
28
	logger      *logrus.Logger
29
	results     []scan.Result
30
	resultMap   map[string]struct{}
31
	mux         sync.RWMutex
32
}
33
34
func (s *ResultSummarizer) Add(result scan.Result) {
35
	s.mux.Lock()
36
	defer s.mux.Unlock()
37
38
	key := keyForResult(result)
39
40
	if _, found := s.resultMap[key]; found {
41
		return
42
	}
43
44
	s.log(result)
45
46
	s.resultMap[key] = struct{}{}
47
48
	s.results = append(s.results, result)
49
}
50
51
func (s *ResultSummarizer) Summarize() {
52
	s.mux.Lock()
53
	defer s.mux.Unlock()
54
55
	sort.Slice(s.results, func(i, j int) bool {
56
		return s.results[i].Target.Path < s.results[j].Target.Path
57
	})
58
59
	s.printSummary()
60
	s.printTree()
61
62
	for _, r := range s.results {
63
		_, _ = fmt.Fprintln(
64
			s.logger.Out,
65
			fmt.Sprintf(
66
				"%s [%d] [%s]",
67
				r.URL.String(),
68
				r.StatusCode,
69
				r.Target.Method,
70
			),
71
		)
72
	}
73
}
74
75
func (s *ResultSummarizer) printSummary() {
76
	_, _ = fmt.Fprintln(
77
		s.logger.Out,
78
		fmt.Sprintf("%d results found", len(s.results)),
79
	)
80
}
81
82
func (s *ResultSummarizer) printTree() {
83
	_, _ = fmt.Fprintln(s.logger.Out, s.treePrinter.String(s.results))
84
}
85
86
func (s *ResultSummarizer) log(result scan.Result) {
87
	statusCode := result.StatusCode
88
89
	l := s.logger.WithFields(logrus.Fields{
90
		"status-code": statusCode,
91
		"method":      result.Target.Method,
92
		"url":         result.URL.String(),
93
	})
94
95
	if statusCode >= http.StatusInternalServerError {
96
		l.Warn(breakingText)
97
	} else {
98
		l.Info(foundText)
99
	}
100
}
101
102
func keyForResult(result scan.Result) string {
103
	return fmt.Sprintf("%s~%s", result.URL.String(), result.Target.Method)
104
}
105