github.com/nyan233/littlerpc@v0.4.6-0.20230316182519-0c8d5c48abaf/cmd/lrpcurl/rpcurl.go (about) 1 package main 2 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "github.com/nyan233/littlerpc/cmd/lrpcurl/proxy" 8 "github.com/nyan233/littlerpc/core/client" 9 "github.com/nyan233/littlerpc/core/common/logger" 10 "github.com/nyan233/littlerpc/core/server" 11 "github.com/nyan233/littlerpc/core/utils/convert" 12 flag "github.com/spf13/pflag" 13 "io" 14 "log" 15 "os" 16 "os/signal" 17 "strings" 18 "syscall" 19 "unsafe" 20 ) 21 22 type Caller interface { 23 RawCall(service string, opts []client.CallOption, args ...interface{}) (reps []interface{}, err error) 24 } 25 26 type OutType string 27 28 const ( 29 FormatJson OutType = "format_json" 30 Json OutType = "json" 31 Text OutType = "text" 32 ) 33 34 const ( 35 GetAllSupportOption = "get_all_support_option" 36 GetAllInstance = "get_all_instance" 37 GetAllCodec = "get_all_codec" 38 GetAllPacker = "get_all_packer" 39 GetMethodTable = "get_method_table" 40 GetArgumentType = "get_argument_type" 41 CallFunc = "call_func" 42 ) 43 44 var ( 45 allSupportOption = []string{ 46 GetAllCodec, GetAllPacker, GetAllInstance, GetMethodTable, GetArgumentType, CallFunc, 47 } 48 ) 49 50 var ( 51 serverAddr = flag.StringP("address", "a", "127.0.0.1:9090", "服务器地址,Example: 127.0.0.1:9090") 52 source = flag.StringP("source", "i", server.ReflectionSource, "资源的名称,注册方法时指定的实例名称") 53 option = flag.StringP("option", "o", "get_all_instance", "操作, get_all_support_option -> 获取所有支持的操作了解更多") 54 service = flag.StringP("service", "s", "Hello.Hello", "调用的目标: InstanceName.MethodName") 55 outType = flag.StringP("out_type", "t", string(FormatJson), "输出的信息的格式(format_json/json/text)") 56 call = flag.StringP("call", "c", "null", "调用传递的参数(不包括context/stream): [100,\"hh\"]") 57 ) 58 59 func main() { 60 flag.Parse() 61 logger.SetOpenLogger(false) 62 c := dial() 63 defer c.Close() 64 ctx, cancel := context.WithCancel(context.Background()) 65 channel := make(chan os.Signal) 66 signal.Notify(channel, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM) 67 go func() { 68 select { 69 case <-channel: 70 cancel() 71 } 72 }() 73 parserOption(ctx, proxy.NewLittleRpcReflection(c), c) 74 } 75 76 func parserOption(ctx context.Context, proxy proxy.LittleRpcReflectionProxy, caller Caller) { 77 switch *option { 78 case GetAllSupportOption: 79 getAllSupportOption(OutType(*outType), os.Stdout) 80 case GetAllCodec: 81 getAllCodec(ctx, proxy, OutType(*outType), os.Stdout) 82 case GetAllPacker: 83 getAllPacker(ctx, proxy, OutType(*outType), os.Stdout) 84 case GetAllInstance: 85 getAllInstance(ctx, proxy, OutType(*outType), os.Stdout) 86 case GetArgumentType: 87 getArgType(ctx, proxy, *service, OutType(*outType), os.Stdout) 88 case GetMethodTable: 89 getMethodTable(ctx, proxy, *source, OutType(*outType), os.Stdout) 90 case CallFunc: 91 var rawArgs []json.RawMessage 92 err := json.Unmarshal(convert.StringToBytes(*call), &rawArgs) 93 if err != nil { 94 log.Fatalln(err) 95 } 96 callFunc(ctx, caller, *service, *(*[][]byte)(unsafe.Pointer(&rawArgs)), OutType(*outType), os.Stdout) 97 default: 98 log.Fatalln("no implement option") 99 } 100 } 101 102 func dial() *client.Client { 103 c, err := client.New( 104 client.WithCustomLogger(logger.NilLogger{}), 105 client.WithNoMuxWriter(), 106 client.WithMuxConnection(false), 107 client.WithProtocol("std_tcp"), 108 client.WithStackTrace(), 109 client.WithAddress(*serverAddr), 110 ) 111 *call = strings.TrimPrefix(*call, "\xef\xbb\xbf") 112 if err != nil { 113 panic(err) 114 } 115 return c 116 } 117 118 func getAllSupportOption(ot OutType, w io.Writer) { 119 switch ot { 120 case Text: 121 for _, option := range allSupportOption { 122 _, _ = fmt.Fprintln(w, option) 123 } 124 default: 125 anyOutFromJson(allSupportOption, ot, w) 126 } 127 } 128 129 func getAllInstance(ctx context.Context, proxy proxy.LittleRpcReflectionProxy, ot OutType, w io.Writer) { 130 instances, err := proxy.AllInstance(ctx) 131 if err != nil { 132 log.Fatalln(err) 133 } 134 switch ot { 135 case Text: 136 for k, v := range instances { 137 _, _ = fmt.Fprintf(w, "%s --> %s\n", k, v) 138 } 139 default: 140 anyOutFromJson(instances, ot, w) 141 } 142 } 143 144 func getArgType(ctx context.Context, proxy proxy.LittleRpcReflectionProxy, service string, ot OutType, w io.Writer) { 145 argType, err := proxy.MethodArgumentType(ctx, service) 146 if err != nil { 147 log.Fatalln(err) 148 } 149 switch ot { 150 case Text: 151 if argType == nil || len(argType) == 0 { 152 return 153 } 154 for _, v := range argType { 155 anyOutFromJson(v, Json, w) 156 } 157 default: 158 anyOutFromJson(argType, ot, w) 159 } 160 } 161 162 func getMethodTable(ctx context.Context, proxy proxy.LittleRpcReflectionProxy, sourceName string, ot OutType, w io.Writer) { 163 tab, err := proxy.MethodTable(ctx, sourceName) 164 if err != nil { 165 log.Fatalln(err) 166 } 167 if tab == nil { 168 return 169 } 170 switch ot { 171 case Text: 172 break 173 default: 174 anyOutFromJson(tab, ot, w) 175 } 176 } 177 178 func getAllPacker(ctx context.Context, proxy proxy.LittleRpcReflectionProxy, ot OutType, w io.Writer) { 179 packers, err := proxy.AllPacker(ctx) 180 if err != nil { 181 log.Fatalln(err) 182 } 183 switch ot { 184 case Text: 185 if packers == nil { 186 return 187 } 188 for _, packer := range packers { 189 _, _ = fmt.Fprintln(w, packer) 190 } 191 default: 192 anyOutFromJson(packers, ot, w) 193 } 194 } 195 196 func getAllCodec(ctx context.Context, proxy proxy.LittleRpcReflectionProxy, ot OutType, w io.Writer) { 197 codecs, err := proxy.AllCodec(ctx) 198 if err != nil { 199 log.Fatalln(err) 200 } 201 switch ot { 202 case Text: 203 if codecs == nil { 204 return 205 } 206 for _, codec := range codecs { 207 _, _ = fmt.Fprintln(w, codec) 208 } 209 default: 210 anyOutFromJson(codecs, ot, w) 211 } 212 } 213 214 func anyOutFromJson(data any, ot OutType, w io.Writer) { 215 switch ot { 216 case FormatJson: 217 bytes, err := json.MarshalIndent(data, "", "\t") 218 if err != nil { 219 log.Fatalln(err) 220 } 221 _, _ = fmt.Fprintln(w, string(bytes)) 222 case Json: 223 bytes, err := json.Marshal(data) 224 if err != nil { 225 log.Fatalln(err) 226 } 227 _, _ = fmt.Fprintln(w, string(bytes)) 228 default: 229 log.Fatalln("invalid output format") 230 } 231 } 232 233 func callFunc(ctx context.Context, c Caller, service string, argsBytes [][]byte, ot OutType, w io.Writer) { 234 args := make([]interface{}, len(argsBytes)+1) 235 args[0] = ctx 236 for k, rawArg := range argsBytes { 237 err := json.Unmarshal(rawArg, &args[k+1]) 238 if err != nil { 239 log.Fatalln(err) 240 } 241 } 242 reps, err := c.RawCall(service, nil, args...) 243 reps = append(reps, err) 244 switch ot { 245 case Text: 246 for _, rep := range reps { 247 bytes, err := json.Marshal(rep) 248 if err != nil { 249 log.Fatalln(err) 250 } 251 _, _ = fmt.Fprintln(w, string(bytes)) 252 } 253 default: 254 anyOutFromJson(reps, ot, w) 255 } 256 }