重构 websocket
This commit is contained in:
@@ -1,9 +1,7 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"path/filepath"
|
||||
@@ -15,7 +13,6 @@ import (
|
||||
"github.com/dop251/goja_nodejs/eventloop"
|
||||
"github.com/dop251/goja_nodejs/require"
|
||||
"github.com/dop251/goja_nodejs/url"
|
||||
"go.uber.org/zap"
|
||||
"gopkg.d7z.net/gitea-pages/pkg/core"
|
||||
)
|
||||
|
||||
@@ -109,16 +106,15 @@ func FilterInstGoJa(gl core.Params) (core.FilterInstance, error) {
|
||||
go func() {
|
||||
for {
|
||||
switch promise.State() {
|
||||
case goja.PromiseStateFulfilled, goja.PromiseStateRejected:
|
||||
result := promise.Result().Export()
|
||||
switch data := result.(type) {
|
||||
case goja.PromiseStateFulfilled:
|
||||
stop <- nil
|
||||
return
|
||||
case goja.PromiseStateRejected:
|
||||
switch data := promise.Result().Export().(type) {
|
||||
case error:
|
||||
stop <- data
|
||||
default:
|
||||
marshal, _ := json.Marshal(result)
|
||||
zap.L().Debug(fmt.Sprintf("js promise result %s", string(marshal)),
|
||||
zap.Any("result", promise.Result().ExportType()))
|
||||
stop <- nil
|
||||
stop <- errors.New(promise.Result().String())
|
||||
}
|
||||
return
|
||||
default:
|
||||
@@ -126,7 +122,11 @@ func FilterInstGoJa(gl core.Params) (core.FilterInstance, error) {
|
||||
}
|
||||
}
|
||||
}()
|
||||
} else {
|
||||
stop <- nil
|
||||
}
|
||||
} else {
|
||||
stop <- nil
|
||||
}
|
||||
})
|
||||
resultErr := <-stop
|
||||
|
||||
@@ -30,8 +30,19 @@ func EventInject(ctx core.FilterContext, jsCtx *goja.Runtime, loop *eventloop.Ev
|
||||
}()
|
||||
return promise
|
||||
},
|
||||
"put": func(key, value string) error {
|
||||
return ctx.Event.Publish(ctx, key, value)
|
||||
"put": func(key, value string) *goja.Promise {
|
||||
promise, resolve, reject := jsCtx.NewPromise()
|
||||
go func() {
|
||||
err := ctx.Event.Publish(ctx, key, value)
|
||||
loop.RunOnLoop(func(runtime *goja.Runtime) {
|
||||
if err != nil {
|
||||
_ = reject(runtime.ToValue(err))
|
||||
} else {
|
||||
_ = resolve(goja.Undefined())
|
||||
}
|
||||
})
|
||||
}()
|
||||
return promise
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ func WebsocketInject(ctx core.FilterContext, jsCtx *goja.Runtime, w http.Respons
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
zap.L().Debug("websocket upgrader created")
|
||||
closers.AddCloser(conn.Close)
|
||||
go func() {
|
||||
ticker := time.NewTicker(15 * time.Second)
|
||||
defer ticker.Stop()
|
||||
@@ -37,28 +39,7 @@ func WebsocketInject(ctx core.FilterContext, jsCtx *goja.Runtime, w http.Respons
|
||||
}
|
||||
}
|
||||
}()
|
||||
zap.L().Debug("websocket upgrader created")
|
||||
closers.AddCloser(conn.Close)
|
||||
return map[string]interface{}{
|
||||
"on": func(f func(mType int, message string)) {
|
||||
go func() {
|
||||
z:
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
break z
|
||||
default:
|
||||
messageType, p, err := conn.ReadMessage()
|
||||
if err != nil {
|
||||
break z
|
||||
}
|
||||
f(messageType, string(p))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}()
|
||||
},
|
||||
"TypeTextMessage": websocket.TextMessage,
|
||||
"TypeBinaryMessage": websocket.BinaryMessage,
|
||||
"readText": func() *goja.Promise {
|
||||
@@ -91,36 +72,115 @@ func WebsocketInject(ctx core.FilterContext, jsCtx *goja.Runtime, w http.Respons
|
||||
}()
|
||||
return promise
|
||||
},
|
||||
"read": func() (any, error) {
|
||||
messageType, p, err := conn.ReadMessage()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return map[string]interface{}{
|
||||
"type": messageType,
|
||||
"data": p,
|
||||
}, nil
|
||||
"read": func() *goja.Promise {
|
||||
promise, resolve, reject := jsCtx.NewPromise()
|
||||
go func() {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
loop.RunOnLoop(func(runtime *goja.Runtime) {
|
||||
_ = reject(runtime.ToValue(ctx.Err()))
|
||||
})
|
||||
return
|
||||
default:
|
||||
}
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
zap.L().Debug("websocket panic", zap.Any("panic", r))
|
||||
loop.RunOnLoop(func(runtime *goja.Runtime) {
|
||||
_ = reject(runtime.ToValue(r))
|
||||
})
|
||||
}
|
||||
}()
|
||||
messageType, p, err := conn.ReadMessage()
|
||||
loop.RunOnLoop(func(runtime *goja.Runtime) {
|
||||
if err != nil {
|
||||
_ = reject(runtime.ToValue(err))
|
||||
} else {
|
||||
_ = resolve(runtime.ToValue(map[string]interface{}{
|
||||
"type": messageType,
|
||||
"data": p,
|
||||
}))
|
||||
}
|
||||
})
|
||||
}()
|
||||
return promise
|
||||
},
|
||||
"writeText": func(data string) error {
|
||||
return conn.WriteMessage(websocket.TextMessage, []byte(data))
|
||||
"writeText": func(data string) *goja.Promise {
|
||||
promise, resolve, reject := jsCtx.NewPromise()
|
||||
go func() {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
loop.RunOnLoop(func(runtime *goja.Runtime) {
|
||||
_ = reject(runtime.ToValue(ctx.Err()))
|
||||
})
|
||||
return
|
||||
default:
|
||||
}
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
zap.L().Debug("websocket panic", zap.Any("panic", r))
|
||||
loop.RunOnLoop(func(runtime *goja.Runtime) {
|
||||
_ = reject(runtime.ToValue(r))
|
||||
})
|
||||
}
|
||||
}()
|
||||
err := conn.WriteMessage(websocket.TextMessage, []byte(data))
|
||||
loop.RunOnLoop(func(runtime *goja.Runtime) {
|
||||
if err != nil {
|
||||
_ = reject(runtime.ToValue(err))
|
||||
} else {
|
||||
_ = resolve(runtime.ToValue(nil))
|
||||
}
|
||||
})
|
||||
}()
|
||||
return promise
|
||||
},
|
||||
"write": func(mType int, data any) error {
|
||||
if item, ok := data.(goja.Value); ok {
|
||||
data = item.Export()
|
||||
}
|
||||
var dataRaw []byte
|
||||
switch it := data.(type) {
|
||||
case []byte:
|
||||
dataRaw = it
|
||||
case string:
|
||||
dataRaw = []byte(it)
|
||||
default:
|
||||
return errors.Errorf("invalid type for websocket text: %T", data)
|
||||
}
|
||||
return conn.WriteMessage(mType, dataRaw)
|
||||
},
|
||||
"ping": func() error {
|
||||
return conn.WriteControl(websocket.PingMessage, []byte{}, time.Now().Add(1*time.Second))
|
||||
"write": func(mType int, data any) *goja.Promise {
|
||||
promise, resolve, reject := jsCtx.NewPromise()
|
||||
go func() {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
loop.RunOnLoop(func(runtime *goja.Runtime) {
|
||||
_ = reject(runtime.ToValue(ctx.Err()))
|
||||
})
|
||||
return
|
||||
default:
|
||||
}
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
zap.L().Debug("websocket panic", zap.Any("panic", r))
|
||||
loop.RunOnLoop(func(runtime *goja.Runtime) {
|
||||
_ = reject(runtime.ToValue(r))
|
||||
})
|
||||
}
|
||||
}()
|
||||
|
||||
if item, ok := data.(goja.Value); ok {
|
||||
data = item.Export()
|
||||
}
|
||||
var dataRaw []byte
|
||||
switch it := data.(type) {
|
||||
case []byte:
|
||||
dataRaw = it
|
||||
case string:
|
||||
dataRaw = []byte(it)
|
||||
default:
|
||||
loop.RunOnLoop(func(runtime *goja.Runtime) {
|
||||
_ = reject(runtime.ToValue(errors.Errorf("invalid type for websocket text: %T", data)))
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
err := conn.WriteMessage(mType, dataRaw)
|
||||
loop.RunOnLoop(func(runtime *goja.Runtime) {
|
||||
if err != nil {
|
||||
_ = reject(runtime.ToValue(err))
|
||||
} else {
|
||||
_ = resolve(goja.Undefined())
|
||||
}
|
||||
})
|
||||
}()
|
||||
return promise
|
||||
},
|
||||
}, nil
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user