package service import ( "reflect" "strings" "apigo.cc/gojs" "apigo.cc/gojs/goja" "github.com/ssgo/discover" "github.com/ssgo/httpclient" "github.com/ssgo/u" ) type Caller struct { client *discover.Caller } func NewCaller(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm) return vm.ToValue(gojs.MakeMap(Caller{client: discover.NewCaller(nil, args.Logger)})) } func makeResult(r *httpclient.Result, vm *goja.Runtime) goja.Value { if r.Error != nil { panic(vm.NewGoError(r.Error)) } headers := map[string]string{} for k, v := range r.Response.Header { headers[k] = v[0] } return vm.ToValue(map[string]any{ "status": r.Response.Status, "statusCode": r.Response.StatusCode, "headers": headers, "_data": r.Bytes(), "bytes": toBytes, "string": toString, "object": toObject, }) } func toBytes(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { dataValue := argsIn.This.ToObject(vm).Get("_data") if _, ok := dataValue.Export().([]byte); ok { return dataValue } return nil } func toString(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { dataValue := argsIn.This.ToObject(vm).Get("_data") if data, ok := dataValue.Export().([]byte); ok { return vm.ToValue(string(data)) } return nil } func toObject(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { dataValue := argsIn.This.ToObject(vm).Get("_data") if data, ok := dataValue.Export().([]byte); ok { obj := u.UnJsonBytes(data, nil) v := u.FinalValue(reflect.ValueOf(obj)) if v.IsValid() { return vm.ToValue(v.Interface()) } } return nil } func (cl *Caller) makeHeaderArray(in map[string]any) []string { out := make([]string, 0) if in != nil { for k, v := range in { out = append(out, k, u.String(v)) } } return out } func parseAppPath(appURL string) (string, string) { arr := strings.SplitN(appURL, "/", 2) if len(arr) == 2 { return arr[0], arr[1] } return appURL, "/" } func (cl *Caller) Get(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm).Check(1) app, path := parseAppPath(args.Str(0)) return makeResult(cl.client.Get(app, path, cl.makeHeaderArray(args.Map(1))...), vm) } func (cl *Caller) Head(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm).Check(1) app, path := parseAppPath(args.Str(0)) return makeResult(cl.client.Head(app, path, cl.makeHeaderArray(args.Map(1))...), vm) } func (cl *Caller) Post(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm).Check(2) app, path := parseAppPath(args.Str(0)) return makeResult(cl.client.Post(app, path, args.Any(1), cl.makeHeaderArray(args.Map(2))...), vm) } func (cl *Caller) Put(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm).Check(2) app, path := parseAppPath(args.Str(0)) return makeResult(cl.client.Put(app, path, args.Any(1), cl.makeHeaderArray(args.Map(2))...), vm) } func (cl *Caller) Delete(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm).Check(2) app, path := parseAppPath(args.Str(0)) return makeResult(cl.client.Delete(app, path, args.Any(1), cl.makeHeaderArray(args.Map(2))...), vm) } func (cl *Caller) Do(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value { args := gojs.MakeArgs(&argsIn, vm).Check(3) app, path := parseAppPath(args.Str(0)) if len(argsIn.Arguments) == 3 { argsIn.Arguments = append(argsIn.Arguments, vm.ToValue(nil)) } var r *httpclient.Result if cb, ok := goja.AssertFunction(argsIn.Arguments[3]); ok { r = cl.client.ManualDo(app, path, args.Str(1), args.Any(2), cl.makeHeaderArray(args.Map(4))...) buf := make([]byte, 1024) for { n, err := r.Response.Body.Read(buf) if err != nil { break } _, _ = cb(argsIn.This, vm.ToValue(u.String(buf[0:n]))) } } else { r = cl.client.Do(app, path, args.Str(1), args.Any(2), cl.makeHeaderArray(args.Map(4))...) } return makeResult(r, vm) }