Skip to content

Commit

Permalink
set status code fileter by range
Browse files Browse the repository at this point in the history
  • Loading branch information
hsiafan committed Apr 17, 2019
1 parent ab238f3 commit d979aaa
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 20 deletions.
2 changes: 2 additions & 0 deletions README.md
Expand Up @@ -52,6 +52,8 @@ httpdump can read from pcap file, or capture data from network interfaces:
Filter by port, if either source or target port is matched, the packet will be processed.
-pretty
Try to format and prettify json content
-status string
Filter by response status code
```

## Samples
Expand Down
111 changes: 111 additions & 0 deletions config_struct.go
@@ -0,0 +1,111 @@
package main

import (
"errors"
"strconv"
"strings"
)

// Config is user config for http traffics
type Config struct {
level string
filterIP string
filterPort uint16
host string
uri string
status *IntSet
force bool
pretty bool
output string
}

// parse int set
func ParseIntSet(str string) (*IntSet, error) {
if str == "" {
return nil, errors.New("empty str")
}
var intSet IntSet
for _, item := range strings.Split(str, ":") {
var numbers = strings.Split(item, "-")
if len(numbers) > 2 {
return nil, errors.New("illegal range str: " + item)
}
if len(numbers) == 1 {
start, err := strconv.Atoi(numbers[0])
if err != nil {
return nil, err
}
intSet.ranges = append(intSet.ranges, NewIntRange(start, start))
} else if len(numbers) == 2 {
start, err := strconv.Atoi(numbers[0])
if err != nil {
return nil, err
}
end, err := strconv.Atoi(numbers[1])
if err != nil {
return nil, err
}
intSet.ranges = append(intSet.ranges, NewIntRange(start, end))
}
}
return &intSet, nil
}

// A set of int values
type IntSet struct {
ranges []IntRange
}

// Create new IntSet
func NewIntSet(ranges ...IntRange) *IntSet {
return &IntSet{
ranges: ranges,
}
}

// implement Stringer
func (s *IntSet) String() string {
var sb strings.Builder
for index, r := range s.ranges {
if index > 0 {
sb.WriteRune(':')
}
if r.Start == r.End {
sb.WriteString(strconv.Itoa(r.Start))
} else {
sb.WriteString(strconv.Itoa(r.Start))
sb.WriteRune('-')
sb.WriteString(strconv.Itoa(r.End))
}
}
return sb.String()
}

// If this set contains int value
func (s *IntSet) Contains(value int) bool {
for _, r := range s.ranges {
if r.Contains(value) {
return true
}
}
return false
}

// Range of int value
type IntRange struct {
Start int // inclusive
End int // inclusive
}

// Create new int range
func NewIntRange(start int, end int) IntRange {
return IntRange{
Start: start,
End: end,
}
}

// If this range contains the value
func (r *IntRange) Contains(value int) bool {
return value >= r.Start && value <= r.End
}
18 changes: 18 additions & 0 deletions config_struct_test.go
@@ -0,0 +1,18 @@
package main

import "testing"
import "github.com/stretchr/testify/assert"

func TestIntSet_String(t *testing.T) {
assert.Equal(t, "1", NewIntSet(NewIntRange(1, 1)).String())
assert.Equal(t, "1:1-2", NewIntSet(NewIntRange(1, 1), NewIntRange(1, 2)).String())
}

func TestParseIntSet(t *testing.T) {
intRange, err := ParseIntSet("1:1-2")
assert.NoError(t, err)
assert.Equal(t, 1, intRange.ranges[0].Start)
assert.Equal(t, 1, intRange.ranges[0].End)
assert.Equal(t, 1, intRange.ranges[1].Start)
assert.Equal(t, 2, intRange.ranges[1].End)
}
4 changes: 2 additions & 2 deletions http_traffic_handler.go
Expand Up @@ -17,7 +17,7 @@ import (
"github.com/google/gopacket/tcpassembly/tcpreader"
)

// ConnectionKey contains src and dst endpoint idendity a connection
// ConnectionKey contains src and dst endpoint identify a connection
type ConnectionKey struct {
src Endpoint
dst Endpoint
Expand Down Expand Up @@ -121,7 +121,7 @@ func (h *HTTPTrafficHandler) handle(connection *TCPConnection) {
break
}

if h.config.status != 0 && h.config.status != resp.StatusCode {
if h.config.status != nil && !h.config.status.Contains(resp.StatusCode) {
filtered = true
}

Expand Down
30 changes: 12 additions & 18 deletions main.go
Expand Up @@ -26,19 +26,6 @@ func init() {
var waitGroup sync.WaitGroup
var printerWaitGroup sync.WaitGroup

// Config is user config for http traffics
type Config struct {
level string
filterIP string
filterPort uint16
host string
uri string
status int
force bool
pretty bool
output string
}

func listenOneSource(handle *pcap.Handle) chan gopacket.Packet {
packetSource := gopacket.NewPacketSource(handle, handle.LinkType())
packets := packetSource.Packets()
Expand Down Expand Up @@ -90,9 +77,7 @@ func openSingleDevice(device string, filterIP string, filterPort uint16) (localP
}

if err := setDeviceFilter(handle, filterIP, filterPort); err != nil {
if err != nil {
logger.Warn("set capture filter failed, ", err)
}
logger.Warn("set capture filter failed, ", err)
}
localPackets = listenOneSource(handle)
return
Expand All @@ -107,7 +92,7 @@ func main() {
var filterPort = flagSet.Uint("port", 0, "Filter by port, if either source or target port is matched, the packet will be processed.")
var host = flagSet.String("filter-host", "", "Filter by request host, using wildcard match(*, ?)")
var uri = flagSet.String("filter-uri", "", "Filter by request url path, using wildcard match(*, ?)")
var status = flagSet.Int("status", 0, "Filter by response status code")
var status = flagSet.String("status", "", "Filter by response status code")
var force = flagSet.Bool("force", false, "Force print unknown content-type http body even if it seems not to be text content")
var pretty = flagSet.Bool("pretty", false, "Try to format and prettify json content")
var output = flagSet.String("output", "", "Write result to file [output] instead of stdout")
Expand All @@ -118,13 +103,22 @@ func main() {
*filterPort = 0
}

var statusSet *IntSet
if *status != "" {
var err error
if statusSet, err = ParseIntSet(*status); err != nil {
fmt.Fprint(os.Stderr, "status range not valid ", *status)
return
}
}

var config = &Config{
level: *level,
filterIP: *filterIP,
filterPort: uint16(*filterPort),
host: *host,
uri: *uri,
status: *status,
status: statusSet,
force: *force,
pretty: *pretty,
output: *output,
Expand Down

0 comments on commit d979aaa

Please sign in to comment.