Skip to content

Commit

Permalink
annotation: Add support for using single quotes in //kun:param
Browse files Browse the repository at this point in the history
  • Loading branch information
RussellLuo committed Mar 10, 2022
1 parent 12e7c19 commit 7ebd937
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 22 deletions.
2 changes: 1 addition & 1 deletion gen/http/parser/annotation/body_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func TestParseBody(t *testing.T) {
{
name: "invalid directive",
in: "user name:xx",
wantErrStr: "invalid parameter pair: name:xx",
wantErrStr: "invalid parameter option: name:xx",
},
}

Expand Down
58 changes: 41 additions & 17 deletions gen/http/parser/annotation/param.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ import (
)

var (
reKokParam = regexp.MustCompile(`^(\w+)(.*)$`)
reKunParam = regexp.MustCompile(`^(\w+)(.*)$`)

// Supported formats:
// - k1=v1
// - k2='v2'
reKunParamOption = regexp.MustCompile(`(\w+)=('[^']+'|\S+)`)
)

type Param struct {
Expand Down Expand Up @@ -50,7 +55,7 @@ func ParseParams(s string) ([]*Param, error) {
func parseParam(s string) (*Param, error) {
s = strings.TrimSpace(s)

r := reKokParam.FindStringSubmatch(s)
r := reKunParam.FindStringSubmatch(s)
if len(r) != 3 {
return nil, fmt.Errorf("invalid directive arguments: %s", s)
}
Expand Down Expand Up @@ -88,32 +93,29 @@ func parseOption(argName, s string) (*spec.Parameter, error) {
s = strings.TrimSpace(s)
p := new(spec.Parameter)

for _, part := range strings.Fields(s) {
part = strings.TrimSpace(part)
kv := strings.SplitN(part, "=", 2)
if len(kv) != 2 {
return nil, fmt.Errorf("invalid parameter pair: %s", part)
}

k, v := kv[0], kv[1]
pairs, err := parseOptionPairs(s)
if err != nil {
return nil, err
}

switch k {
for _, pair := range pairs {
switch pair.k {
case "in":
p.In = spec.Location(v)
p.In = spec.Location(pair.v)

if err := validateLocation(p.In); err != nil {
return nil, err
}
case "name":
p.Name = v
p.Name = pair.v
case "required":
p.Required = v == "true"
p.Required = pair.v == "true"
case "type":
p.Type = v
p.Type = pair.v
case "descr":
p.Description = v
p.Description = pair.v
default:
return nil, fmt.Errorf("invalid directive argument: %s", part)
return nil, fmt.Errorf("invalid parameter option: %s=%s", pair.k, pair.v)
}
}

Expand All @@ -134,6 +136,28 @@ func parseOption(argName, s string) (*spec.Parameter, error) {
return p, nil
}

type optionPair struct{ k, v string }

func parseOptionPairs(s string) ([]optionPair, error) {
// NOTE: Instead of using ReplaceAllString and then FindAllStringSubmatch,
// a more performant alternative solution may be to use ReplaceAllStringFunc once.

unmatched := strings.TrimSpace(reKunParamOption.ReplaceAllString(s, ""))
if unmatched != "" {
return nil, fmt.Errorf("invalid parameter option: %s", unmatched)
}

var pairs []optionPair
result := reKunParamOption.FindAllStringSubmatch(s, -1)
for _, r := range result {
pairs = append(pairs, optionPair{
k: r[1],
v: strings.Trim(strings.TrimSpace(r[2]), "'"),
})
}
return pairs, nil
}

func validateLocation(in spec.Location) error {
if in != spec.InPath && in != spec.InQuery && in != spec.InHeader &&
/*in != InCookie &&*/ in != spec.InRequest {
Expand Down
13 changes: 9 additions & 4 deletions gen/http/parser/annotation/param_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ func TestParseParams(t *testing.T) {
}{
{
name: "one binding one sub-parameter",
in: "name in=header name=X-User-Name required=true type=string descr=user-name",
in: "name in=header name=X-User-Name required=true type=string descr='user name'",
wantOut: []*annotation.Param{
{
ArgName: "name",
Expand All @@ -27,7 +27,7 @@ func TestParseParams(t *testing.T) {
Name: "X-User-Name",
Required: true,
Type: "string",
Description: "user-name",
Description: "user name",
},
},
},
Expand Down Expand Up @@ -107,15 +107,20 @@ func TestParseParams(t *testing.T) {
},
},
{
name: "invalid parameter pair",
name: "invalid parameter option",
in: "name x:y",
wantErrStr: "invalid parameter pair: x:y",
wantErrStr: "invalid parameter option: x:y",
},
{
name: "invalid location",
in: "name in=xxx",
wantErrStr: `invalid location value: xxx (must be "path", "query", "header" or "request")`,
},
{
name: "invalid parameter option key",
in: "name xxx=yyy",
wantErrStr: "invalid parameter option: xxx=yyy",
},
}

for _, tt := range tests {
Expand Down

0 comments on commit 7ebd937

Please sign in to comment.