mirror of
https://github.com/kubeshark/kubeshark.git
synced 2025-09-27 13:33:26 +00:00
Prefix and suffix detected
This commit is contained in:
@@ -2,13 +2,12 @@ package oas
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"github.com/chanced/openapi"
|
||||||
|
"github.com/up9inc/mizu/shared/logger"
|
||||||
"net/url"
|
"net/url"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/chanced/openapi"
|
|
||||||
"github.com/up9inc/mizu/shared/logger"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type NodePath = []string
|
type NodePath = []string
|
||||||
@@ -79,7 +78,7 @@ func (n *Node) getOrSet(path NodePath, existingPathObj *openapi.PathObj) (node *
|
|||||||
logger.Log.Warningf("Failed to add example to a parameter: %s", err)
|
logger.Log.Warningf("Failed to add example to a parameter: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(*exmp) > 1 && node.pathParam.Schema.Pattern == nil { // is it enough to decide on 2 samples?
|
if len(*exmp) >= 3 && node.pathParam.Schema.Pattern == nil { // is it enough to decide on 2 samples?
|
||||||
node.pathParam.Schema.Pattern = getPatternFromExamples(exmp)
|
node.pathParam.Schema.Pattern = getPatternFromExamples(exmp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,6 +95,7 @@ func (n *Node) getOrSet(path NodePath, existingPathObj *openapi.PathObj) (node *
|
|||||||
|
|
||||||
func getPatternFromExamples(exmp *openapi.Examples) *openapi.Regexp {
|
func getPatternFromExamples(exmp *openapi.Examples) *openapi.Regexp {
|
||||||
allInts := true
|
allInts := true
|
||||||
|
strs := make([]string, 0)
|
||||||
for _, example := range *exmp {
|
for _, example := range *exmp {
|
||||||
exampleObj, err := example.ResolveExample(exampleResolver)
|
exampleObj, err := example.ResolveExample(exampleResolver)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -108,6 +108,7 @@ func getPatternFromExamples(exmp *openapi.Examples) *openapi.Regexp {
|
|||||||
logger.Log.Warningf("Failed decoding parameter example into string: %s", err)
|
logger.Log.Warningf("Failed decoding parameter example into string: %s", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
strs = append(strs, value)
|
||||||
|
|
||||||
if _, err := strconv.Atoi(value); err != nil {
|
if _, err := strconv.Atoi(value); err != nil {
|
||||||
allInts = false
|
allInts = false
|
||||||
@@ -118,6 +119,27 @@ func getPatternFromExamples(exmp *openapi.Examples) *openapi.Regexp {
|
|||||||
re := new(openapi.Regexp)
|
re := new(openapi.Regexp)
|
||||||
re.Regexp = regexp.MustCompile(`\d+`)
|
re.Regexp = regexp.MustCompile(`\d+`)
|
||||||
return re
|
return re
|
||||||
|
} else {
|
||||||
|
prefix := longestCommonXfixStr(strs, true)
|
||||||
|
suffix := longestCommonXfixStr(strs, false)
|
||||||
|
|
||||||
|
pat := ""
|
||||||
|
separators := "-._/:|*,+"
|
||||||
|
if len(prefix) > 0 && strings.Contains(separators, string(prefix[len(prefix)-1])) {
|
||||||
|
pat = "^" + regexp.QuoteMeta(prefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
pat += ".+"
|
||||||
|
|
||||||
|
if len(suffix) > 0 && strings.Contains(separators, string(suffix[0])) {
|
||||||
|
pat += regexp.QuoteMeta(suffix) + "$"
|
||||||
|
}
|
||||||
|
|
||||||
|
if pat != ".+" {
|
||||||
|
re := new(openapi.Regexp)
|
||||||
|
re.Regexp = regexp.MustCompile(`\d+`)
|
||||||
|
return re
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -159,19 +181,20 @@ func (n *Node) searchInParams(paramObj *openapi.ParameterObj, chunk string, chun
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if chunkIsGibberish {
|
if paramObj != nil {
|
||||||
return subnode
|
|
||||||
} else if paramObj != nil {
|
|
||||||
// TODO: mergeParam(subnode.pathParam, paramObj)
|
// TODO: mergeParam(subnode.pathParam, paramObj)
|
||||||
return subnode
|
return subnode
|
||||||
} else if subnode.pathParam.Schema.Pattern != nil {
|
} else if subnode.pathParam.Schema.Pattern != nil { // it has defined param pattern, have to respect it
|
||||||
// TODO: and not in exceptions
|
// TODO: and not in exceptions
|
||||||
if subnode.pathParam.Schema.Pattern.Match([]byte(chunk)) {
|
if subnode.pathParam.Schema.Pattern.Match([]byte(chunk)) {
|
||||||
return subnode
|
return subnode
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
} else if chunkIsGibberish {
|
||||||
|
return subnode
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@@ -290,6 +290,53 @@ func longestCommonXfix(strs [][]string, pre bool) []string { // https://github.c
|
|||||||
return xfix
|
return xfix
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func longestCommonXfixStr(strs []string, pre bool) string { // https://github.com/jpillora/longestcommon
|
||||||
|
//short-circuit empty list
|
||||||
|
if len(strs) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
xfix := strs[0]
|
||||||
|
//short-circuit single-element list
|
||||||
|
if len(strs) == 1 {
|
||||||
|
return xfix
|
||||||
|
}
|
||||||
|
//compare first to rest
|
||||||
|
for _, str := range strs[1:] {
|
||||||
|
xfixl := len(xfix)
|
||||||
|
strl := len(str)
|
||||||
|
//short-circuit empty strings
|
||||||
|
if xfixl == 0 || strl == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
//maximum possible length
|
||||||
|
maxl := xfixl
|
||||||
|
if strl < maxl {
|
||||||
|
maxl = strl
|
||||||
|
}
|
||||||
|
//compare letters
|
||||||
|
if pre {
|
||||||
|
//prefix, iterate left to right
|
||||||
|
for i := 0; i < maxl; i++ {
|
||||||
|
if xfix[i] != str[i] {
|
||||||
|
xfix = xfix[:i]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//suffix, iternate right to left
|
||||||
|
for i := 0; i < maxl; i++ {
|
||||||
|
xi := xfixl - i - 1
|
||||||
|
si := strl - i - 1
|
||||||
|
if xfix[xi] != str[si] {
|
||||||
|
xfix = xfix[xi+1:]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return xfix
|
||||||
|
}
|
||||||
|
|
||||||
func getSimilarPrefix(strs []string) string {
|
func getSimilarPrefix(strs []string) string {
|
||||||
chunked := make([][]string, 0)
|
chunked := make([][]string, 0)
|
||||||
for _, item := range strs {
|
for _, item := range strs {
|
||||||
|
Reference in New Issue
Block a user