2024-10-15 10:45:04 +08:00
|
|
|
package http
|
|
|
|
|
|
|
|
import (
|
|
|
|
_ "embed"
|
|
|
|
"net/http"
|
|
|
|
"reflect"
|
|
|
|
"strings"
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"apigo.cc/gojs"
|
|
|
|
"apigo.cc/gojs/goja"
|
|
|
|
"github.com/gorilla/websocket"
|
|
|
|
"github.com/ssgo/httpclient"
|
|
|
|
"github.com/ssgo/log"
|
|
|
|
"github.com/ssgo/u"
|
|
|
|
)
|
|
|
|
|
|
|
|
//go:embed http.ts
|
|
|
|
var httpTS string
|
|
|
|
|
|
|
|
type Http struct {
|
|
|
|
client *httpclient.ClientPool
|
|
|
|
baseURL string
|
|
|
|
globalHeaders map[string]string
|
|
|
|
}
|
|
|
|
|
|
|
|
var defaultHttp = &Http{
|
|
|
|
client: httpclient.GetClient(60000 * time.Millisecond),
|
|
|
|
globalHeaders: make(map[string]string),
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO ws
|
|
|
|
func init() {
|
|
|
|
obj := map[string]any{
|
|
|
|
"new": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
|
|
|
return newClient("HTTP", argsIn, vm)
|
|
|
|
},
|
|
|
|
"newH2C": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
|
|
|
return newClient("H2C", argsIn, vm)
|
|
|
|
},
|
|
|
|
"get": defaultHttp.Get,
|
|
|
|
"head": defaultHttp.Head,
|
|
|
|
"post": defaultHttp.Post,
|
|
|
|
"put": defaultHttp.Put,
|
|
|
|
"delete": defaultHttp.Delete,
|
|
|
|
"do": defaultHttp.Do,
|
|
|
|
"upload": defaultHttp.Upload,
|
|
|
|
"download": defaultHttp.Download,
|
|
|
|
"connect": defaultHttp.Connect,
|
|
|
|
}
|
|
|
|
|
|
|
|
gojs.Register("apigo.cc/gojs/http", gojs.Module{
|
|
|
|
Object: obj,
|
|
|
|
TsCode: httpTS,
|
|
|
|
Desc: "",
|
|
|
|
Example: "",
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func newClient(portal string, argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
|
|
|
args := gojs.MakeArgs(&argsIn, vm).Check(0)
|
|
|
|
opt := args.Obj(0)
|
|
|
|
timeout := 60000 * time.Millisecond
|
|
|
|
if opt != nil {
|
|
|
|
timeout = time.Duration(opt.Int64("timeout")) * time.Millisecond
|
|
|
|
}
|
|
|
|
var client *httpclient.ClientPool
|
|
|
|
if portal == "H2C" {
|
|
|
|
client = httpclient.GetClientH2C(timeout)
|
|
|
|
} else {
|
|
|
|
client = httpclient.GetClient(timeout)
|
|
|
|
}
|
|
|
|
cli := &Http{
|
|
|
|
client: client,
|
|
|
|
globalHeaders: make(map[string]string),
|
|
|
|
}
|
|
|
|
setConfig(cli, opt)
|
|
|
|
return vm.ToValue(gojs.MakeMap(cli))
|
|
|
|
}
|
|
|
|
|
|
|
|
func setConfig(cli *Http, opt *gojs.Obj) {
|
|
|
|
if opt != nil {
|
|
|
|
if globalHeaders := opt.Map("globalHeaders"); globalHeaders != nil {
|
|
|
|
for k, v := range globalHeaders {
|
|
|
|
cli.globalHeaders[k] = u.String(v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if baseURL := opt.Str("baseURL"); baseURL != "" {
|
|
|
|
cli.baseURL = baseURL
|
|
|
|
}
|
|
|
|
if downloadPartSize := opt.Int64("downloadPartSize"); downloadPartSize != 0 {
|
|
|
|
cli.client.DownloadPartSize = downloadPartSize
|
|
|
|
}
|
|
|
|
if redirect := opt.Bool("redirect"); redirect {
|
|
|
|
cli.client.EnableRedirect()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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))
|
2024-10-16 11:47:38 +08:00
|
|
|
if v.IsValid() {
|
|
|
|
return vm.ToValue(v.Interface())
|
|
|
|
}
|
2024-10-15 10:45:04 +08:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (hc *Http) makeURL(url string) string {
|
|
|
|
if !strings.Contains(url, "://") && hc.baseURL != "" {
|
|
|
|
if strings.HasSuffix(hc.baseURL, "/") && strings.HasPrefix(url, "/") {
|
|
|
|
return hc.baseURL + url[1:]
|
|
|
|
} else if !strings.HasSuffix(hc.baseURL, "/") && !strings.HasPrefix(url, "/") {
|
|
|
|
return hc.baseURL + "/" + url
|
|
|
|
}
|
|
|
|
return hc.baseURL + url
|
|
|
|
}
|
|
|
|
return url
|
|
|
|
}
|
|
|
|
|
|
|
|
func (hc *Http) makeHeaderArray(in map[string]any) []string {
|
|
|
|
out := make([]string, 0)
|
|
|
|
if hc.globalHeaders != nil {
|
|
|
|
for k, v := range hc.globalHeaders {
|
|
|
|
out = append(out, k, v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if in != nil {
|
|
|
|
for k, v := range in {
|
|
|
|
out = append(out, k, u.String(v))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return out
|
|
|
|
}
|
|
|
|
|
|
|
|
func (hc *Http) Get(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
|
|
|
args := gojs.MakeArgs(&argsIn, vm).Check(1)
|
|
|
|
return makeResult(hc.client.Get(hc.makeURL(args.Str(0)), hc.makeHeaderArray(args.Map(1))...), vm)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (hc *Http) Head(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
|
|
|
args := gojs.MakeArgs(&argsIn, vm).Check(1)
|
|
|
|
return makeResult(hc.client.Head(hc.makeURL(args.Str(0)), hc.makeHeaderArray(args.Map(1))...), vm)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (hc *Http) Post(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
|
|
|
args := gojs.MakeArgs(&argsIn, vm).Check(2)
|
|
|
|
return makeResult(hc.client.Post(hc.makeURL(args.Str(0)), args.Any(1), hc.makeHeaderArray(args.Map(2))...), vm)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (hc *Http) Put(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
|
|
|
args := gojs.MakeArgs(&argsIn, vm).Check(2)
|
|
|
|
return makeResult(hc.client.Put(hc.makeURL(args.Str(0)), args.Any(1), hc.makeHeaderArray(args.Map(2))...), vm)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (hc *Http) Delete(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
|
|
|
args := gojs.MakeArgs(&argsIn, vm).Check(2)
|
|
|
|
return makeResult(hc.client.Delete(hc.makeURL(args.Str(0)), args.Any(1), hc.makeHeaderArray(args.Map(2))...), vm)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (hc *Http) Do(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
|
|
|
args := gojs.MakeArgs(&argsIn, vm).Check(3)
|
|
|
|
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 = hc.client.ManualDo(hc.makeURL(args.Str(0)), args.Str(1), args.Any(2), hc.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 = hc.client.Do(hc.makeURL(args.Str(0)), args.Str(1), args.Any(2), hc.makeHeaderArray(args.Map(4))...)
|
|
|
|
}
|
|
|
|
return makeResult(r, vm)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (hc *Http) Upload(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
|
|
|
args := gojs.MakeArgs(&argsIn, vm).Check(2)
|
|
|
|
postData := map[string]string{}
|
|
|
|
postFiles := map[string]any{}
|
|
|
|
u.Convert(args.Any(1), &postData)
|
|
|
|
if len(argsIn.Arguments) > 2 {
|
|
|
|
u.Convert(args.Any(2), &postFiles)
|
|
|
|
}
|
|
|
|
r, _ := hc.client.MPost(hc.makeURL(args.Str(0)), postData, postFiles, hc.makeHeaderArray(args.Map(3))...)
|
|
|
|
return makeResult(r, vm)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (hc *Http) Download(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
|
|
|
args := gojs.MakeArgs(&argsIn, vm).Check(2)
|
|
|
|
var r *httpclient.Result
|
|
|
|
var callback goja.Callable
|
|
|
|
if len(argsIn.Arguments) > 2 {
|
|
|
|
if cb, ok := goja.AssertFunction(argsIn.Arguments[2]); ok {
|
|
|
|
callback = cb
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if callback != nil {
|
|
|
|
r, _ = hc.client.Download(hc.makeURL(args.Str(0)), args.Str(1), func(start, end int64, ok bool, finished, total int64) {
|
|
|
|
_, _ = callback(argsIn.This, vm.ToValue(finished), vm.ToValue(total))
|
|
|
|
}, hc.makeHeaderArray(args.Map(3))...)
|
|
|
|
} else {
|
|
|
|
r, _ = hc.client.Download(hc.makeURL(args.Str(0)), args.Str(1), nil, hc.makeHeaderArray(args.Map(3))...)
|
|
|
|
}
|
|
|
|
return makeResult(r, vm)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (hc *Http) Connect(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
|
|
|
args := gojs.MakeArgs(&argsIn, vm).Check(1)
|
|
|
|
url := hc.makeURL(args.Str(0))
|
|
|
|
if strings.HasPrefix(url, "http") {
|
|
|
|
url = strings.Replace(url, "http", "ws", 1)
|
|
|
|
}
|
|
|
|
|
|
|
|
ws := &WS{url: url, this: args.This, running: false, pingStopChan: make(chan bool, 1), closeChan: make(chan bool, 1), logger: args.Logger, headers: make(map[string]string)}
|
|
|
|
|
|
|
|
for k, v := range hc.globalHeaders {
|
|
|
|
ws.headers[k] = v
|
|
|
|
}
|
|
|
|
if opt := args.Obj(1); opt != nil {
|
|
|
|
if headers := opt.Map("headers"); headers != nil {
|
|
|
|
for k, v := range headers {
|
|
|
|
ws.headers[k] = u.String(v)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ws.compress = opt.Bool("compress")
|
|
|
|
ws.onOpen = opt.Func("onOpen")
|
|
|
|
ws.onClose = opt.Func("onClose")
|
|
|
|
ws.onError = opt.Func("onError")
|
|
|
|
// ws.onPing = opt.Func("onPing")
|
|
|
|
// ws.onPong = opt.Func("onPong")
|
|
|
|
ws.onMessage = opt.Func("onMessage")
|
|
|
|
ws.onJSONMessage = opt.Func("onJSONMessage")
|
|
|
|
ws.pingInterval = opt.Int64("pingInterval")
|
|
|
|
ws.reconnectInterval = opt.Int64("reconnectInterval")
|
|
|
|
if ws.reconnectInterval == 0 && (ws.onMessage != nil || ws.onJSONMessage != nil) {
|
|
|
|
ws.reconnectInterval = 1000
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// fmt.Println(u.BMagenta("WS"), "start")
|
|
|
|
if err := ws.connect(vm); err == nil {
|
|
|
|
if ws.pingInterval > 0 {
|
|
|
|
// fmt.Println(u.BMagenta("WS"), "start ping")
|
|
|
|
go func() {
|
|
|
|
// ws.sleep(time.Duration(ws.pingInterval) * time.Millisecond)
|
|
|
|
for {
|
|
|
|
if ws.conn != nil {
|
|
|
|
// fmt.Println(u.BMagenta("WS"), "ping")
|
|
|
|
ws.writeLock.Lock()
|
|
|
|
ws.conn.WriteMessage(websocket.PingMessage, []byte{'P'})
|
|
|
|
ws.writeLock.Unlock()
|
|
|
|
}
|
|
|
|
if !ws.running {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
ws.sleep(time.Duration(ws.pingInterval) * time.Millisecond)
|
|
|
|
if !ws.running {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// fmt.Println(u.BMagenta("WS"), "stop ping")
|
|
|
|
ws.pingStopChan <- true
|
|
|
|
}()
|
|
|
|
} else {
|
|
|
|
ws.pingStopChan <- true
|
|
|
|
}
|
|
|
|
|
|
|
|
if ws.onMessage != nil || ws.onJSONMessage != nil {
|
|
|
|
// fmt.Println(u.BMagenta("WS"), "start onMessage")
|
|
|
|
go func() {
|
|
|
|
for {
|
|
|
|
for {
|
|
|
|
if ws.conn != nil {
|
|
|
|
if ws.onJSONMessage != nil {
|
|
|
|
var obj interface{}
|
|
|
|
err := ws.conn.ReadJSON(&obj)
|
|
|
|
if err != nil {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
_, _ = ws.onJSONMessage(ws.this, vm.ToValue(obj))
|
|
|
|
} else {
|
|
|
|
typ, buf, err := ws.conn.ReadMessage()
|
|
|
|
if err != nil {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
if typ == websocket.TextMessage {
|
|
|
|
_, _ = ws.onMessage(ws.this, vm.ToValue(string(buf)))
|
|
|
|
} else {
|
|
|
|
_, _ = ws.onMessage(ws.this, vm.ToValue(buf))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// fmt.Println(u.BMagenta("WS"), "stop onMessage")
|
|
|
|
// 未结束的连接自动重连
|
|
|
|
if !ws.running {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
ws.sleep(time.Duration(ws.reconnectInterval) * time.Millisecond)
|
|
|
|
if !ws.running {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
// fmt.Println(u.BMagenta("WS"), "reconnect")
|
|
|
|
ws.connect(vm)
|
|
|
|
}
|
|
|
|
// fmt.Println(u.BMagenta("WS"), "stop onMessage2")
|
|
|
|
ws.closeChan <- true
|
|
|
|
}()
|
|
|
|
} else {
|
|
|
|
ws.closeChan <- true
|
|
|
|
}
|
|
|
|
return vm.ToValue(gojs.MakeMap(ws))
|
|
|
|
} else {
|
|
|
|
panic(vm.NewGoError(err))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type WS struct {
|
|
|
|
conn *websocket.Conn
|
|
|
|
running bool
|
|
|
|
closed bool
|
|
|
|
closeChan chan bool
|
|
|
|
pingStopChan chan bool
|
|
|
|
logger *log.Logger
|
|
|
|
this goja.Value
|
|
|
|
writeLock sync.Mutex
|
|
|
|
url string
|
|
|
|
headers map[string]string
|
|
|
|
compress bool
|
|
|
|
onOpen goja.Callable
|
|
|
|
onClose goja.Callable
|
|
|
|
onError goja.Callable
|
|
|
|
// onPing goja.Callable
|
|
|
|
// onPong goja.Callable
|
|
|
|
onMessage goja.Callable
|
|
|
|
onJSONMessage goja.Callable
|
|
|
|
pingInterval int64
|
|
|
|
reconnectInterval int64
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ws *WS) sleep(interval time.Duration) {
|
|
|
|
if interval < time.Second {
|
|
|
|
time.Sleep(interval)
|
|
|
|
} else {
|
|
|
|
for {
|
|
|
|
time.Sleep(time.Second)
|
|
|
|
interval -= time.Second
|
|
|
|
if !ws.running || interval <= 0 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ws *WS) error(err goja.Value) {
|
|
|
|
if ws.onError != nil {
|
|
|
|
ws.onError(ws.this, err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ws *WS) connect(vm *goja.Runtime) error {
|
|
|
|
reqHeader := http.Header{}
|
|
|
|
for k, v := range ws.headers {
|
|
|
|
reqHeader.Set(k, v)
|
|
|
|
}
|
|
|
|
|
|
|
|
conn, _, err := websocket.DefaultDialer.Dial(ws.url, reqHeader)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
ws.conn = conn
|
|
|
|
if ws.reconnectInterval > 0 || ws.pingInterval > 0 {
|
|
|
|
ws.running = true
|
|
|
|
}
|
|
|
|
ws.closed = false
|
|
|
|
if ws.compress {
|
|
|
|
conn.EnableWriteCompression(true)
|
|
|
|
}
|
|
|
|
// if ws.onPing != nil {
|
|
|
|
// conn.SetPingHandler(func(appData string) error {
|
|
|
|
// fmt.Println(u.BMagenta("WS"), "onPing")
|
|
|
|
// _, err := ws.onPing(ws.this, vm.ToValue(appData))
|
|
|
|
// return err
|
|
|
|
// })
|
|
|
|
// return err
|
|
|
|
// }
|
|
|
|
// if ws.onPong != nil {
|
|
|
|
// conn.SetPongHandler(func(appData string) error {
|
|
|
|
// fmt.Println(u.BMagenta("WS"), "onPong")
|
|
|
|
// _, err := ws.onPong(ws.this, vm.ToValue(appData))
|
|
|
|
// return err
|
|
|
|
// })
|
|
|
|
// return err
|
|
|
|
// }
|
|
|
|
conn.SetCloseHandler(func(code int, text string) error {
|
|
|
|
// fmt.Println(u.BMagenta("WS"), "onClose")
|
|
|
|
if ws.onClose != nil {
|
|
|
|
_, err := ws.onClose(ws.this, vm.ToValue(code), vm.ToValue(text))
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// 关闭旧连接和接收器
|
|
|
|
if !ws.closed {
|
|
|
|
ws.conn.Close()
|
|
|
|
ws.closed = true
|
|
|
|
}
|
|
|
|
|
|
|
|
// 未结束的连接自动重连
|
|
|
|
if ws.running {
|
|
|
|
time.Sleep(time.Duration(ws.reconnectInterval) * time.Millisecond)
|
|
|
|
// fmt.Println(u.BMagenta("WS"), "reconnect")
|
|
|
|
return ws.connect(vm)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ws *WS) Read(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
|
|
|
typ, buf, err := ws.conn.ReadMessage()
|
|
|
|
if err != nil {
|
|
|
|
panic(vm.NewGoError(err))
|
|
|
|
}
|
|
|
|
if typ == websocket.TextMessage {
|
|
|
|
return vm.ToValue(string(buf))
|
|
|
|
} else {
|
|
|
|
return vm.ToValue(buf)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ws *WS) ReadJSON(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
|
|
|
var obj interface{}
|
|
|
|
err := ws.conn.ReadJSON(&obj)
|
|
|
|
if err != nil {
|
|
|
|
panic(vm.NewGoError(err))
|
|
|
|
}
|
|
|
|
return vm.ToValue(obj)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ws *WS) Write(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
|
|
|
args := gojs.MakeArgs(&argsIn, vm).Check(1)
|
|
|
|
var err error
|
|
|
|
ws.writeLock.Lock()
|
|
|
|
if args.Arguments[0].ExportType().Kind() == reflect.String {
|
|
|
|
err = ws.conn.WriteMessage(websocket.TextMessage, args.Bytes(0))
|
|
|
|
} else {
|
|
|
|
err = ws.conn.WriteMessage(websocket.BinaryMessage, args.Bytes(0))
|
|
|
|
}
|
|
|
|
ws.writeLock.Unlock()
|
|
|
|
if err != nil {
|
|
|
|
panic(vm.NewGoError(err))
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ws *WS) WriteJSON(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
|
|
|
args := gojs.MakeArgs(&argsIn, vm).Check(1)
|
|
|
|
ws.writeLock.Lock()
|
|
|
|
err := ws.conn.WriteJSON(args.Any(0))
|
|
|
|
ws.writeLock.Unlock()
|
|
|
|
if err != nil {
|
|
|
|
panic(vm.NewGoError(err))
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (ws *WS) Close(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
|
|
|
// fmt.Println(u.BMagenta("WS"), "stop")
|
|
|
|
ws.running = false
|
|
|
|
if !ws.closed {
|
|
|
|
ws.closed = true
|
|
|
|
err := ws.conn.Close()
|
|
|
|
if err != nil {
|
|
|
|
panic(vm.NewGoError(err))
|
|
|
|
}
|
|
|
|
<-ws.pingStopChan
|
|
|
|
<-ws.closeChan
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|