/
contextualize.go
104 lines (93 loc) · 2.74 KB
/
contextualize.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package deftree
import (
"regexp"
"strings"
"github.com/pkg/errors"
)
// Assemble takes a deftree that's already had http options parsed by svcparse
// and inserted, then assembles the `HttpParameters` corresponding to each
// ServiceMethod's http annotations. After this, each `HttpBinding` will have a
// populated list of all the http parameters that that binding requires, where
// that parameter should be located, and the type of each parameter.
func Assemble(dt Deftree) error {
md := dt.(*MicroserviceDefinition)
for _, file := range md.Files {
for _, svc := range file.Services {
for _, meth := range svc.Methods {
for _, pbind := range meth.HttpBindings {
err := contextualizeBinding(meth, pbind)
if err != nil {
return errors.Wrap(err, "contextualizing http bindings failed")
}
}
}
}
}
return nil
}
func contextualizeBinding(meth *ServiceMethod, binding *MethodHttpBinding) error {
msg := meth.RequestType
// Find the verb and the path
binding.Verb, binding.Path = getVerb(binding)
params := make([]*HttpParameter, 0)
// Create the new HttpParameters
for _, field := range msg.Fields {
new_param := &HttpParameter{}
new_param.Name = field.Name
new_param.Type = field.Type.GetName()
new_param.Location = paramLocation(field, binding)
params = append(params, new_param)
}
binding.Params = params
return nil
}
// Get's the verb of binding. Currently doesn't support "custom" verbs.
func getVerb(binding *MethodHttpBinding) (verb string, path string) {
if binding.CustomHTTPPattern != nil {
for _, field := range binding.CustomHTTPPattern {
if field.Kind == "kind" {
verb = field.Value
} else if field.Kind == "path" {
path = field.Value
}
}
return verb, path
}
for _, field := range binding.Fields {
switch field.Kind {
case "get", "put", "post", "delete", "patch":
return field.Kind, field.Value
}
}
return "", ""
}
func paramLocation(field *MessageField, binding *MethodHttpBinding) string {
path_params := getPathParams(binding)
for _, path_param := range path_params {
if strings.Split(path_param, ".")[0] == field.GetName() {
return "path"
}
}
for _, optField := range binding.Fields {
if optField.Kind == "body" {
if optField.Value == "*" {
return "body"
} else if optField.Value == field.GetName() {
return "body"
}
}
}
return "query"
}
// Returns a slice of strings containing all parameters in the path
func getPathParams(binding *MethodHttpBinding) []string {
_, path := getVerb(binding)
find_params := regexp.MustCompile("{(.*?)}")
remove_braces := regexp.MustCompile("{|}")
params := find_params.FindAllString(path, -1)
rv := []string{}
for _, p := range params {
rv = append(rv, remove_braces.ReplaceAllString(p, ""))
}
return rv
}