gitee.com/liuxuezhan/go-micro-v1.18.0@v1.0.0/api/api.go (about) 1 package api 2 3 import ( 4 "errors" 5 "regexp" 6 "strings" 7 8 "gitee.com/liuxuezhan/go-micro-v1.18.0/registry" 9 "gitee.com/liuxuezhan/go-micro-v1.18.0/server" 10 ) 11 12 // Endpoint is a mapping between an RPC method and HTTP endpoint 13 type Endpoint struct { 14 // RPC Method e.g. Greeter.Hello 15 Name string 16 // Description e.g what's this endpoint for 17 Description string 18 // API Handler e.g rpc, proxy 19 Handler string 20 // HTTP Host e.g example.com 21 Host []string 22 // HTTP Methods e.g GET, POST 23 Method []string 24 // HTTP Path e.g /greeter. Expect POSIX regex 25 Path []string 26 } 27 28 // Service represents an API service 29 type Service struct { 30 // Name of service 31 Name string 32 // The endpoint for this service 33 Endpoint *Endpoint 34 // Versions of this service 35 Services []*registry.Service 36 } 37 38 func strip(s string) string { 39 return strings.TrimSpace(s) 40 } 41 42 func slice(s string) []string { 43 var sl []string 44 45 for _, p := range strings.Split(s, ",") { 46 if str := strip(p); len(str) > 0 { 47 sl = append(sl, strip(p)) 48 } 49 } 50 51 return sl 52 } 53 54 // Encode encodes an endpoint to endpoint metadata 55 func Encode(e *Endpoint) map[string]string { 56 if e == nil { 57 return nil 58 } 59 60 return map[string]string{ 61 "endpoint": e.Name, 62 "description": e.Description, 63 "method": strings.Join(e.Method, ","), 64 "path": strings.Join(e.Path, ","), 65 "host": strings.Join(e.Host, ","), 66 "handler": e.Handler, 67 } 68 } 69 70 // Decode decodes endpoint metadata into an endpoint 71 func Decode(e map[string]string) *Endpoint { 72 if e == nil { 73 return nil 74 } 75 76 return &Endpoint{ 77 Name: e["endpoint"], 78 Description: e["description"], 79 Method: slice(e["method"]), 80 Path: slice(e["path"]), 81 Host: slice(e["host"]), 82 Handler: e["handler"], 83 } 84 } 85 86 // Validate validates an endpoint to guarantee it won't blow up when being served 87 func Validate(e *Endpoint) error { 88 if e == nil { 89 return errors.New("endpoint is nil") 90 } 91 92 if len(e.Name) == 0 { 93 return errors.New("name required") 94 } 95 96 for _, p := range e.Path { 97 _, err := regexp.CompilePOSIX(p) 98 if err != nil { 99 return err 100 } 101 } 102 103 if len(e.Handler) == 0 { 104 return errors.New("invalid handler") 105 } 106 107 return nil 108 } 109 110 /* 111 Design ideas 112 113 // Gateway is an api gateway interface 114 type Gateway interface { 115 // Register a http handler 116 Handle(pattern string, http.Handler) 117 // Register a route 118 RegisterRoute(r Route) 119 // Init initialises the command line. 120 // It also parses further options. 121 Init(...Option) error 122 // Run the gateway 123 Run() error 124 } 125 126 // NewGateway returns a new api gateway 127 func NewGateway() Gateway { 128 return newGateway() 129 } 130 */ 131 132 // WithEndpoint returns a server.HandlerOption with endpoint metadata set 133 // 134 // Usage: 135 // 136 // proto.RegisterHandler(service.Server(), new(Handler), api.WithEndpoint( 137 // &api.Endpoint{ 138 // Name: "Greeter.Hello", 139 // Path: []string{"/greeter"}, 140 // }, 141 // )) 142 func WithEndpoint(e *Endpoint) server.HandlerOption { 143 return server.EndpointMetadata(e.Name, Encode(e)) 144 }