Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a1f5f72181 | ||
b1796dad4d | |||
e9d4ec6bc7 | |||
5352152b66 |
18
go.mod
18
go.mod
@ -3,17 +3,17 @@ module apigo.cc/gojs/service
|
|||||||
go 1.18
|
go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
apigo.cc/gojs v0.0.7
|
apigo.cc/gojs v0.0.12
|
||||||
apigo.cc/gojs/console v0.0.2
|
apigo.cc/gojs/console v0.0.2
|
||||||
apigo.cc/gojs/http v0.0.3
|
apigo.cc/gojs/http v0.0.3
|
||||||
apigo.cc/gojs/util v0.0.7
|
apigo.cc/gojs/util v0.0.8
|
||||||
github.com/gorilla/websocket v1.5.3
|
github.com/gorilla/websocket v1.5.3
|
||||||
github.com/ssgo/config v1.7.9
|
github.com/ssgo/config v1.7.9
|
||||||
github.com/ssgo/discover v1.7.9
|
github.com/ssgo/discover v1.7.9
|
||||||
github.com/ssgo/httpclient v1.7.8
|
github.com/ssgo/httpclient v1.7.8
|
||||||
github.com/ssgo/log v1.7.7
|
github.com/ssgo/log v1.7.7
|
||||||
github.com/ssgo/redis v1.7.7
|
github.com/ssgo/redis v1.7.7
|
||||||
github.com/ssgo/s v1.7.20
|
github.com/ssgo/s v1.7.22
|
||||||
github.com/ssgo/standard v1.7.7
|
github.com/ssgo/standard v1.7.7
|
||||||
github.com/ssgo/u v1.7.13
|
github.com/ssgo/u v1.7.13
|
||||||
)
|
)
|
||||||
@ -21,7 +21,7 @@ require (
|
|||||||
require (
|
require (
|
||||||
github.com/ZZMarquis/gm v1.3.2 // indirect
|
github.com/ZZMarquis/gm v1.3.2 // indirect
|
||||||
github.com/dlclark/regexp2 v1.11.4 // indirect
|
github.com/dlclark/regexp2 v1.11.4 // indirect
|
||||||
github.com/emmansun/gmsm v0.29.4 // indirect
|
github.com/emmansun/gmsm v0.29.6 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
||||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||||
github.com/go-sourcemap/sourcemap v2.1.4+incompatible // indirect
|
github.com/go-sourcemap/sourcemap v2.1.4+incompatible // indirect
|
||||||
@ -32,13 +32,13 @@ require (
|
|||||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
|
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
|
||||||
github.com/shirou/gopsutil/v3 v3.24.5 // indirect
|
github.com/shirou/gopsutil/v3 v3.24.5 // indirect
|
||||||
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||||
github.com/ssgo/tool v0.4.27 // indirect
|
github.com/ssgo/tool v0.4.28 // indirect
|
||||||
github.com/tklauser/go-sysconf v0.3.14 // indirect
|
github.com/tklauser/go-sysconf v0.3.14 // indirect
|
||||||
github.com/tklauser/numcpus v0.9.0 // indirect
|
github.com/tklauser/numcpus v0.9.0 // indirect
|
||||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||||
golang.org/x/crypto v0.29.0 // indirect
|
golang.org/x/crypto v0.31.0 // indirect
|
||||||
golang.org/x/net v0.31.0 // indirect
|
golang.org/x/net v0.32.0 // indirect
|
||||||
golang.org/x/sys v0.27.0 // indirect
|
golang.org/x/sys v0.28.0 // indirect
|
||||||
golang.org/x/text v0.20.0 // indirect
|
golang.org/x/text v0.21.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
@ -111,7 +111,7 @@ func (r *Response) SendFile(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Val
|
|||||||
|
|
||||||
func (r *Response) DownloadFile(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
func (r *Response) DownloadFile(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
||||||
args := gojs.MakeArgs(&argsIn, vm).Check(3)
|
args := gojs.MakeArgs(&argsIn, vm).Check(3)
|
||||||
r.resp.DownloadFile(args.Str(0), args.Str(1), args.Bytes(1))
|
r.resp.DownloadFile(args.Str(0), args.Str(1), args.Bytes(2))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
50
service.go
50
service.go
@ -90,7 +90,7 @@ func initConfig(opt *gojs.Obj, logger *log.Logger, vm *goja.Runtime) {
|
|||||||
s.SetWorkPath(u.String(startPath))
|
s.SetWorkPath(u.String(startPath))
|
||||||
}
|
}
|
||||||
// 处理配置
|
// 处理配置
|
||||||
serviceConfig = Config{"Session", "Device", "Client", "userId", "", 3600, "auth failed", "verify failed", "too many requests", nil, "", map[string]string{}, map[string]string{}, map[string]string{}}
|
serviceConfig = Config{"Session", "Device", "Client", "id", "", 3600, "auth failed", "verify failed", "too many requests", nil, "", map[string]string{}, map[string]string{}, map[string]string{}}
|
||||||
if errs := config.LoadConfig("service", &serviceConfig); errs != nil && len(errs) > 0 {
|
if errs := config.LoadConfig("service", &serviceConfig); errs != nil && len(errs) > 0 {
|
||||||
panic(vm.NewGoError(errs[0]))
|
panic(vm.NewGoError(errs[0]))
|
||||||
}
|
}
|
||||||
@ -214,20 +214,13 @@ func init() {
|
|||||||
// 处理Watch
|
// 处理Watch
|
||||||
if vm.GoData["inWatch"] == true {
|
if vm.GoData["inWatch"] == true {
|
||||||
onWatchConn := map[string]*websocket.Conn{}
|
onWatchConn := map[string]*websocket.Conn{}
|
||||||
onWatchLock := sync.RWMutex{}
|
onWatchLock := sync.Mutex{}
|
||||||
vm.GoData["onWatch"] = func(filename string) {
|
vm.GoData["onWatch"] = func(filename string) {
|
||||||
conns := map[string]*websocket.Conn{}
|
onWatchLock.Lock()
|
||||||
onWatchLock.RLock()
|
defer onWatchLock.Unlock()
|
||||||
for id, conn := range onWatchConn {
|
for id, conn := range onWatchConn {
|
||||||
conns[id] = conn
|
|
||||||
}
|
|
||||||
onWatchLock.RUnlock()
|
|
||||||
for id, conn := range conns {
|
|
||||||
if err := conn.WriteMessage(websocket.TextMessage, []byte(filename)); err != nil {
|
if err := conn.WriteMessage(websocket.TextMessage, []byte(filename)); err != nil {
|
||||||
onWatchLock.Lock()
|
|
||||||
delete(onWatchConn, id)
|
delete(onWatchConn, id)
|
||||||
onWatchLock.Unlock()
|
|
||||||
} else {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -244,13 +237,43 @@ func init() {
|
|||||||
s.SetOutFilter(func(in map[string]any, request *s.Request, response *s.Response, out any, logger *log.Logger) (newOut any, isOver bool) {
|
s.SetOutFilter(func(in map[string]any, request *s.Request, response *s.Response, out any, logger *log.Logger) (newOut any, isOver bool) {
|
||||||
if strings.HasPrefix(response.Header().Get("Content-Type"), "text/html") {
|
if strings.HasPrefix(response.Header().Get("Content-Type"), "text/html") {
|
||||||
outStr := u.String(out)
|
outStr := u.String(out)
|
||||||
|
if strings.Contains(outStr, "let _watchWS = null") {
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
// 注入自动刷新的代码
|
// 注入自动刷新的代码
|
||||||
outStr = strings.ReplaceAll(outStr, "</html>", `<script>
|
outStr = strings.ReplaceAll(outStr, "</html>", `<script>
|
||||||
|
let _watchWS = null
|
||||||
|
let _watchWSConnection = false
|
||||||
|
let _watchWSIsFirst = true
|
||||||
function connect() {
|
function connect() {
|
||||||
|
_watchWSConnection = true
|
||||||
let ws = new WebSocket(location.protocol.replace('http', 'ws') + '//' + location.host + '/_watch')
|
let ws = new WebSocket(location.protocol.replace('http', 'ws') + '//' + location.host + '/_watch')
|
||||||
ws.onmessage = () => { location.reload() }
|
ws.onopen = () => {
|
||||||
ws.onclose = () => { setTimeout(connect, 1000) }
|
_watchWS = ws
|
||||||
|
_watchWSConnection = false
|
||||||
|
if( !_watchWSIsFirst ) location.reload()
|
||||||
|
_watchWSIsFirst = false
|
||||||
|
}
|
||||||
|
ws.onmessage = () => {
|
||||||
|
location.reload()
|
||||||
|
}
|
||||||
|
ws.onclose = () => {
|
||||||
|
_watchWS = null
|
||||||
|
_watchWSConnection = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
setInterval(()=>{
|
||||||
|
if(_watchWS!= null){
|
||||||
|
try{
|
||||||
|
_watchWS.send("ping")
|
||||||
|
}catch(err){
|
||||||
|
_watchWS = null
|
||||||
|
_watchWSConnection = false
|
||||||
|
}
|
||||||
|
} else if(!_watchWSConnection){
|
||||||
|
connect()
|
||||||
|
}
|
||||||
|
}, 1000)
|
||||||
connect()
|
connect()
|
||||||
</script>
|
</script>
|
||||||
</html>`)
|
</html>`)
|
||||||
@ -285,6 +308,7 @@ func init() {
|
|||||||
panic(vm.NewGoError(errors.New("server not started")))
|
panic(vm.NewGoError(errors.New("server not started")))
|
||||||
}
|
}
|
||||||
server.Stop()
|
server.Stop()
|
||||||
|
s.ResetAllSets()
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
"uniqueId": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
"uniqueId": func(argsIn goja.FunctionCall, vm *goja.Runtime) goja.Value {
|
||||||
|
@ -85,6 +85,8 @@ interface Config {
|
|||||||
cpuLimitTimes: number // CPU超过最高占用值超过次数(1-100)将报警(如果CpuMonitor开启的话),默认6(即30秒内连续6次)
|
cpuLimitTimes: number // CPU超过最高占用值超过次数(1-100)将报警(如果CpuMonitor开启的话),默认6(即30秒内连续6次)
|
||||||
memoryLimitTimes: number // 内存超过最高占用值超过次数(1-100)将报警(如果MemoryMonitor开启的话),默认6(即30秒内连续6次)
|
memoryLimitTimes: number // 内存超过最高占用值超过次数(1-100)将报警(如果MemoryMonitor开启的话),默认6(即30秒内连续6次)
|
||||||
cookieScope: string // 启用Session时Cookie的有效范围,host|domain|topDomain,默认值为host
|
cookieScope: string // 启用Session时Cookie的有效范围,host|domain|topDomain,默认值为host
|
||||||
|
sessionWithoutCookie: boolean // Session禁用Cookie保持,默认使用Cookie
|
||||||
|
deviceWithoutCookie: boolean // 设备ID禁用Cookie保持,默认使用Cookie
|
||||||
idServer: string // 用s.UniqueId、s.Id来生成唯一ID(雪花算法)时所需的redis服务器连接,如果不指定将不能实现跨服务的全局唯一
|
idServer: string // 用s.UniqueId、s.Id来生成唯一ID(雪花算法)时所需的redis服务器连接,如果不指定将不能实现跨服务的全局唯一
|
||||||
keepKeyCase: boolean // 是否保持Key的首字母大小写?默认保持,设置为false则自动将首字母转为小写
|
keepKeyCase: boolean // 是否保持Key的首字母大小写?默认保持,设置为false则自动将首字母转为小写
|
||||||
indexFiles: string[] // 访问静态文件时的索引文件,默认为 index.html
|
indexFiles: string[] // 访问静态文件时的索引文件,默认为 index.html
|
||||||
@ -106,7 +108,7 @@ interface Config {
|
|||||||
sessionKey: string // HTTP头和Cookie中SessionID的Key,客户端没有传递时服务端自动生成,Header的优先级高于Cookie,默认为 Session, 设置为空时表示不使用
|
sessionKey: string // HTTP头和Cookie中SessionID的Key,客户端没有传递时服务端自动生成,Header的优先级高于Cookie,默认为 Session, 设置为空时表示不使用
|
||||||
deviceKey: string // 标识设备ID的Key,客户端没有传递时服务端自动生成,Header的优先级高于Cookie,默认为 Device, 设置为空时表示不使用
|
deviceKey: string // 标识设备ID的Key,客户端没有传递时服务端自动生成,Header的优先级高于Cookie,默认为 Device, 设置为空时表示不使用
|
||||||
clientKey: string // 标识客户端的Key,默认为 Client,对应的Header头为 ClientName 和 ClientVersion
|
clientKey: string // 标识客户端的Key,默认为 Client,对应的Header头为 ClientName 和 ClientVersion
|
||||||
userIdKey: string // session中userID的Key,用于在日志中记录userId信息,默认为 userId
|
userIdKey: string // session中userID的Key,用于在日志中记录用户ID信息,默认为 id
|
||||||
sessionProvider: string // 指定一个redis连接(例如:redis://:sskey加密的密码@127.0.0.1:6379/15),默认使用内存存储
|
sessionProvider: string // 指定一个redis连接(例如:redis://:sskey加密的密码@127.0.0.1:6379/15),默认使用内存存储
|
||||||
sessionTimeout: number // session过期时间,单位 秒,默认为 3600秒
|
sessionTimeout: number // session过期时间,单位 秒,默认为 3600秒
|
||||||
authFieldMessage: string | Object // 身份验证失败时的消息,默认为 auth failed,可以设置对象来返回JSON,可以使用模版 {{TARGET_AUTHLEVEL}}、{{USER_AUTHLEVEL}}
|
authFieldMessage: string | Object // 身份验证失败时的消息,默认为 auth failed,可以设置对象来返回JSON,可以使用模版 {{TARGET_AUTHLEVEL}}、{{USER_AUTHLEVEL}}
|
||||||
@ -271,6 +273,7 @@ interface Response {
|
|||||||
sendFile: (contentType: string, filename: string) => void
|
sendFile: (contentType: string, filename: string) => void
|
||||||
downloadFile: (contentType: string, filename: string, data: any) => void
|
downloadFile: (contentType: string, filename: string, data: any) => void
|
||||||
location: (url: string) => void
|
location: (url: string) => void
|
||||||
|
end: (data: any) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Logger {
|
interface Logger {
|
||||||
|
Loading…
Reference in New Issue
Block a user