mirror of
https://github.com/chainreactors/spray.git
synced 2025-09-15 11:40:13 +00:00
新增statistor, 用作统计请求概览与断点续传
This commit is contained in:
parent
cd0ede7e1c
commit
cc512829ec
@ -215,6 +215,9 @@ func (opt *Option) PrepareRunner() (*Runner, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
logs.Log.Importantf("Parsed %d words by %s", len(r.Wordlist), opt.Word)
|
logs.Log.Importantf("Parsed %d words by %s", len(r.Wordlist), opt.Word)
|
||||||
|
pkg.DefaultStatistor.Total = len(r.Wordlist)
|
||||||
|
pkg.DefaultStatistor.Word = opt.Word
|
||||||
|
pkg.DefaultStatistor.Dictionaries = opt.Dictionaries
|
||||||
|
|
||||||
if r.Limit == 0 {
|
if r.Limit == 0 {
|
||||||
if r.CheckOnly {
|
if r.CheckOnly {
|
||||||
|
@ -26,6 +26,7 @@ func NewPool(ctx context.Context, config *pkg.Config) (*Pool, error) {
|
|||||||
pctx, cancel := context.WithCancel(ctx)
|
pctx, cancel := context.WithCancel(ctx)
|
||||||
pool := &Pool{
|
pool := &Pool{
|
||||||
Config: config,
|
Config: config,
|
||||||
|
Statistor: pkg.NewStatistor(config.BaseURL),
|
||||||
ctx: pctx,
|
ctx: pctx,
|
||||||
cancel: cancel,
|
cancel: cancel,
|
||||||
client: ihttp.NewClient(config.Thread, 2, config.ClientType),
|
client: ihttp.NewClient(config.Thread, 2, config.ClientType),
|
||||||
@ -68,7 +69,9 @@ func NewPool(ctx context.Context, config *pkg.Config) (*Pool, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var mutex sync.Mutex
|
||||||
p, _ := ants.NewPoolWithFunc(config.Thread, func(i interface{}) {
|
p, _ := ants.NewPoolWithFunc(config.Thread, func(i interface{}) {
|
||||||
|
pool.Statistor.ReqNumber++
|
||||||
unit := i.(*Unit)
|
unit := i.(*Unit)
|
||||||
req, err := pool.genReq(unit.path)
|
req, err := pool.genReq(unit.path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -84,9 +87,17 @@ func NewPool(ctx context.Context, config *pkg.Config) (*Pool, error) {
|
|||||||
|
|
||||||
if reqerr != nil && reqerr != fasthttp.ErrBodyTooLarge {
|
if reqerr != nil && reqerr != fasthttp.ErrBodyTooLarge {
|
||||||
pool.failedCount++
|
pool.failedCount++
|
||||||
|
pool.Statistor.FailedNumber++
|
||||||
bl = &pkg.Baseline{Url: pool.BaseURL + unit.path, IsValid: false, ErrString: reqerr.Error(), Reason: ErrRequestFailed.Error()}
|
bl = &pkg.Baseline{Url: pool.BaseURL + unit.path, IsValid: false, ErrString: reqerr.Error(), Reason: ErrRequestFailed.Error()}
|
||||||
pool.failedBaselines = append(pool.failedBaselines, bl)
|
pool.failedBaselines = append(pool.failedBaselines, bl)
|
||||||
} else {
|
} else {
|
||||||
|
mutex.Lock()
|
||||||
|
if _, ok := pool.Statistor.Counts[resp.StatusCode()]; ok {
|
||||||
|
pool.Statistor.Counts[resp.StatusCode()]++
|
||||||
|
} else {
|
||||||
|
pool.Statistor.Counts[resp.StatusCode()] = 1
|
||||||
|
}
|
||||||
|
mutex.Unlock()
|
||||||
if unit.source != WordSource {
|
if unit.source != WordSource {
|
||||||
bl = pkg.NewBaseline(req.URI(), req.Host(), resp)
|
bl = pkg.NewBaseline(req.URI(), req.Host(), resp)
|
||||||
} else {
|
} else {
|
||||||
@ -136,9 +147,11 @@ func NewPool(ctx context.Context, config *pkg.Config) (*Pool, error) {
|
|||||||
pool.reqCount++
|
pool.reqCount++
|
||||||
if pool.reqCount%pool.CheckPeriod == 0 {
|
if pool.reqCount%pool.CheckPeriod == 0 {
|
||||||
pool.reqCount++
|
pool.reqCount++
|
||||||
|
pool.Statistor.CheckNumber++
|
||||||
go pool.check()
|
go pool.check()
|
||||||
} else if pool.failedCount%pool.ErrPeriod == 0 {
|
} else if pool.failedCount%pool.ErrPeriod == 0 {
|
||||||
pool.failedCount++
|
pool.failedCount++
|
||||||
|
pool.Statistor.CheckNumber++
|
||||||
go pool.check()
|
go pool.check()
|
||||||
}
|
}
|
||||||
pool.bar.Done()
|
pool.bar.Done()
|
||||||
@ -161,7 +174,9 @@ func NewPool(ctx context.Context, config *pkg.Config) (*Pool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if status {
|
if status {
|
||||||
|
pool.Statistor.FoundNumber++
|
||||||
if pool.FilterExpr != nil && pool.CompareWithExpr(pool.FilterExpr, bl) {
|
if pool.FilterExpr != nil && pool.CompareWithExpr(pool.FilterExpr, bl) {
|
||||||
|
pool.Statistor.FilteredNumber++
|
||||||
bl.Reason = ErrCustomFilter.Error()
|
bl.Reason = ErrCustomFilter.Error()
|
||||||
bl.IsValid = false
|
bl.IsValid = false
|
||||||
}
|
}
|
||||||
@ -179,6 +194,7 @@ func NewPool(ctx context.Context, config *pkg.Config) (*Pool, error) {
|
|||||||
|
|
||||||
type Pool struct {
|
type Pool struct {
|
||||||
*pkg.Config
|
*pkg.Config
|
||||||
|
Statistor *pkg.Statistor
|
||||||
client *ihttp.Client
|
client *ihttp.Client
|
||||||
pool *ants.PoolWithFunc
|
pool *ants.PoolWithFunc
|
||||||
bar *pkg.Bar
|
bar *pkg.Bar
|
||||||
@ -237,6 +253,7 @@ func (p *Pool) Init() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pool) Run(ctx context.Context, offset, limit int) {
|
func (p *Pool) Run(ctx context.Context, offset, limit int) {
|
||||||
|
p.Statistor.Offset = offset
|
||||||
Loop:
|
Loop:
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
@ -244,13 +261,13 @@ Loop:
|
|||||||
if !ok {
|
if !ok {
|
||||||
break Loop
|
break Loop
|
||||||
}
|
}
|
||||||
|
p.Statistor.End++
|
||||||
if p.reqCount < offset {
|
if p.reqCount < offset {
|
||||||
p.reqCount++
|
p.reqCount++
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.reqCount > limit {
|
if p.Statistor.End > limit {
|
||||||
break Loop
|
break Loop
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,6 +286,7 @@ Loop:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
p.wg.Wait()
|
p.wg.Wait()
|
||||||
|
p.Statistor.ReqNumber = p.reqCount
|
||||||
p.Close()
|
p.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -327,12 +345,14 @@ func (p *Pool) BaseCompare(bl *pkg.Baseline) bool {
|
|||||||
bl.Collect()
|
bl.Collect()
|
||||||
for _, f := range bl.Frameworks {
|
for _, f := range bl.Frameworks {
|
||||||
if f.Tag == "waf/cdn" {
|
if f.Tag == "waf/cdn" {
|
||||||
|
p.Statistor.WafedNumber++
|
||||||
bl.Reason = ErrWaf.Error()
|
bl.Reason = ErrWaf.Error()
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ok && status == 0 && base.FuzzyCompare(bl) {
|
if ok && status == 0 && base.FuzzyCompare(bl) {
|
||||||
|
p.Statistor.FuzzyNumber++
|
||||||
bl.Reason = ErrFuzzyCompareFailed.Error()
|
bl.Reason = ErrFuzzyCompareFailed.Error()
|
||||||
p.PutToFuzzy(bl)
|
p.PutToFuzzy(bl)
|
||||||
return false
|
return false
|
||||||
|
@ -140,6 +140,8 @@ func (r *Runner) Prepare(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pool.Run(ctx, r.Offset, r.Limit)
|
pool.Run(ctx, r.Offset, r.Limit)
|
||||||
|
logs.Log.Important(pool.Statistor.String())
|
||||||
|
logs.Log.Important(pool.Statistor.Detail())
|
||||||
r.Done()
|
r.Done()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
68
pkg/statistor.go
Normal file
68
pkg/statistor.go
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
package pkg
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var DefaultStatistor Statistor
|
||||||
|
|
||||||
|
func NewStatistor(url string) *Statistor {
|
||||||
|
stat := DefaultStatistor
|
||||||
|
stat.Counts = make(map[int]int)
|
||||||
|
stat.BaseUrl = url
|
||||||
|
return &stat
|
||||||
|
}
|
||||||
|
|
||||||
|
type Statistor struct {
|
||||||
|
BaseUrl string `json:"url"`
|
||||||
|
Counts map[int]int `json:"counts"`
|
||||||
|
ReqNumber int `json:"req"`
|
||||||
|
FailedNumber int `json:"failed"`
|
||||||
|
CheckNumber int `json:"check"`
|
||||||
|
FoundNumber int `json:"found"`
|
||||||
|
FilteredNumber int `json:"filtered"`
|
||||||
|
FuzzyNumber int `json:"fuzzy"`
|
||||||
|
WafedNumber int `json:"wafed"`
|
||||||
|
End int `json:"end"`
|
||||||
|
Offset int `json:"offset"`
|
||||||
|
Total int `json:"total"`
|
||||||
|
Word string `json:"word"`
|
||||||
|
Dictionaries []string `json:"dictionaries"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (stat *Statistor) String() string {
|
||||||
|
var s strings.Builder
|
||||||
|
s.WriteString(fmt.Sprintf("[stat] %s request total: %d, found: %d, check: %d, failed: %d", stat.BaseUrl, stat.ReqNumber, stat.FoundNumber, stat.CheckNumber, stat.FailedNumber))
|
||||||
|
|
||||||
|
if stat.FuzzyNumber != 0 {
|
||||||
|
s.WriteString(", fuzzy: " + strconv.Itoa(stat.FuzzyNumber))
|
||||||
|
}
|
||||||
|
if stat.FilteredNumber != 0 {
|
||||||
|
s.WriteString(", filtered: " + strconv.Itoa(stat.FilteredNumber))
|
||||||
|
}
|
||||||
|
if stat.WafedNumber != 0 {
|
||||||
|
s.WriteString(", wafed: " + strconv.Itoa(stat.WafedNumber))
|
||||||
|
}
|
||||||
|
return s.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (stat *Statistor) Detail() string {
|
||||||
|
var s strings.Builder
|
||||||
|
s.WriteString("[stat] ")
|
||||||
|
s.WriteString(stat.BaseUrl)
|
||||||
|
for k, v := range stat.Counts {
|
||||||
|
s.WriteString(fmt.Sprintf(" %d: %d,", k, v))
|
||||||
|
}
|
||||||
|
return s.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (stat *Statistor) Json() string {
|
||||||
|
content, err := json.Marshal(stat)
|
||||||
|
if err != nil {
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
return string(content)
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user