github.com/profzone/eden-framework@v1.0.10/pkg/courier/transport_http/http_route_meta.go (about) 1 package transport_http 2 3 import ( 4 "fmt" 5 "github.com/profzone/eden-framework/pkg/courier" 6 "github.com/profzone/eden-framework/pkg/courier/httpx" 7 "net/http" 8 "reflect" 9 "regexp" 10 "strings" 11 12 "github.com/fatih/color" 13 "github.com/julienschmidt/httprouter" 14 ) 15 16 type MethodDescriber interface { 17 Method() string 18 } 19 20 type PathDescriber interface { 21 Path() string 22 } 23 24 type BasePathDescriber interface { 25 BasePath() string 26 } 27 28 var pkgPathHttpx = reflect.TypeOf(httpx.MethodGet{}).PkgPath() 29 30 func NewOperatorFactoryWithRouteMeta(op courier.IOperator, last bool) *OperatorFactoryWithRouteMeta { 31 f := courier.NewOperatorFactory(op, last) 32 33 m := &OperatorFactoryWithRouteMeta{ 34 OperatorFactory: f, 35 } 36 37 m.ID = m.Type.Name() 38 39 if methodDescriber, ok := op.(MethodDescriber); ok { 40 m.Method = methodDescriber.Method() 41 } 42 43 if m.Type.Kind() == reflect.Struct { 44 structType := m.Type 45 46 for i := 0; i < structType.NumField(); i++ { 47 f := structType.Field(i) 48 if f.Anonymous && f.Type.PkgPath() == pkgPathHttpx && strings.HasPrefix(f.Name, "Method") { 49 if path, ok := f.Tag.Lookup("path"); ok { 50 vs := strings.Split(path, ",") 51 m.Path = vs[0] 52 53 if len(vs) > 0 { 54 for i := range vs { 55 switch vs[i] { 56 case "deprecated": 57 m.Deprecated = true 58 break 59 } 60 } 61 } 62 } 63 64 if basePath, ok := f.Tag.Lookup("basePath"); ok { 65 m.BasePath = basePath 66 } 67 68 if summary, ok := f.Tag.Lookup("summary"); ok { 69 m.Summary = summary 70 } 71 72 break 73 } 74 } 75 } 76 77 if basePathDescriber, ok := op.(BasePathDescriber); ok { 78 m.BasePath = basePathDescriber.BasePath() 79 } 80 81 if pathDescriber, ok := m.Operator.(PathDescriber); ok { 82 m.Path = pathDescriber.Path() 83 } 84 85 return m 86 } 87 88 type RouteMeta struct { 89 ID string 90 Method string 91 Path string 92 BasePath string 93 Summary string 94 Deprecated bool 95 } 96 97 type OperatorFactoryWithRouteMeta struct { 98 *courier.OperatorFactory 99 RouteMeta 100 } 101 102 func NewHttpRouteMeta(route *courier.Route) *HttpRouteMeta { 103 operatorFactoryWithRouteMetas := make([]*OperatorFactoryWithRouteMeta, len(route.Operators)) 104 105 for i := range route.Operators { 106 operatorFactoryWithRouteMetas[i] = NewOperatorFactoryWithRouteMeta(route.Operators[i], i == len(route.Operators)-1) 107 } 108 109 return &HttpRouteMeta{ 110 Route: route, 111 OperatorFactoryWithRouteMetas: operatorFactoryWithRouteMetas, 112 } 113 } 114 115 type HttpRouteMeta struct { 116 Route *courier.Route 117 OperatorFactoryWithRouteMetas []*OperatorFactoryWithRouteMeta 118 } 119 120 func (route *HttpRouteMeta) OperatorNames() string { 121 operatorTypeNames := make([]string, 0) 122 123 for _, opFactory := range route.OperatorFactoryWithRouteMetas { 124 if opFactory.NoOutput { 125 continue 126 } 127 128 if opFactory.IsLast { 129 operatorTypeNames = append(operatorTypeNames, color.MagentaString(opFactory.String())) 130 } else { 131 operatorTypeNames = append(operatorTypeNames, color.CyanString(opFactory.String())) 132 } 133 } 134 135 return strings.Join(operatorTypeNames, " ") 136 } 137 138 func (route *HttpRouteMeta) Key() string { 139 return reHttpRouterPath.ReplaceAllString(route.Path(), "/{$1}") + " " + route.OperatorNames() 140 } 141 142 func (route *HttpRouteMeta) String() string { 143 method := route.Method() 144 145 return methodColor(method)("%s %s", method[0:3], route.Key()) 146 } 147 148 func (route *HttpRouteMeta) Log() { 149 method := route.Method() 150 151 last := route.OperatorFactoryWithRouteMetas[len(route.OperatorFactoryWithRouteMetas)-1] 152 153 firstLine := methodColor(method)("%s %s", method[0:3], reHttpRouterPath.ReplaceAllString(route.Path(), "/{$1}")) 154 155 if last.Deprecated { 156 firstLine = firstLine + " Deprecated" 157 } 158 159 if last.Summary != "" { 160 firstLine = firstLine + " " + last.Summary 161 } 162 163 fmt.Println("[Courier] ", firstLine) 164 fmt.Println("[Courier] ", "\t", route.OperatorNames()) 165 } 166 167 var reHttpRouterPath = regexp.MustCompile("/:([^/]+)") 168 169 func methodColor(method string) func(f string, args ...interface{}) string { 170 switch method { 171 case http.MethodGet: 172 return color.BlueString 173 case http.MethodPost: 174 return color.GreenString 175 case http.MethodPut: 176 return color.YellowString 177 case http.MethodDelete: 178 return color.RedString 179 default: 180 return color.WhiteString 181 } 182 } 183 184 func (route *HttpRouteMeta) Method() string { 185 method := "" 186 for _, m := range route.OperatorFactoryWithRouteMetas { 187 if m.Method != "" { 188 method = m.Method 189 } 190 } 191 return method 192 } 193 194 func (route *HttpRouteMeta) Path() string { 195 basePath := "/" 196 p := "" 197 198 for _, m := range route.OperatorFactoryWithRouteMetas { 199 if m.BasePath != "" { 200 basePath = m.BasePath 201 } 202 203 if m.Path != "" { 204 p += m.Path 205 } 206 } 207 208 return httprouter.CleanPath(basePath + p) 209 } 210 211 func BasePath(basePath string) *MetaOperator { 212 return &MetaOperator{ 213 basePath: basePath, 214 } 215 } 216 217 func Group(path string) *MetaOperator { 218 return &MetaOperator{path: path} 219 } 220 221 type MetaOperator struct { 222 courier.EmptyOperator 223 path string 224 basePath string 225 } 226 227 func (g *MetaOperator) Path() string { 228 return g.path 229 } 230 231 func (g *MetaOperator) BasePath() string { 232 return g.basePath 233 }