feat: add jsonl_rename_key utility function and remove tablewriter dependency

- Add jsonl_rename_key() function to rename keys in JSONL files with mapping syntax 'old1:new1,old2:new2'
- Implements fast JSON parsing with fastjson and efficient buffered I/O for large files
- Include comprehensive test coverage with 7 test cases for edge cases and valid mappings
- Remove unused tablewriter dependency from go.mod/go.sum and internal/terminal/table.go
- Refactor printResultSummary() to use markdown table printing instead of tablewriter
- Add test data file ffuf-result.jsonl for integration testing
- Fix function list width default calculation in function.go
This commit is contained in:
j3ssie
2026-02-17 01:43:04 +07:00
parent bd1434739e
commit d01bd326df
10 changed files with 363 additions and 115 deletions
-1
View File
@@ -29,7 +29,6 @@ require (
github.com/json-iterator/go v1.1.12
github.com/mattn/go-sqlite3 v1.14.32
github.com/minio/minio-go/v7 v7.0.97
github.com/olekukonko/tablewriter v0.0.5
github.com/orivej/go-nix v0.0.0-20180830055821-dae45d921a44
github.com/pkg/sftp v1.13.9
github.com/prometheus/client_golang v1.23.2
-3
View File
@@ -285,7 +285,6 @@ github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw=
github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
@@ -327,8 +326,6 @@ github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJm
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY=
github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/gomega v1.38.3 h1:eTX+W6dobAYfFeGC2PV6RwXRu/MyT+cQguijutvkpSM=
github.com/onsi/gomega v1.38.3/go.mod h1:ZCU1pkQcXDO5Sl9/VVEGlDyp+zm0m1cmeG5TOzLgdh4=
github.com/opentracing/basictracer-go v1.1.0 h1:Oa1fTSBvAl8pa3U+IJYqrKm0NALwH9OsgwOqDv4xJW0=
+8 -5
View File
@@ -276,11 +276,12 @@ const (
// Output Functions - Save content to files
const (
FnSaveContent = "save_content" // save_content(content, path) -> bool
FnJSONLToCSV = "jsonl_to_csv"
FnCSVToJSONL = "csv_to_jsonl"
FnJSONLUnique = "jsonl_unique"
FnJSONLFilter = "jsonl_filter"
FnSaveContent = "save_content" // save_content(content, path) -> bool
FnJSONLToCSV = "jsonl_to_csv"
FnCSVToJSONL = "csv_to_jsonl"
FnJSONLUnique = "jsonl_unique"
FnJSONLFilter = "jsonl_filter"
FnJSONLRenameKey = "jsonl_rename_key"
)
// URL Processing Functions - URL deduplication, filtering, and parsing
@@ -559,6 +560,7 @@ func AllFunctions() []string {
FnCSVToJSONL,
FnJSONLUnique,
FnJSONLFilter,
FnJSONLRenameKey,
// URL Processing Functions
FnInterestingUrls,
@@ -927,6 +929,7 @@ func FunctionRegistry() map[string][]FunctionInfo {
{FnRunNmap, "run_nmap(target, flags?, output?)", "Run nmap scan and auto-convert to JSONL (XML → JSONL)", "string", "run_nmap('192.168.1.0/24', '-sV -p-', '{{Output}}/scan.jsonl')"},
{FnJSONLUnique, "jsonl_unique(source, dest, fields)", "Deduplicate JSONL by hashing selected fields", "bool", "jsonl_unique('{{Output}}/httpx.jsonl', '{{Output}}/httpx.unique.jsonl', ['status','words','lines'])"},
{FnJSONLFilter, "jsonl_filter(source, dest, fields)", "Filter JSONL to selected fields (comma or array)", "bool", "jsonl_filter('{{Output}}/httpx.jsonl', '{{Output}}/httpx.filtered.jsonl', 'host,status,hash.body_sha256')"},
{FnJSONLRenameKey, "jsonl_rename_key(source, dest, mappings)", "Rename keys in JSONL (mappings: 'old1:new1,old2:new2')", "bool", "jsonl_rename_key('{{Output}}/httpx.jsonl', '{{Output}}/httpx.renamed.jsonl', 'host:domain,status:status_code')"},
},
CategoryURLProcessing: {
{FnInterestingUrls, "interesting_urls(src, dest, json_field?)", "Deduplicate URLs by hostname+path+params, filter static files and noise patterns", "bool", "interesting_urls('{{Output}}/all-urls.txt', '{{Output}}/interesting-urls.txt', 'url')"},
+1
View File
@@ -226,6 +226,7 @@ func (r *GojaRuntime) registerFunctionsOnVM(vm *goja.Runtime) {
_ = vm.Set(FnCSVToJSONL, vf.csvToJSONL)
_ = vm.Set(FnJSONLUnique, vf.jsonlUnique)
_ = vm.Set(FnJSONLFilter, vf.jsonlFilter)
_ = vm.Set(FnJSONLRenameKey, vf.jsonlRenameKey)
// URL processing functions
_ = vm.Set(FnInterestingUrls, vf.interestingUrls)
+134
View File
@@ -672,6 +672,140 @@ func (vf *vmFunc) jsonlFilter(call goja.FunctionCall) goja.Value {
return vf.vm.ToValue(true)
}
func (vf *vmFunc) jsonlRenameKey(call goja.FunctionCall) goja.Value {
logger.Get().Debug("Calling jsonlRenameKey")
if len(call.Arguments) < 3 {
logger.Get().Warn("jsonlRenameKey: requires 3 arguments (source, dest, mappings)")
return vf.vm.ToValue(false)
}
source := call.Argument(0).String()
dest := call.Argument(1).String()
mappingsRaw := call.Argument(2).String()
if source == "undefined" || source == "" || dest == "undefined" || dest == "" || mappingsRaw == "undefined" || mappingsRaw == "" {
logger.Get().Warn("jsonlRenameKey: empty source, dest, or mappings")
return vf.vm.ToValue(false)
}
// Parse mappings: "old1:new1,old2:new2"
type keyMapping struct {
oldKey string
newKey string
}
var mappings []keyMapping
for _, pair := range strings.Split(mappingsRaw, ",") {
pair = strings.TrimSpace(pair)
if pair == "" {
continue
}
parts := strings.SplitN(pair, ":", 2)
if len(parts) != 2 || strings.TrimSpace(parts[0]) == "" || strings.TrimSpace(parts[1]) == "" {
logger.Get().Warn("jsonlRenameKey: invalid mapping pair", zap.String("pair", pair))
continue
}
mappings = append(mappings, keyMapping{oldKey: strings.TrimSpace(parts[0]), newKey: strings.TrimSpace(parts[1])})
}
if len(mappings) == 0 {
logger.Get().Warn("jsonlRenameKey: no valid mappings found", zap.String("mappings", mappingsRaw))
return vf.vm.ToValue(false)
}
logger.Get().Debug("jsonlRenameKey arguments",
zap.String("source", source), zap.String("dest", dest), zap.Int("mappings", len(mappings)))
f, err := os.Open(source)
if err != nil {
logger.Get().Warn("jsonlRenameKey: failed to open source", zap.String("source", source), zap.Error(err))
return vf.vm.ToValue(false)
}
defer func() { _ = f.Close() }()
if err := os.MkdirAll(filepath.Dir(dest), 0755); err != nil {
logger.Get().Warn("jsonlRenameKey: failed to create destination directory", zap.String("dest", dest), zap.Error(err))
return vf.vm.ToValue(false)
}
out, err := os.Create(dest)
if err != nil {
logger.Get().Warn("jsonlRenameKey: failed to create destination file", zap.String("dest", dest), zap.Error(err))
return vf.vm.ToValue(false)
}
defer func() { _ = out.Close() }()
scanner := bufio.NewScanner(f)
scanner.Buffer(make([]byte, 64*1024), 10*1024*1024)
writer := bufio.NewWriterSize(out, 256*1024)
defer func() { _ = writer.Flush() }()
lineCount := 0
outCount := 0
var p fastjson.Parser
var arena fastjson.Arena
for scanner.Scan() {
raw := strings.TrimSpace(scanner.Text())
if raw == "" {
continue
}
lineCount++
v, err := p.Parse(raw)
if err != nil {
continue
}
obj := v.GetObject()
if obj == nil {
continue
}
arena.Reset()
result := arena.NewObject()
// Copy all keys, renaming where a mapping exists
// Build a lookup map for old->new
renameMap := make(map[string]string, len(mappings))
for _, m := range mappings {
renameMap[m.oldKey] = m.newKey
}
obj.Visit(func(key []byte, val *fastjson.Value) {
k := string(key)
if newKey, ok := renameMap[k]; ok {
result.Set(newKey, val)
} else {
result.Set(k, val)
}
})
if _, err := writer.Write(result.MarshalTo(nil)); err != nil {
logger.Get().Warn("jsonlRenameKey: failed writing output", zap.Error(err))
return vf.vm.ToValue(false)
}
if err := writer.WriteByte('\n'); err != nil {
logger.Get().Warn("jsonlRenameKey: failed writing newline", zap.Error(err))
return vf.vm.ToValue(false)
}
outCount++
}
if err := scanner.Err(); err != nil {
logger.Get().Warn("jsonlRenameKey: failed reading source", zap.String("source", source), zap.Error(err))
return vf.vm.ToValue(false)
}
if err := writer.Flush(); err != nil {
logger.Get().Warn("jsonlRenameKey: failed flushing output", zap.Error(err))
return vf.vm.ToValue(false)
}
logger.Get().Debug("jsonlRenameKey completed", zap.Int("lines", lineCount), zap.Int("written", outCount))
return vf.vm.ToValue(true)
}
func (vf *vmFunc) jsonlUnique(call goja.FunctionCall) goja.Value {
logger.Get().Debug("Calling jsonlUnique")
@@ -708,3 +708,152 @@ func TestJSONLUnique(t *testing.T) {
require.Len(t, lines, 1)
})
}
func TestJSONLRenameKey(t *testing.T) {
runtime := NewOttoRuntime()
t.Run("renames single key", func(t *testing.T) {
tmpDir := t.TempDir()
source := filepath.Join(tmpDir, "in.jsonl")
dest := filepath.Join(tmpDir, "out.jsonl")
content := `{"host":"example.com","status":200}` + "\n" +
`{"host":"test.com","status":404}` + "\n"
err := os.WriteFile(source, []byte(content), 0644)
require.NoError(t, err)
result, err := runtime.Execute(
`jsonl_rename_key("`+source+`", "`+dest+`", "host:domain")`,
nil,
)
require.NoError(t, err)
assert.Equal(t, true, result)
out, err := os.ReadFile(dest)
require.NoError(t, err)
lines := strings.Split(strings.TrimSpace(string(out)), "\n")
require.Len(t, lines, 2)
assert.Contains(t, lines[0], `"domain"`)
assert.NotContains(t, lines[0], `"host"`)
assert.Contains(t, lines[0], `"status"`)
})
t.Run("renames multiple keys", func(t *testing.T) {
tmpDir := t.TempDir()
source := filepath.Join(tmpDir, "in.jsonl")
dest := filepath.Join(tmpDir, "out.jsonl")
content := `{"host":"example.com","status":200,"words":50}` + "\n"
err := os.WriteFile(source, []byte(content), 0644)
require.NoError(t, err)
result, err := runtime.Execute(
`jsonl_rename_key("`+source+`", "`+dest+`", "host:domain,status:status_code")`,
nil,
)
require.NoError(t, err)
assert.Equal(t, true, result)
out, err := os.ReadFile(dest)
require.NoError(t, err)
lines := strings.Split(strings.TrimSpace(string(out)), "\n")
require.Len(t, lines, 1)
assert.Contains(t, lines[0], `"domain"`)
assert.Contains(t, lines[0], `"status_code"`)
assert.Contains(t, lines[0], `"words"`)
assert.NotContains(t, lines[0], `"host"`)
assert.NotContains(t, lines[0], `"status":`)
})
t.Run("preserves keys without mappings", func(t *testing.T) {
tmpDir := t.TempDir()
source := filepath.Join(tmpDir, "in.jsonl")
dest := filepath.Join(tmpDir, "out.jsonl")
content := `{"a":1,"b":2,"c":3}` + "\n"
err := os.WriteFile(source, []byte(content), 0644)
require.NoError(t, err)
result, err := runtime.Execute(
`jsonl_rename_key("`+source+`", "`+dest+`", "a:x")`,
nil,
)
require.NoError(t, err)
assert.Equal(t, true, result)
out, err := os.ReadFile(dest)
require.NoError(t, err)
assert.Contains(t, string(out), `"x"`)
assert.Contains(t, string(out), `"b"`)
assert.Contains(t, string(out), `"c"`)
assert.NotContains(t, string(out), `"a"`)
})
t.Run("skips invalid JSON lines", func(t *testing.T) {
tmpDir := t.TempDir()
source := filepath.Join(tmpDir, "in.jsonl")
dest := filepath.Join(tmpDir, "out.jsonl")
content := `{"host":"a.com"}` + "\n" +
"not json\n" +
`{"host":"b.com"}` + "\n"
err := os.WriteFile(source, []byte(content), 0644)
require.NoError(t, err)
result, err := runtime.Execute(
`jsonl_rename_key("`+source+`", "`+dest+`", "host:domain")`,
nil,
)
require.NoError(t, err)
assert.Equal(t, true, result)
out, err := os.ReadFile(dest)
require.NoError(t, err)
lines := strings.Split(strings.TrimSpace(string(out)), "\n")
require.Len(t, lines, 2)
})
t.Run("empty mappings returns false", func(t *testing.T) {
tmpDir := t.TempDir()
source := filepath.Join(tmpDir, "in.jsonl")
dest := filepath.Join(tmpDir, "out.jsonl")
err := os.WriteFile(source, []byte(`{"a":1}`+"\n"), 0644)
require.NoError(t, err)
result, err := runtime.Execute(
`jsonl_rename_key("`+source+`", "`+dest+`", "")`,
nil,
)
require.NoError(t, err)
assert.Equal(t, false, result)
})
t.Run("missing arguments returns false", func(t *testing.T) {
result, err := runtime.Execute(
`jsonl_rename_key("source", "dest")`,
nil,
)
require.NoError(t, err)
assert.Equal(t, false, result)
})
t.Run("creates output directory if not exists", func(t *testing.T) {
tmpDir := t.TempDir()
source := filepath.Join(tmpDir, "in.jsonl")
dest := filepath.Join(tmpDir, "nested", "dir", "out.jsonl")
err := os.WriteFile(source, []byte(`{"a":1}`+"\n"), 0644)
require.NoError(t, err)
result, err := runtime.Execute(
`jsonl_rename_key("`+source+`", "`+dest+`", "a:b")`,
nil,
)
require.NoError(t, err)
assert.Equal(t, true, result)
_, err = os.Stat(dest)
assert.NoError(t, err)
})
}
-92
View File
@@ -1,92 +0,0 @@
package terminal
import (
"io"
"os"
"github.com/olekukonko/tablewriter"
)
// NewTable creates a new table with consistent styling (no borders)
func NewTable(w io.Writer, header []string) *tablewriter.Table {
if w == nil {
w = os.Stdout
}
table := tablewriter.NewWriter(w)
table.SetHeader(header)
// Clean styling without borders
table.SetBorder(false)
table.SetRowLine(false)
table.SetCenterSeparator("")
table.SetColumnSeparator("")
table.SetRowSeparator("")
table.SetHeaderLine(false)
table.SetAutoWrapText(false)
table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
table.SetAlignment(tablewriter.ALIGN_LEFT)
table.SetTablePadding(" ")
table.SetNoWhiteSpace(true)
if colorEnabled {
colors := make([]tablewriter.Colors, len(header))
for i := range colors {
colors[i] = tablewriter.Colors{tablewriter.Bold, tablewriter.FgCyanColor}
}
table.SetHeaderColor(colors...)
}
return table
}
// NewBorderedTable creates a table with borders
func NewBorderedTable(w io.Writer, header []string) *tablewriter.Table {
if w == nil {
w = os.Stdout
}
table := tablewriter.NewWriter(w)
table.SetHeader(header)
table.SetBorder(true)
table.SetRowLine(true)
table.SetHeaderAlignment(tablewriter.ALIGN_CENTER)
table.SetAlignment(tablewriter.ALIGN_LEFT)
if colorEnabled {
colors := make([]tablewriter.Colors, len(header))
for i := range colors {
colors[i] = tablewriter.Colors{tablewriter.Bold, tablewriter.FgCyanColor}
}
table.SetHeaderColor(colors...)
}
return table
}
// NewSimpleTable creates a minimal table without header styling
func NewSimpleTable(w io.Writer, header []string) *tablewriter.Table {
if w == nil {
w = os.Stdout
}
table := tablewriter.NewWriter(w)
table.SetHeader(header)
table.SetBorder(false)
table.SetCenterSeparator("")
table.SetColumnSeparator(" ")
table.SetRowSeparator("")
table.SetHeaderLine(true)
table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
table.SetAlignment(tablewriter.ALIGN_LEFT)
return table
}
// TableWithColors creates a table and applies color functions to columns
func TableWithColors(w io.Writer, header []string, columnColors []func(string) string) *tablewriter.Table {
table := NewTable(w, header)
// Note: tablewriter doesn't support per-cell coloring via functions
// Colors need to be applied to the data before appending
return table
}
+4 -4
View File
@@ -435,11 +435,11 @@ func runFunctionList(cmd *cobra.Command, args []string) error {
}
headers := []string{"Category", "Function", "Description", "Returns"}
if globalWidth > 0 {
printMarkdownTableWithWidth(headers, rows, globalWidth)
} else {
printMarkdownTable(headers, rows)
width := globalWidth
if width <= 0 {
width = 65
}
printMarkdownTableWithWidth(headers, rows, width)
return nil
}
+3 -10
View File
@@ -32,7 +32,6 @@ import (
"github.com/j3ssie/osmedeus/v5/internal/logger"
"github.com/j3ssie/osmedeus/v5/internal/parser"
"github.com/j3ssie/osmedeus/v5/internal/terminal"
"github.com/olekukonko/tablewriter"
"github.com/spf13/cobra"
"go.uber.org/zap"
)
@@ -1489,21 +1488,15 @@ func printResultSummary(result *core.WorkflowResult) {
if len(result.Steps) > 0 {
fmt.Println()
fmt.Println(terminal.ResultSymbol() + " " + terminal.Bold("Step Results:"))
table := terminal.NewTable(os.Stdout, []string{"Status", "Step", "Duration"})
table.SetColumnAlignment([]int{
tablewriter.ALIGN_LEFT, // Status
tablewriter.ALIGN_LEFT, // Step
tablewriter.ALIGN_CENTER, // Duration - center align for better visual alignment
})
var rows [][]string
for _, step := range result.Steps {
table.Append([]string{
rows = append(rows, []string{
terminal.PaddedStepSymbol(string(step.Status)),
step.StepName,
formatDuration(step.Duration),
})
}
table.Render()
printMarkdownTable([]string{"Status", "Step", "Duration"}, rows)
}
if len(result.Artifacts) > 0 {
+64
View File
@@ -0,0 +1,64 @@
{"input":{"FFUFHASH":"MWUzZGIyMDVj","FUZZ":"YXBp"},"position":8284,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api","duration":297816208,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGIyMDVl","FUZZ":"YXBpLWRvY3M="},"position":8286,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api-docs","duration":379254333,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGIyMDYx","FUZZ":"YXBpL2Vycm9yX2xvZw=="},"position":8289,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/error_log","duration":309499125,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGIyMDVm","FUZZ":"YXBpLmxvZw=="},"position":8287,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api.log","duration":324116834,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGIyMDYw","FUZZ":"YXBpLw=="},"position":8288,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/","duration":390379833,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGIyMDYy","FUZZ":"YXBpL3N3YWdnZXIueW1s"},"position":8290,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/swagger.yml","duration":384793917,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGIyMDYz","FUZZ":"YXBpYnVpbGQucHlj"},"position":8291,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/apibuild.pyc","duration":895151875,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGIyMDVk","FUZZ":"YXBpLWRvYw=="},"position":8285,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api-doc","duration":5458008833,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGIyZDQy","FUZZ":"bG9naW4="},"position":11586,"status":200,"length":53283,"words":3333,"lines":371,"content-type":"text/html; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/login","duration":320204125,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGIyZDY5","FUZZ":"bG9naW4v"},"position":11625,"status":200,"length":53283,"words":3333,"lines":371,"content-type":"text/html; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/login/","duration":377887500,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGIzNTgy","FUZZ":"cm9ib3RzLnR4dA=="},"position":13698,"status":200,"length":26,"words":3,"lines":3,"content-type":"text/plain; charset=utf-8","redirectlocation":"","url":"http://102.88.154.187:3000/robots.txt","duration":407736541,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGIzNzVl","FUZZ":"c2lnbnVw"},"position":14174,"status":200,"length":53283,"words":3333,"lines":371,"content-type":"text/html; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/signup","duration":361819042,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGIzZTEy","FUZZ":"YXBpL2V4cGVyaW1lbnRzL2NvbmZpZ3VyYXRpb25z"},"position":15890,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/experiments/configurations","duration":325372875,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGIzZTEx","FUZZ":"YXBpL2V4cGVyaW1lbnRz"},"position":15889,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/experiments","duration":376589875,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGIzZTEz","FUZZ":"YXBpcw=="},"position":15891,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/apis","duration":400421083,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0Mjg2","FUZZ":"aGVhbHRoeg=="},"position":17030,"status":200,"length":2,"words":1,"lines":1,"content-type":"text/plain; charset=utf-8","redirectlocation":"","url":"http://102.88.154.187:3000/healthz","duration":307148208,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDQy","FUZZ":"YXBpLnRhci5neg=="},"position":19778,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api.tar.gz","duration":328882292,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDQx","FUZZ":"YXBpLnB5"},"position":19777,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api.py","duration":337278667,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDQw","FUZZ":"YXBpLnBocA=="},"position":19776,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api.php","duration":337704792,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDQ0","FUZZ":"YXBpLnppcA=="},"position":19780,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api.zip","duration":371168167,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDQz","FUZZ":"YXBpLnRneg=="},"position":19779,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api.tgz","duration":371482209,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDQ1","FUZZ":"YXBpLzIvZXhwbG9yZS8="},"position":19781,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/2/explore/","duration":376365209,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDQ2","FUZZ":"YXBpL2VudHJ5cG9pbnRz"},"position":19782,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/entrypoints","duration":376451291,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDQ3","FUZZ":"YXBpL2dyYXBoaXFs"},"position":19783,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/graphiql","duration":376461041,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDQ4","FUZZ":"YXBpL2dyYXBocWw="},"position":19784,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/graphql","duration":376495250,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDRi","FUZZ":"YXBpL2h0dHAvc2VydmljZXM="},"position":19787,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/http/services","duration":302354333,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDQ5","FUZZ":"YXBpL2h0dHAvbWlkZGxld2FyZXM="},"position":19785,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/http/middlewares","duration":376457041,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDRj","FUZZ":"YXBpL2pzb253cw=="},"position":19788,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/jsonws","duration":303586292,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDRk","FUZZ":"YXBpL2xvZ2luLmpzb24="},"position":19789,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/login.json","duration":303625750,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDRl","FUZZ":"YXBpL292ZXJ2aWV3"},"position":19790,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/overview","duration":300822584,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDRm","FUZZ":"YXBpL3BhY2thZ2Vfc2VhcmNoL3Y0L2RvY3VtZW50YXRpb24="},"position":19791,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/package_search/v4/documentation","duration":309602208,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDUx","FUZZ":"YXBpL3N3YWdnZXI="},"position":19793,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/swagger","duration":307041417,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDUw","FUZZ":"YXBpL3Jhd2RhdGE="},"position":19792,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/rawdata","duration":307408917,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDUy","FUZZ":"YXBpL3N3YWdnZXItdWkuaHRtbA=="},"position":19794,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/swagger-ui.html","duration":307160500,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDRh","FUZZ":"YXBpL2h0dHAvcm91dGVycw=="},"position":19786,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/http/routers","duration":387040792,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDU2","FUZZ":"YXBpL3VkcC9yb3V0ZXJz"},"position":19798,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/udp/routers","duration":347295250,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDU0","FUZZ":"YXBpL3RjcC9yb3V0ZXJz"},"position":19796,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/tcp/routers","duration":348795834,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDUz","FUZZ":"YXBpL3RjcC9taWRkbGV3YXJlcw=="},"position":19795,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/tcp/middlewares","duration":348924458,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDU1","FUZZ":"YXBpL3RjcC9zZXJ2aWNlcw=="},"position":19797,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/tcp/services","duration":352227959,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDVh","FUZZ":"YXBpL3YxL2dyYXBocWw="},"position":19802,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/v1/graphql","duration":343564458,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDU3","FUZZ":"YXBpL3VkcC9zZXJ2aWNlcw=="},"position":19799,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/udp/services","duration":346160667,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDU5","FUZZ":"YXBpL3YxL2dyYXBoaXFs"},"position":19801,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/v1/graphiql","duration":348964000,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDU4","FUZZ":"YXBpL3Yx"},"position":19800,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/v1","duration":349053167,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDVi","FUZZ":"YXBpL3YxL3BsYXlncm91bmQ="},"position":19803,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/v1/playground","duration":349308958,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDVk","FUZZ":"YXBpL3YyL2dyYXBoaXFs"},"position":19805,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/v2/graphiql","duration":313760292,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDVj","FUZZ":"YXBpL3Yy"},"position":19804,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/v2","duration":314004250,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDYy","FUZZ":"YXBpL3YzL2dyYXBocWw="},"position":19810,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/v3/graphql","duration":308185583,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDY0","FUZZ":"YXBpL3ZlcnNpb24="},"position":19812,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/version","duration":305395292,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDY1","FUZZ":"YXBpX2xvZy50eHQ="},"position":19813,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api_log.txt","duration":305319834,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDY2","FUZZ":"YXBpZG9j"},"position":19814,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/apidoc","duration":305667125,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDVl","FUZZ":"YXBpL3YyL2dyYXBocWw="},"position":19806,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/v2/graphql","duration":313934250,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDYx","FUZZ":"YXBpL3YzL2dyYXBoaXFs"},"position":19809,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/v3/graphiql","duration":313473000,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDYw","FUZZ":"YXBpL3Yz"},"position":19808,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/v3","duration":313904250,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDVm","FUZZ":"YXBpL3YyL3BsYXlncm91bmQ="},"position":19807,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/v2/playground","duration":314220084,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDYz","FUZZ":"YXBpL3YzL3BsYXlncm91bmQ="},"position":19811,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/api/v3/playground","duration":315612875,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDY3","FUZZ":"YXBpZG9jcw=="},"position":19815,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/apidocs","duration":314153791,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDY4","FUZZ":"YXBpc2VydmVyLWFnZ3JlZ2F0b3ItY2EuY2VydA=="},"position":19816,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/apiserver-aggregator-ca.cert","duration":314202500,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDZh","FUZZ":"YXBpc2VydmVyLWFnZ3JlZ2F0b3Iua2V5"},"position":19818,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/apiserver-aggregator.key","duration":314058875,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDY5","FUZZ":"YXBpc2VydmVyLWFnZ3JlZ2F0b3IuY2VydA=="},"position":19817,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/apiserver-aggregator.cert","duration":314194417,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDZi","FUZZ":"YXBpc2VydmVyLWNsaWVudC5jcnQ="},"position":19819,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/apiserver-client.crt","duration":323116750,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI0ZDZj","FUZZ":"YXBpc2VydmVyLWtleS5wZW0="},"position":19820,"status":401,"length":102,"words":1,"lines":2,"content-type":"application/json; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/apiserver-key.pem","duration":392598459,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI1MGJi","FUZZ":"bWV0cmljcw=="},"position":20667,"status":200,"length":6585570,"words":51403,"lines":44236,"content-type":"text/plain; version=0.0.4; charset=utf-8; escaping=underscores","redirectlocation":"","url":"http://102.88.154.187:3000/metrics","duration":379000292,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI1MjYx","FUZZ":"c3dhZ2dlcg=="},"position":21089,"status":200,"length":1586,"words":202,"lines":45,"content-type":"text/html; charset=UTF-8","redirectlocation":"","url":"http://102.88.154.187:3000/swagger","duration":440555584,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}
{"input":{"FFUFHASH":"MWUzZGI1MjYz","FUZZ":"c3dhZ2dlci11aQ=="},"position":21091,"status":301,"length":43,"words":3,"lines":3,"content-type":"text/html; charset=utf-8","redirectlocation":"/swagger","url":"http://102.88.154.187:3000/swagger-ui","duration":436819709,"scraper":{},"resultfile":"","host":"102.88.154.187:3000"}