finish params check v2

This commit is contained in:
Liujian
2025-01-14 18:53:54 +08:00
parent b7880c92ee
commit 27cd8e68b2
9 changed files with 134 additions and 58 deletions
+2 -1
View File
@@ -16,6 +16,7 @@ import (
js_inject "github.com/eolinker/apinto/drivers/plugins/js-inject"
"github.com/eolinker/apinto/drivers/plugins/oauth2"
params_check "github.com/eolinker/apinto/drivers/plugins/params-check"
params_check_v2 "github.com/eolinker/apinto/drivers/plugins/params-check-v2"
"github.com/eolinker/apinto/drivers/plugins/prometheus"
request_file_parse "github.com/eolinker/apinto/drivers/plugins/request-file-parse"
request_interception "github.com/eolinker/apinto/drivers/plugins/request-interception"
@@ -82,7 +83,7 @@ func pluginRegister(extenderRegister eosc.IExtenderDriverRegister) {
proxy_rewrite_v2.Register(extenderRegister)
http_mocking.Register(extenderRegister)
params_check.Register(extenderRegister)
//params_check_v2.Register(extenderRegister)
params_check_v2.Register(extenderRegister)
data_transform.Register(extenderRegister)
request_interception.Register(extenderRegister)
request_file_parse.Register(extenderRegister)
+23 -14
View File
@@ -19,7 +19,7 @@ var (
)
type IParamChecker interface {
Check(logic string, header http_service.IHeaderReader, query http_service.IQueryReader, body interface{}, fn bodyCheckerFunc) bool
Check(header http_service.IHeaderReader, query http_service.IQueryReader, body interface{}, fn bodyCheckerFunc) bool
}
type headerChecker struct {
@@ -27,7 +27,7 @@ type headerChecker struct {
checker checker.Checker
}
func (h *headerChecker) Check(logic string, header http_service.IHeaderReader, query http_service.IQueryReader, body interface{}, fn bodyCheckerFunc) bool {
func (h *headerChecker) Check(header http_service.IHeaderReader, query http_service.IQueryReader, body interface{}, fn bodyCheckerFunc) bool {
v := header.GetHeader(h.name)
match := h.checker.Check(v, true)
if !match {
@@ -49,7 +49,7 @@ type queryChecker struct {
checker checker.Checker
}
func (q *queryChecker) Check(logic string, header http_service.IHeaderReader, query http_service.IQueryReader, body interface{}, fn bodyCheckerFunc) bool {
func (q *queryChecker) Check(header http_service.IHeaderReader, query http_service.IQueryReader, body interface{}, fn bodyCheckerFunc) bool {
v := query.GetQuery(q.name)
match := q.checker.Check(v, true)
if !match {
@@ -91,7 +91,7 @@ func newBodyChecker(name string, matchText string, matchMode string) (*bodyCheck
}, nil
}
func (b *bodyChecker) Check(logic string, header http_service.IHeaderReader, query http_service.IQueryReader, body interface{}, fn bodyCheckerFunc) bool {
func (b *bodyChecker) Check(header http_service.IHeaderReader, query http_service.IQueryReader, body interface{}, fn bodyCheckerFunc) bool {
return fn(body, b) == nil
}
@@ -103,7 +103,10 @@ type paramChecker struct {
checker IParamChecker
}
func genParamChecker(param *Param) (IParamChecker, error) {
func genParamChecker(param *SubParam) (IParamChecker, error) {
if param == nil {
return nil, nil
}
if param.Position == "" {
return nil, nil
}
@@ -130,17 +133,22 @@ func genParamChecker(param *Param) (IParamChecker, error) {
}
func newParamChecker(param *Param) (*paramChecker, error) {
ck, err := genParamChecker(param)
ck, err := genParamChecker(&SubParam{
Name: param.Name,
Position: param.Position,
MatchText: param.MatchText,
MatchMode: param.MatchMode,
})
if err != nil {
return nil, err
}
cks := make([]IParamChecker, 0, len(param.Params))
for _, p := range param.Params {
ck, err := genParamChecker(p)
c, err := genParamChecker(p)
if err != nil {
return nil, err
}
cks = append(cks, ck)
cks = append(cks, c)
}
return &paramChecker{
@@ -150,21 +158,22 @@ func newParamChecker(param *Param) (*paramChecker, error) {
}, nil
}
func (c *paramChecker) Check(logic string, header http_service.IHeaderReader, query http_service.IQueryReader, body interface{}, fn bodyCheckerFunc) bool {
success := false
func (c *paramChecker) Check(header http_service.IHeaderReader, query http_service.IQueryReader, body interface{}, fn bodyCheckerFunc) bool {
success := true
for _, ck := range c.checkers {
if ck == nil {
continue
}
ok := ck.Check(c.logic, header, query, body, fn)
ok := ck.Check(header, query, body, fn)
if !ok {
if logic == logicAnd {
if c.logic == logicAnd {
return false
}
success = false
continue
} else {
success = true
if logic == logicOr {
if c.logic == logicOr {
break
}
}
@@ -175,7 +184,7 @@ func (c *paramChecker) Check(logic string, header http_service.IHeaderReader, qu
if c.checker == nil {
return true
}
return c.checker.Check(c.logic, header, query, body, fn)
return c.checker.Check(header, query, body, fn)
}
func formChecker(body interface{}, ck *bodyChecker) error {
+10 -10
View File
@@ -59,7 +59,7 @@ func TestParamCheckLogic(t *testing.T) {
name: "And logic",
param: &Param{
Logic: logicAnd,
Params: []*Param{
Params: []*SubParam{
{
Position: positionHeader,
Name: "X-Test-Header",
@@ -85,7 +85,7 @@ func TestParamCheckLogic(t *testing.T) {
name: "Or logic",
param: &Param{
Logic: logicOr,
Params: []*Param{
Params: []*SubParam{
{
Position: positionHeader,
Name: "X-Test-Header",
@@ -111,7 +111,7 @@ func TestParamCheckLogic(t *testing.T) {
name: "And logic (fail case)",
param: &Param{
Logic: logicAnd,
Params: []*Param{
Params: []*SubParam{
{
Position: positionHeader,
Name: "X-Test-Header",
@@ -137,7 +137,7 @@ func TestParamCheckLogic(t *testing.T) {
name: "Or logic (fail case)",
param: &Param{
Logic: logicOr,
Params: []*Param{
Params: []*SubParam{
{
Position: positionHeader,
Name: "X-Test-Header",
@@ -164,7 +164,7 @@ func TestParamCheckLogic(t *testing.T) {
ck, err := newParamChecker(tt.param)
assert.NoError(t, err)
assert.NotNil(t, ck)
assert.Equal(t, tt.expected, ck.Check(tt.param.Logic, &MockHeaderReader{headers: tt.header}, &MockQueryReader{queries: tt.query}, nil, nil))
assert.Equal(t, tt.expected, ck.Check(&MockHeaderReader{headers: tt.header}, &MockQueryReader{queries: tt.query}, nil, nil))
})
}
}
@@ -206,7 +206,7 @@ func TestParamCheck(t *testing.T) {
{
name: "Body array match any",
param: &Param{
Params: []*Param{
Params: []*SubParam{
{
Position: positionBody,
Name: "search[*].val",
@@ -228,7 +228,7 @@ func TestParamCheck(t *testing.T) {
{
name: "Header match",
param: &Param{
Params: []*Param{
Params: []*SubParam{
{
Position: positionHeader,
Name: "X-Test-Header",
@@ -246,7 +246,7 @@ func TestParamCheck(t *testing.T) {
{
name: "Query match",
param: &Param{
Params: []*Param{
Params: []*SubParam{
{
Position: positionQuery,
Name: "query-param",
@@ -264,7 +264,7 @@ func TestParamCheck(t *testing.T) {
{
name: "Body array match all (fail case)",
param: &Param{
Params: []*Param{
Params: []*SubParam{
{
Position: positionBody,
Name: "search[*].val",
@@ -301,7 +301,7 @@ func TestParamCheck(t *testing.T) {
queryReader := &MockQueryReader{queries: test.query}
// 执行校验
ok := ck.Check(test.param.Logic, headerReader, queryReader, body, jsonChecker)
ok := ck.Check(headerReader, queryReader, body, jsonChecker)
// 检查结果
if ok != test.expected {
+60 -18
View File
@@ -6,40 +6,82 @@ import (
"github.com/eolinker/apinto/checker"
)
type Config Param
type Param struct {
Name string `json:"name" label:"参数名"`
Position string `json:"position" label:"参数位置" enum:"query,header,body"`
MatchText string `json:"match_text" label:"匹配文本"`
MatchMode string `json:"match_mode" label:"匹配模式" enum:"any,all"`
Logic string `json:"logic" label:"逻辑" enum:"and,or"`
Params []*Param `json:"params" label:"参数列表"`
type Config struct {
Logic string `json:"logic" label:"逻辑" enum:"and,or"`
Params []*Param `json:"params" label:"参数列表"`
}
func checkParam(conf *Param) error {
if conf.Name == "" && len(conf.Params) == 0 {
type Param struct {
Name string `json:"name" label:"参数名"`
Position string `json:"position" label:"参数位置" enum:"query,header,body"`
MatchText string `json:"match_text" label:"匹配文本"`
MatchMode string `json:"match_mode" label:"匹配模式" enum:"any,all"`
Logic string `json:"logic" label:"逻辑" enum:"and,or"`
Params []*SubParam `json:"params" label:"参数列表"`
}
func (p *Param) check() error {
if p.Name == "" && len(p.Params) == 0 {
return fmt.Errorf("name is empty")
}
switch conf.Position {
switch p.Position {
case positionQuery, positionHeader, positionBody, "":
default:
return fmt.Errorf("position is error")
}
switch conf.MatchMode {
switch p.MatchMode {
case checker.JsonArrayMatchAll, checker.JsonArrayMatchAny:
default:
conf.MatchMode = checker.JsonArrayMatchAll
p.MatchMode = checker.JsonArrayMatchAll
}
switch conf.Logic {
switch p.Logic {
case logicAnd, logicOr:
default:
conf.Logic = logicAnd
p.Logic = logicAnd
}
for _, p := range conf.Params {
if err := checkParam(p); err != nil {
for _, sub := range p.Params {
err := sub.check()
if err != nil {
return err
}
}
return nil
}
type SubParam struct {
Name string `json:"name" label:"参数名"`
Position string `json:"position" label:"参数位置" enum:"query,header,body"`
MatchText string `json:"match_text" label:"匹配文本"`
MatchMode string `json:"match_mode" label:"匹配模式" enum:"any,all"`
}
func (p *SubParam) check() error {
if p.Name == "" {
return fmt.Errorf("name is empty")
}
switch p.Position {
case positionQuery, positionHeader, positionBody:
default:
return fmt.Errorf("position is error")
}
switch p.MatchMode {
case checker.JsonArrayMatchAll, checker.JsonArrayMatchAny:
default:
p.MatchMode = checker.JsonArrayMatchAll
}
return nil
}
func checkParam(conf *Config) error {
for _, p := range conf.Params {
err := p.check()
if err != nil {
return err
}
}
if conf.Logic == "" {
conf.Logic = logicAnd
}
return nil
}
+23 -5
View File
@@ -23,7 +23,7 @@ var _ eosc.IWorker = (*executor)(nil)
type executor struct {
drivers.WorkerBase
logic string
ck IParamChecker
cks []IParamChecker
}
func (e *executor) DoFilter(ctx eocontext.EoContext, next eocontext.IChain) (err error) {
@@ -33,7 +33,8 @@ func (e *executor) DoFilter(ctx eocontext.EoContext, next eocontext.IChain) (err
var errParamCheck = "Can not find the %s param \"%s\" or the \"%s\" is illegal"
func (e *executor) DoHttpFilter(ctx http_service.IHttpContext, next eocontext.IChain) (err error) {
if e.ck != nil {
if e.cks != nil {
cks := e.cks
headerReader := ctx.Request().Header()
queryReader := ctx.Request().URI()
var body interface{}
@@ -54,8 +55,25 @@ func (e *executor) DoHttpFilter(ctx http_service.IHttpContext, next eocontext.IC
fn = jsonChecker
}
ok := e.ck.Check(e.logic, headerReader, queryReader, body, fn)
if !ok {
success := true
for _, ck := range cks {
ok := ck.Check(headerReader, queryReader, body, fn)
if !ok {
if e.logic == logicAnd {
ctx.Response().SetStatus(401, "401")
ctx.Response().SetBody([]byte("param check failed"))
return err
}
success = false
continue
} else {
success = true
if e.logic == logicOr {
break
}
}
}
if !success {
ctx.Response().SetStatus(401, "401")
ctx.Response().SetBody([]byte("param check failed"))
return err
@@ -69,7 +87,7 @@ func (e *executor) DoHttpFilter(ctx http_service.IHttpContext, next eocontext.IC
}
func (e *executor) Destroy() {
e.ck = nil
e.cks = nil
return
}
+13 -7
View File
@@ -3,6 +3,7 @@ package params_check_v2
import (
"github.com/eolinker/apinto/drivers"
"github.com/eolinker/eosc"
"github.com/eolinker/eosc/log"
)
const (
@@ -10,28 +11,33 @@ const (
)
func Register(register eosc.IExtenderDriverRegister) {
log.Debug("register params_check_v2 is ", Name)
register.RegisterExtenderDriver(Name, NewFactory())
}
func NewFactory() eosc.IExtenderDriverFactory {
return drivers.NewFactory[Config](Create)
}
func Create(id, name string, conf *Config, workers map[eosc.RequireId]eosc.IWorker) (eosc.IWorker, error) {
cfg := (*Param)(conf)
err := checkParam(cfg)
err := checkParam(conf)
if err != nil {
return nil, err
}
ck, err := newParamChecker(cfg)
if err != nil {
return nil, err
cks := make([]IParamChecker, 0, len(conf.Params))
for _, p := range conf.Params {
ck, err := newParamChecker(p)
if err != nil {
return nil, err
}
cks = append(cks, ck)
}
return &executor{
WorkerBase: drivers.Worker(id, name),
ck: ck,
logic: cfg.Logic,
cks: cks,
logic: conf.Logic,
}, nil
}
+1 -1
View File
@@ -24,7 +24,7 @@ require (
github.com/lestrrat-go/jwx v1.2.28
github.com/nacos-group/nacos-sdk-go/v2 v2.2.3
github.com/nsqio/go-nsq v1.1.0
github.com/ohler55/ojg v1.12.9
github.com/ohler55/ojg v1.25.1
github.com/pkg/sftp v1.13.4
github.com/polarismesh/polaris-go v1.1.0
github.com/redis/go-redis/v9 v9.7.0
+1 -1
View File
@@ -161,5 +161,5 @@ func (b *BodyChecker) MatchCheck(req interface{}) bool {
}
func (b *BodyChecker) Weight() int {
return int(checker.CheckTypeAll-b.Checker.CheckType()) * len(b.Checker.Value())
return int(checker.CheckTypeAll-b.Checker.CheckType()) * 50 * len(b.Checker.Value())
}
+1 -1
View File
@@ -177,7 +177,7 @@ func (as AppendMatchers) Len() int {
}
func (as AppendMatchers) Less(i, j int) bool {
return as[i].checkers.Weight() < as[j].checkers.Weight()
return as[i].checkers.Weight() > as[j].checkers.Weight()
}
func (as AppendMatchers) Swap(i, j int) {