Skip to content

Commit

Permalink
Merge 61c439a into eb2f538
Browse files Browse the repository at this point in the history
  • Loading branch information
ChuntaoLu committed Aug 14, 2018
2 parents eb2f538 + 61c439a commit 4882fa5
Show file tree
Hide file tree
Showing 30 changed files with 1,748 additions and 145 deletions.
111 changes: 82 additions & 29 deletions codegen/method.go
Expand Up @@ -1013,7 +1013,7 @@ func (ms *MethodSpec) setTypeConverters(
func getQueryMethodForType(typeSpec compile.TypeSpec) string {
var queryMethod string

switch typeSpec.(type) {
switch t := typeSpec.(type) {
case *compile.BoolSpec:
queryMethod = "GetQueryBool"
case *compile.I8Spec:
Expand All @@ -1028,6 +1028,28 @@ func getQueryMethodForType(typeSpec compile.TypeSpec) string {
queryMethod = "GetQueryFloat64"
case *compile.StringSpec:
queryMethod = "GetQueryValue"
case *compile.ListSpec:
switch t.ValueSpec.(type) {
case *compile.BoolSpec:
queryMethod = "GetQueryBoolList"
case *compile.I8Spec:
queryMethod = "GetQueryInt8List"
case *compile.I16Spec:
queryMethod = "GetQueryInt16List"
case *compile.I32Spec:
queryMethod = "GetQueryInt32List"
case *compile.I64Spec:
queryMethod = "GetQueryInt64List"
case *compile.DoubleSpec:
queryMethod = "GetQueryFloat64List"
case *compile.StringSpec:
queryMethod = "GetQueryValues"
default:
panic(fmt.Sprintf(
"Unsupported list value type (%T) %v for query string parameter",
t.ValueSpec, t.ValueSpec,
))
}
default:
panic(fmt.Sprintf(
"Unknown type (%T) %v for query string parameter",
Expand All @@ -1043,7 +1065,7 @@ func getQueryEncodeExpression(
) string {
var encodeExpression string

switch typeSpec.(type) {
switch t := typeSpec.(type) {
case *compile.BoolSpec:
encodeExpression = "strconv.FormatBool(%s)"
case *compile.I8Spec:
Expand All @@ -1058,6 +1080,28 @@ func getQueryEncodeExpression(
encodeExpression = "strconv.FormatFloat(%s, 'G', -1, 64)"
case *compile.StringSpec:
encodeExpression = "%s"
case *compile.ListSpec:
switch t.ValueSpec.(type) {
case *compile.BoolSpec:
encodeExpression = "strconv.FormatBool(%s)"
case *compile.I8Spec:
encodeExpression = "strconv.Itoa(int(%s))"
case *compile.I16Spec:
encodeExpression = "strconv.Itoa(int(%s))"
case *compile.I32Spec:
encodeExpression = "strconv.Itoa(int(%s))"
case *compile.I64Spec:
encodeExpression = "strconv.FormatInt(%s, 10)"
case *compile.DoubleSpec:
encodeExpression = "strconv.FormatFloat(%s, 'G', -1, 64)"
case *compile.StringSpec:
encodeExpression = "%s"
default:
panic(fmt.Sprintf(
"Unsupported list value type (%T) %v for query string parameter",
t.ValueSpec, t.ValueSpec,
))
}
default:
panic(fmt.Sprintf(
"Unknown type (%T) %v for query string parameter",
Expand Down Expand Up @@ -1116,35 +1160,39 @@ func (ms *MethodSpec) setWriteQueryParamStatements(

longQueryName := ms.getLongQueryName(field, thriftPrefix)
identifierName := CamelCase(longQueryName) + "Query"
_, isList := realType.(*compile.ListSpec)
if isList {
longQueryName = longQueryName + "[]"
}

if !hasQueryFields {
statements.append("queryValues := &url.Values{}")
hasQueryFields = true
}

if field.Required {
encodeExpr := getQueryEncodeExpression(
realType, "r"+longFieldName,
)

statements.appendf("%s := %s",
identifierName, encodeExpr,
)
statements.appendf("queryValues.Set(\"%s\", %s)",
longQueryName, identifierName,
)
if isList {
encodeExpr := getQueryEncodeExpression(realType, "value")
statements.appendf("for _, value := range %s {", "r"+longFieldName)
statements.appendf("\tqueryValues.Add(\"%s\", %s)", longQueryName, encodeExpr)
statements.append("}")
} else {
encodeExpr := getQueryEncodeExpression(realType, "r"+longFieldName)
statements.appendf("%s := %s", identifierName, encodeExpr)
statements.appendf("queryValues.Set(\"%s\", %s)", longQueryName, identifierName)
}
} else {
encodeExpr := getQueryEncodeExpression(
realType, "*r"+longFieldName,
)

statements.appendf("if r%s != nil {", longFieldName)
statements.appendf("\t%s := %s",
identifierName, encodeExpr,
)
statements.appendf("\tqueryValues.Set(\"%s\", %s)",
longQueryName, identifierName,
)
if isList {
encodeExpr := getQueryEncodeExpression(realType, "value")
statements.appendf("for _, value := range %s {", "r"+longFieldName)
statements.appendf("\tqueryValues.Add(\"%s\", %s)", longQueryName, encodeExpr)
statements.append("}")
} else {
encodeExpr := getQueryEncodeExpression(realType, "*r"+longFieldName)
statements.appendf("\t%s := %s", identifierName, encodeExpr)
statements.appendf("\tqueryValues.Set(\"%s\", %s)", longQueryName, identifierName)
}
statements.append("}")
}

Expand Down Expand Up @@ -1187,6 +1235,11 @@ func (ms *MethodSpec) setParseQueryParamStatements(
}
}

_, isList := realType.(*compile.ListSpec)
if isList {
longQueryName = longQueryName + "[]"
}

// If the type is a struct then we cannot really do anything
if _, ok := realType.(*compile.StructSpec); ok {
// if a field is a struct then we must do a nil check
Expand Down Expand Up @@ -1239,7 +1292,6 @@ func (ms *MethodSpec) setParseQueryParamStatements(
}

queryMethodName := getQueryMethodForType(realType)
pointerMethod := pointerMethodType(realType)

statements.appendf("%s, ok := req.%s(%q)",
identifierName, queryMethodName, longQueryName,
Expand All @@ -1250,13 +1302,14 @@ func (ms *MethodSpec) setParseQueryParamStatements(
statements.append("}")

if field.Required {
statements.appendf("requestBody%s = %s",
longFieldName, identifierName,
)
statements.appendf("requestBody%s = %s", longFieldName, identifierName)
} else {
statements.appendf("\trequestBody%s = ptr.%s(%s)",
longFieldName, pointerMethod, identifierName,
)
if isList {
statements.appendf("\trequestBody%s = %s", longFieldName, identifierName)
} else {
pointerMethod := pointerMethodType(realType)
statements.appendf("\trequestBody%s = ptr.%s(%s)", longFieldName, pointerMethod, identifierName)
}
statements.append("}")
}

Expand Down
8 changes: 7 additions & 1 deletion codegen/template_bundle/template_files.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions codegen/templates/service_mock.tmpl
Expand Up @@ -39,6 +39,7 @@ type MockService interface {
req, resp zanzibar.RWTStruct,
) (bool, map[string]string, error)
{{$mock}}() *{{$mockType}}
Server() *zanzibar.Gateway
Start()
Stop()
}
Expand Down Expand Up @@ -103,6 +104,11 @@ func MustCreateTestService(t *testing.T) MockService {
}
}

// Server returns the mock server
func (m *mockService) Server() *zanzibar.Gateway {
return m.server
}

// Start starts the mock server, panics if fails doing so
func (m *mockService) Start() {
if err := m.server.Bootstrap(); err != nil {
Expand Down
11 changes: 11 additions & 0 deletions codegen/test_data/bar.json
Expand Up @@ -320,6 +320,9 @@
"\trequestMyuuidQuery := *r.Request.AuthUUID2",
"\tqueryValues.Set(\"request.myuuid\", requestMyuuidQuery)",
"}",
"for _, value := range r.Request.Foo {",
"\tqueryValues.Add(\"request.foo[]\", value)",
"}",
"if r.Opt != nil {",
"optNameQuery := r.Opt.Name",
"queryValues.Set(\"opt.name\", optNameQuery)",
Expand Down Expand Up @@ -555,6 +558,14 @@
"\tuserUUIDQuery := *r.UserUUID",
"\tqueryValues.Set(\"userUUID\", userUUIDQuery)",
"}",
"if r.Foo != nil {",
"for _, value := range r.Foo {",
"\tqueryValues.Add(\"foo[]\", value)",
"}",
"}",
"for _, value := range r.Bar {",
"\tqueryValues.Add(\"bar[]\", strconv.Itoa(int(value)))",
"}",
"fullURL += \"?\" + queryValues.Encode()"
],
"ReqHeaderGoStatements": null,
Expand Down
11 changes: 11 additions & 0 deletions codegen/test_data/clients/bar.gogen
Expand Up @@ -499,6 +499,9 @@ func (c *barClient) ArgWithNestedQueryParams(
requestMyuuidQuery := *r.Request.AuthUUID2
queryValues.Set("request.myuuid", requestMyuuidQuery)
}
for _, value := range r.Request.Foo {
queryValues.Add("request.foo[]", value)
}
if r.Opt != nil {
optNameQuery := r.Opt.Name
queryValues.Set("opt.name", optNameQuery)
Expand Down Expand Up @@ -683,6 +686,14 @@ func (c *barClient) ArgWithQueryParams(
userUUIDQuery := *r.UserUUID
queryValues.Set("userUUID", userUUIDQuery)
}
if r.Foo != nil {
for _, value := range r.Foo {
queryValues.Add("foo[]", value)
}
}
for _, value := range r.Bar {
queryValues.Add("bar[]", strconv.Itoa(int(value)))
}
fullURL += "?" + queryValues.Encode()

err := req.WriteJSON("GET", fullURL, headers, nil)
Expand Down
Expand Up @@ -109,6 +109,16 @@ func (h *BarArgWithNestedQueryParamsHandler) HandleRequest(
requestBody.Request.UserUUID = ptr.String(requestUserUUIDQuery)
}

requestFooOk := req.CheckQueryValue("request.foo[]")
if !requestFooOk {
return
}
requestFooQuery, ok := req.GetQueryValues("request.foo[]")
if !ok {
return
}
requestBody.Request.Foo = requestFooQuery

if req.HasQueryPrefix("opt") || requestBody.Opt != nil {
if requestBody.Opt == nil {
requestBody.Opt = &endpointsBarBar.QueryParamsOptsStruct{}
Expand Down
Expand Up @@ -94,6 +94,25 @@ func (h *BarArgWithQueryParamsHandler) HandleRequest(
requestBody.UserUUID = ptr.String(userUUIDQuery)
}

fooOk := req.HasQueryValue("foo[]")
if fooOk {
fooQuery, ok := req.GetQueryValues("foo[]")
if !ok {
return
}
requestBody.Foo = fooQuery
}

barOk := req.CheckQueryValue("bar[]")
if !barOk {
return
}
barQuery, ok := req.GetQueryInt8List("bar[]")
if !ok {
return
}
requestBody.Bar = barQuery

// log endpoint request to downstream services
if ce := req.Logger.Check(zapcore.DebugLevel, "stub"); ce != nil {
zfields := []zapcore.Field{
Expand Down
3 changes: 1 addition & 2 deletions codegen/thrift.go
Expand Up @@ -208,6 +208,7 @@ func walkFieldGroupsInternal(
case *compile.I32Spec:
case *compile.I64Spec:
case *compile.EnumSpec:
case *compile.ListSpec:
case *compile.StructSpec:
bail := walkFieldGroupsInternal(
goPrefix+"."+PascalCase(field.Name),
Expand All @@ -223,8 +224,6 @@ func walkFieldGroupsInternal(
// TODO: implement
case *compile.MapSpec:
// TODO: implement
case *compile.ListSpec:
// TODO: implement
default:
panic("unknown Spec")
}
Expand Down
26 changes: 25 additions & 1 deletion docs/thrift.md
Expand Up @@ -161,7 +161,31 @@ how its serialized for the client ).
If the annotation is on a field of a struct and that struct is
a method argument, the URL query name will be prefixed with the
struct's field name plus ".".


Following types of method params are supported in query params:

- bool
- i8
- i16
- i32
- i64
- double
- string
- list of bool, i8, i16, i32, i64, double or string
- struct with fields of bool, i8, i16, i32, i64, double, string, or list of bool, i8, i16, i32, i64, double or string

If the annotation is on a field of a list and that list is
a method argument, the URL query name will be prefixed with the
struct's field name plus "[]".

If the annotation is on a field of a struct and that struct is
a method argument, the URL query name will be prefixed with the
struct's field name plus ".".

For types beyond the above supported ones, http `POST` should be
used, and the method params should go into the request body instead
of url params.

- `body.{{$fieldName}}` means that this field comes from
a different field in the body. The fieldName is absolute
from the root of the body JSON object.
Expand Down
11 changes: 11 additions & 0 deletions examples/example-gateway/build/clients/bar/bar.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 4882fa5

Please sign in to comment.