Skip to content

Commit

Permalink
feat: Invoke will extract querystring from method (dapr#127)
Browse files Browse the repository at this point in the history
Co-authored-by: 李锐 <[email protected]>
  • Loading branch information
sword-jin and meicanlirui authored Dec 15, 2020
1 parent f2b03d2 commit b6b6d06
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 12 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

# IDE
.vscode
.idea

# Test binary, build with `go test -c`
*.test
Expand Down
36 changes: 28 additions & 8 deletions client/invoke.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,16 @@ func (c *GRPCClient) invokeServiceWithRequest(ctx context.Context, req *pb.Invok
return
}

func verbToHTTPExtension(verb string) *v1.HTTPExtension {
func queryAndVerbToHTTPExtension(query string, verb string) *v1.HTTPExtension {
var queryMap = map[string]string{}
for _, item := range strings.Split(query, "&") {
kv := strings.Split(item, "=")
if len(kv) == 2 {
queryMap[kv[0]] = kv[1]
}
}
if v, ok := v1.HTTPExtension_Verb_value[strings.ToUpper(verb)]; ok {
return &v1.HTTPExtension{Verb: v1.HTTPExtension_Verb(v)}
return &v1.HTTPExtension{Verb: v1.HTTPExtension_Verb(v), Querystring: queryMap}
}
return &v1.HTTPExtension{Verb: v1.HTTPExtension_NONE}
}
Expand All @@ -64,11 +71,12 @@ func (c *GRPCClient) InvokeMethod(ctx context.Context, appID, methodName, verb s
if err := hasRequiredInvokeArgs(appID, methodName, verb); err != nil {
return nil, errors.Wrap(err, "missing required parameter")
}
method, query := extractMethodAndQuery(methodName)
req := &pb.InvokeServiceRequest{
Id: appID,
Message: &v1.InvokeRequest{
Method: methodName,
HttpExtension: verbToHTTPExtension(verb),
Method: method,
HttpExtension: queryAndVerbToHTTPExtension(query, verb),
},
}
return c.invokeServiceWithRequest(ctx, req)
Expand All @@ -82,13 +90,14 @@ func (c *GRPCClient) InvokeMethodWithContent(ctx context.Context, appID, methodN
if content == nil {
return nil, errors.New("content required")
}
method, query := extractMethodAndQuery(methodName)
req := &pb.InvokeServiceRequest{
Id: appID,
Message: &v1.InvokeRequest{
Method: methodName,
Method: method,
Data: &anypb.Any{Value: content.Data},
ContentType: content.ContentType,
HttpExtension: verbToHTTPExtension(verb),
HttpExtension: queryAndVerbToHTTPExtension(query, verb),
},
}
return c.invokeServiceWithRequest(ctx, req)
Expand All @@ -111,15 +120,26 @@ func (c *GRPCClient) InvokeMethodWithCustomContent(ctx context.Context, appID, m
return nil, errors.WithMessage(err, "error serializing input struct")
}

method, query := extractMethodAndQuery(methodName)

req := &pb.InvokeServiceRequest{
Id: appID,
Message: &v1.InvokeRequest{
Method: methodName,
Method: method,
Data: &anypb.Any{Value: contentData},
ContentType: contentType,
HttpExtension: verbToHTTPExtension(verb),
HttpExtension: queryAndVerbToHTTPExtension(query, verb),
},
}

return c.invokeServiceWithRequest(ctx, req)
}

func extractMethodAndQuery(name string) (method, query string) {
splitStr := strings.SplitN(name, "?", 2)
method = splitStr[0]
if len(splitStr) == 2 {
query = splitStr[1]
}
return
}
75 changes: 71 additions & 4 deletions client/invoke_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,23 @@ func TestInvokeMethodWithContent(t *testing.T) {
assert.Nil(t, err)
assert.NotNil(t, resp)
assert.Equal(t, string(resp), data)
})

t.Run("with content, method contains querystring", func(t *testing.T) {
content := &DataContent{
ContentType: "text/plain",
Data: []byte(data),
}
resp, err := testClient.InvokeMethodWithContent(ctx, "test", "fn?foo=bar&url=http://dapr.io", "get", content)
assert.Nil(t, err)
assert.NotNil(t, resp)
assert.Equal(t, string(resp), data)
})

t.Run("without content", func(t *testing.T) {
resp, err := testClient.InvokeMethod(ctx, "test", "fn", "get")
assert.Nil(t, err)
assert.Nil(t, resp)

})

t.Run("without service ID", func(t *testing.T) {
Expand Down Expand Up @@ -87,20 +96,78 @@ func TestInvokeMethodWithContent(t *testing.T) {

func TestVerbParsing(t *testing.T) {
t.Run("valid lower case", func(t *testing.T) {
v := verbToHTTPExtension("post")
v := queryAndVerbToHTTPExtension("", "post")
assert.NotNil(t, v)
assert.Equal(t, v1.HTTPExtension_POST, v.Verb)
assert.Len(t, v.Querystring, 0)
})

t.Run("valid upper case", func(t *testing.T) {
v := verbToHTTPExtension("GET")
v := queryAndVerbToHTTPExtension("", "GET")
assert.NotNil(t, v)
assert.Equal(t, v1.HTTPExtension_GET, v.Verb)
})

t.Run("invalid verb", func(t *testing.T) {
v := verbToHTTPExtension("BAD")
v := queryAndVerbToHTTPExtension("", "BAD")
assert.NotNil(t, v)
assert.Equal(t, v1.HTTPExtension_NONE, v.Verb)
})

t.Run("valid query", func(t *testing.T) {
v := queryAndVerbToHTTPExtension("foo=bar&url=http://dapr.io", "post")
assert.NotNil(t, v)
assert.Equal(t, v1.HTTPExtension_POST, v.Verb)
assert.Len(t, v.Querystring, 2)
assert.Equal(t, "bar", v.Querystring["foo"])
assert.Equal(t, "http://dapr.io", v.Querystring["url"])
})
}

func TestExtractMethodAndQuery(t *testing.T) {
type args struct {
name string
}
tests := []struct {
name string
args args
wantMethod string
wantQuery string
}{
{
"pure uri",
args{name: "method"},
"method",
"",
},
{
"root route method",
args{name: "/"},
"/",
"",
},
{
"uri with one query",
args{name: "method?foo=bar"},
"method",
"foo=bar",
},
{
"uri with two query",
args{name: "method?foo=bar&url=http://dapr.io"},
"method",
"foo=bar&url=http://dapr.io",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotMethod, gotQuery := extractMethodAndQuery(tt.args.name)
if gotMethod != tt.wantMethod {
t.Errorf("extractMethodAndQuery() gotMethod = %v, want %v", gotMethod, tt.wantMethod)
}
if gotQuery != tt.wantQuery {
t.Errorf("extractMethodAndQuery() gotQuery = %v, want %v", gotQuery, tt.wantQuery)
}
})
}
}

0 comments on commit b6b6d06

Please sign in to comment.