From 9c4e24cc5cd8302c115c098a3046a1028e54a46d Mon Sep 17 00:00:00 2001 From: harveyshao Date: Mon, 28 Nov 2022 20:32:41 +0800 Subject: [PATCH] opt web.serve --- base/aaa/sess.go | 8 +-- base/aaa/user.go | 10 +-- base/ctx/command.go | 6 +- base/gdb/event.go | 18 ++++- base/web/serve.go | 158 +++++++++++++++++--------------------------- base/web/space.go | 9 +-- base/web/web.go | 6 +- conf.go | 1 + core/chat/favor.go | 1 + core/chat/header.go | 3 - init.go | 8 +++ logs.go | 10 ++- meta.go | 3 + misc.go | 22 ++++-- misc/vim/tags.go | 2 +- type.go | 13 +++- 16 files changed, 140 insertions(+), 138 deletions(-) diff --git a/base/aaa/sess.go b/base/aaa/sess.go index 91d18fec..c267489e 100644 --- a/base/aaa/sess.go +++ b/base/aaa/sess.go @@ -67,16 +67,16 @@ func SessCreate(m *ice.Message, username string) string { return m.Option(ice.MSG_SESSID, m.Cmdx(SESS, mdb.CREATE, username)) } func SessCheck(m *ice.Message, sessid string) bool { - m.Option("log.caller", logs.FileLine(2)) + m.Option("aaa.checker", logs.FileLine(2)) m.Options(ice.MSG_USERNAME, "", ice.MSG_USERNICK, "", ice.MSG_USERROLE, VOID) return sessid != "" && m.Cmdy(SESS, CHECK, sessid).Option(ice.MSG_USERNAME) != "" } -func SessAuth(m *ice.Message, value ice.Any, arg ...string) { - m.Auth( +func SessAuth(m *ice.Message, value ice.Any, arg ...string) *ice.Message { + return m.Auth( USERNAME, m.Option(ice.MSG_USERNAME, kit.Value(value, USERNAME)), USERNICK, m.Option(ice.MSG_USERNICK, kit.Value(value, USERNICK)), USERROLE, m.Option(ice.MSG_USERROLE, kit.Value(value, USERROLE)), - arg, logs.FileLineMeta(kit.Select(logs.FileLine(-1), m.Option("log.caller"))), + arg, logs.FileLineMeta(kit.Select(logs.FileLine(-1), m.Option("aaa.checker"))), ) } func SessLogout(m *ice.Message, arg ...string) { diff --git a/base/aaa/user.go b/base/aaa/user.go index d9e1a792..71d3dcd2 100644 --- a/base/aaa/user.go +++ b/base/aaa/user.go @@ -97,12 +97,12 @@ func UserLogin(m *ice.Message, username, password string) bool { return m.Cmdy(USER, LOGIN, username, password).Option(ice.MSG_USERNAME) != "" } func UserRoot(m *ice.Message, arg ...string) *ice.Message { - username := m.Option(ice.MSG_USERNAME, kit.Select(ice.Info.UserName, arg, 0)) - usernick := m.Option(ice.MSG_USERNICK, kit.Select(UserNick(m, username), arg, 1)) - userrole := m.Option(ice.MSG_USERROLE, kit.Select(ROOT, arg, 2)) + username := kit.Select(ice.Info.UserName, arg, 0) + usernick := kit.Select(UserNick(m, username), arg, 1) + userrole := kit.Select(ROOT, arg, 2) if len(arg) > 0 { - m.Cmd(USER, mdb.CREATE, username, "", usernick, "", userrole) ice.Info.UserName = username + m.Cmd(USER, mdb.CREATE, username, "", usernick, "", userrole) } - return m + return SessAuth(m, kit.Dict(USERNAME, username, USERNICK, usernick, USERROLE, userrole)) } diff --git a/base/ctx/command.go b/base/ctx/command.go index 1b844287..c4369450 100644 --- a/base/ctx/command.go +++ b/base/ctx/command.go @@ -57,7 +57,7 @@ func _command_search(m *ice.Message, kind, name, text string) { } m.PushSearch(ice.CTX, kit.PathName(1), ice.CMD, kit.FileName(1), kit.SimpleKV("", s.Cap(ice.CTX_FOLLOW), cmd.Name, cmd.Help), CONTEXT, s.Cap(ice.CTX_FOLLOW), COMMAND, key, INDEX, kit.Keys(s.Cap(ice.CTX_FOLLOW), key), - mdb.HELP, cmd.Help, nfs.FILE, FileURI(cmd.GetFileLine()), + mdb.HELP, cmd.Help, nfs.FILE, FileURI(cmd.GetFileLines()), ) }) } @@ -186,7 +186,7 @@ func GetFileCmd(dir string) string { } func GetCmdFile(m *ice.Message, cmds string) (file string) { m.Search(cmds, func(key string, cmd *ice.Command) { - if file = strings.TrimPrefix(FileURI(kit.Split(cmd.GetFileLine(), ice.DF)[0]), "/require/"); !nfs.ExistsFile(m, file) { + if file = strings.TrimPrefix(FileURI(kit.Split(cmd.GetFileLines(), ice.DF)[0]), "/require/"); !nfs.ExistsFile(m, file) { file = path.Join(ice.ISH_PLUGED, file) } }) @@ -197,7 +197,7 @@ func TravelCmd(m *ice.Message, cb func(key, file, line string)) *ice.Message { if IsOrderCmd(key) { return } - if ls := kit.Split(cmd.GetFileLine(), ice.DF); !m.Warn(len(ls) == 0, ice.ErrNotFound, key) { + if ls := kit.Split(cmd.GetFileLines(), ice.DF); !m.Warn(len(ls) == 0, ice.ErrNotFound, key) { cb(kit.Keys(s.Cap(ice.CTX_FOLLOW), key), strings.TrimPrefix(ls[0], kit.Path("")+ice.PS), kit.Select("1", ls, 1)) } }) diff --git a/base/gdb/event.go b/base/gdb/event.go index 3323ca63..db90a848 100644 --- a/base/gdb/event.go +++ b/base/gdb/event.go @@ -4,6 +4,7 @@ import ( ice "shylinux.com/x/icebergs" "shylinux.com/x/icebergs/base/mdb" kit "shylinux.com/x/toolkits" + "shylinux.com/x/toolkits/logs" ) const ( @@ -19,8 +20,9 @@ func init() { mdb.ZoneInsert(m, m.OptionSimple(EVENT, ice.CMD)) }}, HAPPEN: {Name: "happen event", Help: "触发", Hand: func(m *ice.Message, arg ...string) { + defer m.Cost() mdb.ZoneSelect(m.Spawn(ice.OptionFields("")), m.Option(EVENT)).Tables(func(value ice.Maps) { - m.Cmdy(kit.Split(value[ice.CMD]), m.Option(EVENT), arg[2:], ice.OptionFields("")).Cost() + m.Cmdy(kit.Split(value[ice.CMD]), m.Option(EVENT), arg[2:], ice.OptionFields("")) }) }}, }, mdb.ZoneAction(mdb.SHORT, EVENT, mdb.FIELD, "time,id,cmd"))}, @@ -28,13 +30,23 @@ func init() { } func EventAction(arg ...string) ice.Actions { return ice.Actions{ - ice.CTX_INIT: {Hand: func(m *ice.Message, args ...string) { + ice.CTX_INIT: {Hand: func(m *ice.Message, _ ...string) { for _, v := range arg { Watch(m, v) } }}, } } +func EventsAction(arg ...string) ice.Actions { + list := kit.DictList(arg...) + return ice.Actions{ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { + for sub := range m.Target().Commands[m.CommandKey()].Actions { + if list[sub] == ice.TRUE { + Watch(m, sub) + } + } + }}} +} func Watch(m *ice.Message, key string, arg ...string) *ice.Message { if len(arg) == 0 { arg = append(arg, m.PrefixKey()) @@ -42,5 +54,5 @@ func Watch(m *ice.Message, key string, arg ...string) *ice.Message { return m.Cmd(EVENT, LISTEN, EVENT, key, ice.CMD, kit.Join(arg, ice.SP)) } func Event(m *ice.Message, key string, arg ...ice.Any) *ice.Message { - return m.Cmdy(EVENT, HAPPEN, EVENT, kit.Select(kit.Keys(m.CommandKey(), m.ActionKey()), key), arg) + return m.Cmdy(EVENT, HAPPEN, EVENT, kit.Select(kit.Keys(m.CommandKey(), m.ActionKey()), key), arg, logs.FileLineMeta(logs.FileLine(-1))) } diff --git a/base/web/serve.go b/base/web/serve.go index 16166c63..ee9bddbb 100644 --- a/base/web/serve.go +++ b/base/web/serve.go @@ -1,7 +1,6 @@ package web import ( - "encoding/json" "net/http" "net/url" "path" @@ -17,121 +16,82 @@ import ( "shylinux.com/x/icebergs/base/ssh" "shylinux.com/x/icebergs/base/tcp" kit "shylinux.com/x/toolkits" - "shylinux.com/x/toolkits/logs" ) func _serve_start(m *ice.Message) { + aaa.UserRoot(m, m.Option(aaa.USERNAME), m.Option(aaa.USERNICK)) if cli.NodeInfo(m, kit.Select(ice.Info.HostName, m.Option("nodename")), SERVER); m.Option(tcp.PORT) == tcp.RANDOM { m.Option(tcp.PORT, m.Cmdx(tcp.PORT, aaa.RIGHT)) } - aaa.UserRoot(m, m.Option(aaa.USERNAME), m.Option(aaa.USERNICK)) m.Target().Start(m, m.OptionSimple(tcp.HOST, tcp.PORT)...) - m.Sleep300ms().Go(func() { m.Cmd(BROAD, SERVE) }) - for _, k := range kit.Split(m.Option(ice.DEV)) { - m.Cmd(SPACE, tcp.DIAL, ice.DEV, k, mdb.NAME, ice.Info.NodeName) + m.Sleep30ms().Go(func() { m.Cmd(BROAD, SERVE) }) + for _, v := range kit.Split(m.Option(ice.DEV)) { + m.Cmd(SPACE, tcp.DIAL, ice.DEV, v, mdb.NAME, ice.Info.NodeName) } } func _serve_main(m *ice.Message, w http.ResponseWriter, r *http.Request) bool { - if r.Header.Get("Index-Module") == "" { - r.Header.Set("Index-Module", m.Prefix()) + const ( + X_REAL_IP = "X-Real-Ip" + X_REAL_PORT = "X-Real-Port" + X_FORWARDED_FOR = "X-Forwarded-For" + INDEX_MODULE = "Index-Module" + MOZILLA = "Mozilla/5.0" + ) + if r.Header.Get(INDEX_MODULE) == "" { + r.Header.Set(INDEX_MODULE, m.Prefix()) } else { return true } - if ip := r.Header.Get("X-Real-Ip"); ip != "" { - if r.Header.Set(ice.MSG_USERIP, ip); r.Header.Get("X-Real-Port") != "" { - r.Header.Set(ice.MSG_USERADDR, ip+":"+r.Header.Get("X-Real-Port")) + if ip := r.Header.Get(X_REAL_IP); ip != "" { + if r.Header.Set(ice.MSG_USERIP, ip); r.Header.Get(X_REAL_PORT) != "" { + r.Header.Set(ice.MSG_USERADDR, ip+ice.DF+r.Header.Get(X_REAL_PORT)) } - } else if ip := r.Header.Get("X-Forwarded-For"); ip != "" { + } else if ip := r.Header.Get(X_FORWARDED_FOR); ip != "" { r.Header.Set(ice.MSG_USERIP, kit.Split(ip)[0]) } else if strings.HasPrefix(r.RemoteAddr, "[") { r.Header.Set(ice.MSG_USERIP, strings.Split(r.RemoteAddr, "]")[0][1:]) } else { - r.Header.Set(ice.MSG_USERIP, strings.Split(r.RemoteAddr, ":")[0]) + r.Header.Set(ice.MSG_USERIP, strings.Split(r.RemoteAddr, ice.DF)[0]) } - meta := logs.FileLineMeta("") - m.Info("%s %s %s", r.Header.Get(ice.MSG_USERIP), r.Method, r.URL, meta) - if m.Config(LOGHEADERS) == ice.TRUE { - for k, v := range r.Header { - m.Info("%s: %v", k, kit.Format(v), meta) - } - m.Info("", meta) + if m.Logs(r.Method, r.Header.Get(ice.MSG_USERIP), r.URL.String()); m.Config(LOGHEADERS) == ice.TRUE { + kit.Fetch(r.Header, func(k string, v []string) { m.Logs("Header", k, v) }) } - repos := kit.Select(ice.INTSHELL, ice.VOLCANOS, strings.Contains(r.Header.Get(UserAgent), "Mozilla/5.0")) + repos := kit.Select(ice.INTSHELL, ice.VOLCANOS, strings.Contains(r.Header.Get(UserAgent), MOZILLA)) if msg := gdb.Event(m.Spawn(w, r), SERVE_REWRITE, r.Method, r.URL.Path, path.Join(m.Conf(SERVE, kit.Keym(repos, nfs.PATH)), r.URL.Path), repos); msg.Option(ice.MSG_OUTPUT) != "" { Render(msg, msg.Option(ice.MSG_OUTPUT), kit.List(msg.Optionv(ice.MSG_ARGS))...) return false } return true } -func _serve_domain(m *ice.Message) string { - if p := ice.Info.Domain; p != "" { - return p - } - if p := m.R.Header.Get("X-Host"); p != "" { - return p - } - if m.R.Method == SPIDE_POST { - if p := m.R.Header.Get(Referer); p != "" { - return p - } - } - if m.R.TLS == nil { - return kit.Format("http://%s", m.R.Host) - } else { - return kit.Format("https://%s", m.R.Host) - } -} func _serve_handle(key string, cmd *ice.Command, m *ice.Message, w http.ResponseWriter, r *http.Request) { - meta := logs.FileLineMeta("") if u, e := url.Parse(r.Header.Get(Referer)); e == nil { gdb.Event(m, SERVE_PARSE, strings.Split(strings.TrimPrefix(u.Path, ice.PS), ice.PS)) - kit.Fetch(u.Query(), func(k string, v []string) { m.Logs("refer", k, v, meta).Optionv(k, v) }) + kit.Fetch(u.Query(), func(k string, v []string) { m.Logs("Refer", k, v).Optionv(k, v) }) + } + for k, v := range kit.ParseQuery(r.URL.RawQuery) { + if m.IsCliUA() { + v = kit.Simple(v, func(v string) (string, error) { return url.QueryUnescape(v) }) + } + m.Optionv(k, v) } switch r.Header.Get(ContentType) { case ContentJSON: - defer r.Body.Close() - var data ice.Any - if e := json.NewDecoder(r.Body).Decode(&data); !m.Warn(e, ice.ErrNotFound, data) { - m.Logs(mdb.IMPORT, mdb.VALUE, kit.Format(data)) - m.Optionv(ice.MSG_USERDATA, data) - } - kit.Fetch(data, func(key string, value ice.Any) { m.Optionv(key, value) }) + data := kit.UnMarshal(r.Body) + m.Logs(mdb.IMPORT, mdb.VALUE, kit.Format(data)).Optionv(ice.MSG_USERDATA, data) + kit.Fetch(data, func(k string, v ice.Any) { m.Optionv(k, v) }) default: r.ParseMultipartForm(kit.Int64(kit.Select("4096", r.Header.Get(ContentLength)))) - if r.ParseForm(); len(r.PostForm) > 0 { - kit.Fetch(r.PostForm, func(k string, v []string) { - if len(v) > 1 { - m.Logs("form", k, len(v), kit.Join(v, ice.SP), meta) - } else { - m.Logs("form", k, v, meta) - } - }) - } + kit.Fetch(r.PostForm, func(k string, v []string) { m.Logs("Form", k, kit.Join(v, ice.SP)).Optionv(k, v) }) } - m.R, m.W = r, w - for k, v := range r.Form { - if m.IsCliUA() { - for i, p := range v { - v[i], _ = url.QueryUnescape(p) - } - } - m.Optionv(k, v) - } - for k, v := range r.PostForm { - m.Optionv(k, v) - } - for _, v := range r.Cookies() { - m.Optionv(v.Name, v.Value) - } - m.Option(ice.MSG_USERADDR, kit.Select(r.RemoteAddr, r.Header.Get(ice.MSG_USERADDR))) - m.Option(ice.MSG_USERIP, r.Header.Get(ice.MSG_USERIP)) + kit.Fetch(r.Cookies(), func(k, v string) { m.Optionv(k, v) }) + m.OptionDefault(ice.HEIGHT, "480", ice.WIDTH, "320") m.Option(ice.MSG_USERUA, r.Header.Get(UserAgent)) + m.Option(ice.MSG_USERIP, r.Header.Get(ice.MSG_USERIP)) + m.Option(ice.MSG_USERADDR, kit.Select(r.RemoteAddr, r.Header.Get(ice.MSG_USERADDR))) if m.Option(ice.MSG_USERWEB, _serve_domain(m)); m.Option(ice.POD) != "" { m.Option(ice.MSG_USERPOD, m.Option(ice.POD)) } - if sessid := m.Option(CookieName(m.Option(ice.MSG_USERWEB))); m.Option(ice.MSG_SESSID) == "" { - m.Option(ice.MSG_SESSID, sessid) - } + m.Option(ice.MSG_SESSID, m.Option(CookieName(m.Option(ice.MSG_USERWEB)))) if m.Optionv(ice.MSG_CMDS) == nil { if p := strings.TrimPrefix(r.URL.Path, key); p != "" { m.Optionv(ice.MSG_CMDS, strings.Split(p, ice.PS)) @@ -140,8 +100,8 @@ func _serve_handle(key string, cmd *ice.Command, m *ice.Message, w http.Response if cmds, ok := _serve_login(m, key, kit.Simple(m.Optionv(ice.MSG_CMDS)), w, r); ok { defer func() { m.Cost(kit.Format("%s %v %v", r.URL.Path, cmds, m.FormatSize())) }() m.Option(ice.MSG_OPTS, kit.Simple(m.Optionv(ice.MSG_OPTION), func(k string) bool { return !strings.HasPrefix(k, ice.MSG_SESSID) })) - if len(cmds) > 0 && cmds[0] == ctx.ACTION { - m.Target().Cmd(m, key, cmds...) + if m.Detailv(m.PrefixKey(), cmds); len(cmds) > 1 && cmds[0] == ctx.ACTION { + m.ActionHand(cmd, key, cmds[1], cmds[2:]...) } else { m.CmdHand(cmd, key, cmds...) } @@ -149,6 +109,17 @@ func _serve_handle(key string, cmd *ice.Command, m *ice.Message, w http.Response gdb.Event(m, SERVE_RENDER, m.Option(ice.MSG_OUTPUT)) Render(m, m.Option(ice.MSG_OUTPUT), m.Optionv(ice.MSG_ARGS)) } +func _serve_domain(m *ice.Message) string { + return kit.GetValid(func() string { + return ice.Info.Domain + }, func() string { + return m.R.Header.Get("X-Host") + }, func() string { + return kit.Select("", m.R.Header.Get(Referer), m.R.Method == SPIDE_POST) + }, func() string { + return kit.Format("%s://%s", kit.Select("https", ice.HTTP, m.R.TLS == nil), m.R.Host) + }) +} func _serve_login(m *ice.Message, key string, cmds []string, w http.ResponseWriter, r *http.Request) ([]string, bool) { if aaa.SessCheck(m, m.Option(ice.MSG_SESSID)); m.Option(ice.MSG_USERNAME) == "" { gdb.Event(m, SERVE_LOGIN) @@ -174,27 +145,25 @@ const ( SERVE_STOP = "serve.stop" WEB_LOGIN = "_login" + DOMAIN = "domain" + INDEX = "index" SSO = "sso" - - DOMAIN = "domain" - INDEX = "index" ) const SERVE = "serve" func init() { Index.MergeCommands(ice.Commands{ - SERVE: {Name: "serve name auto start spide", Help: "服务器", Actions: ice.MergeActions(ice.Actions{ + SERVE: {Name: "serve name auto start", Help: "服务器", Actions: ice.MergeActions(ice.Actions{ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { cli.NodeInfo(m, ice.Info.PathName, WORKER) aaa.White(m, LOGIN) }}, - cli.START: {Name: "start dev proto=http host port=9020 nodename username usernick", Hand: func(m *ice.Message, arg ...string) { + cli.START: {Name: "start dev name=web proto=http host port=9020 nodename username usernick", Hand: func(m *ice.Message, arg ...string) { _serve_start(m) }}, SERVE_START: {Hand: func(m *ice.Message, arg ...string) { m.Go(func() { - m.Sleep("30ms", ssh.PRINTF, kit.Dict(nfs.CONTENT, "\r"+ice.Render(m, ice.RENDER_QRCODE, m.Cmdx(SPACE, DOMAIN))+ice.NL)) - m.Cmd(ssh.PROMPT) + m.Sleep("30ms", ssh.PRINTF, kit.Dict(nfs.CONTENT, "\r"+ice.Render(m, ice.RENDER_QRCODE, m.Cmdx(SPACE, DOMAIN))+ice.NL)).Cmd(ssh.PROMPT) }) }}, SERVE_REWRITE: {Hand: func(m *ice.Message, arg ...string) { @@ -215,7 +184,6 @@ func init() { } }}, SERVE_PARSE: {Hand: func(m *ice.Message, arg ...string) { - m.Options(ice.HEIGHT, "480", ice.WIDTH, "320") }}, SERVE_LOGIN: {Hand: func(m *ice.Message, arg ...string) { if m.Option(ice.MSG_USERNAME) == "" && m.Config(tcp.LOCALHOST) == ice.TRUE && tcp.IsLocalHost(m, m.Option(ice.MSG_USERIP)) { @@ -230,7 +198,7 @@ func init() { m.Echo(ice.Info.Domain) }}, }, mdb.HashAction( - mdb.SHORT, mdb.NAME, mdb.FIELD, "time,status,name,proto,host,port,dev", tcp.LOCALHOST, ice.TRUE, LOGHEADERS, ice.FALSE, + mdb.SHORT, mdb.NAME, mdb.FIELD, "time,status,name,proto,host,port", tcp.LOCALHOST, ice.TRUE, LOGHEADERS, ice.FALSE, ice.INTSHELL, kit.Dict(nfs.PATH, ice.USR_INTSHELL, INDEX, ice.INDEX_SH, nfs.REPOS, "https://shylinux.com/x/intshell", nfs.BRANCH, nfs.MASTER), ice.VOLCANOS, kit.Dict(nfs.PATH, ice.USR_VOLCANOS, INDEX, "page/index.html", nfs.REPOS, "https://shylinux.com/x/volcanos", nfs.BRANCH, nfs.MASTER), ), ServeAction())}, @@ -269,24 +237,16 @@ func init() { m.Cmdy("web.chat./cmd/", arg) }}, }) - ice.AddMerges(func(c *ice.Context, key string, cmd *ice.Command, sub string, action *ice.Action) (ice.Handler, ice.Handler) { + ice.AddMerges(func(ctx *ice.Context, key string, cmd *ice.Command, sub string, action *ice.Action) (ice.Handler, ice.Handler) { if strings.HasPrefix(sub, ice.PS) { if sub = kit.Select(sub, PP(key), sub == ice.PS); action.Hand == nil { action.Hand = func(m *ice.Message, arg ...string) { m.Cmdy(key, arg) } } - c.Commands[sub] = &ice.Command{Name: sub, Help: cmd.Help, Hand: action.Hand} + ctx.Commands[sub] = &ice.Command{Name: sub, Help: cmd.Help, Actions: cmd.Actions, Hand: action.Hand} } return nil, nil }) } func ServeAction() ice.Actions { - return ice.Actions{ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { - for sub := range m.Target().Commands[m.CommandKey()].Actions { - if serveActions[sub] == ice.TRUE { - gdb.Watch(m, sub) - } - } - }}} + return gdb.EventsAction(SERVE_START, SERVE_REWRITE, SERVE_PARSE, SERVE_LOGIN, SERVE_CHECK, SERVE_RENDER, SERVE_STOP) } - -var serveActions = kit.DictList(SERVE_START, SERVE_REWRITE, SERVE_PARSE, SERVE_LOGIN, SERVE_CHECK, SERVE_RENDER, SERVE_STOP) diff --git a/base/web/space.go b/base/web/space.go index 52ad2568..ffe0742d 100644 --- a/base/web/space.go +++ b/base/web/space.go @@ -19,8 +19,7 @@ import ( func _space_dial(m *ice.Message, dev, name string, arg ...string) { msg := m.Cmd(SPIDE, dev) - host := msg.Append(kit.Keys(tcp.CLIENT, tcp.HOSTNAME)) - proto := strings.Replace(msg.Append(kit.Keys(tcp.CLIENT, tcp.PROTOCOL)), ice.HTTP, "ws", 1) + proto, host := strings.Replace(msg.Append(kit.Keys(tcp.CLIENT, tcp.PROTOCOL)), ice.HTTP, "ws", 1), msg.Append(kit.Keys(tcp.CLIENT, tcp.HOSTNAME)) uri := kit.ParseURL(kit.MergeURL(proto+"://"+host+PP(SPACE), mdb.TYPE, ice.Info.NodeType, mdb.NAME, name, SHARE, ice.Info.CtxShare, RIVER, ice.Info.CtxRiver, arg)) m.Go(func() { ls := strings.Split(host, ice.DF) @@ -40,10 +39,8 @@ func _space_dial(m *ice.Message, dev, name string, arg ...string) { } }) sleep := time.Duration(rand.Intn(a*(i+1))+b) * time.Millisecond - msg.Cost("order", i, "sleep", sleep, "reconnect", dev) - if time.Sleep(sleep); mdb.HashSelect(msg).Length() == 0 { - break - } + msg.Cost("order", i, "sleep", sleep, "redial", dev) + time.Sleep(sleep) } }) } diff --git a/base/web/web.go b/base/web/web.go index 391888e9..3c5cd72e 100644 --- a/base/web/web.go +++ b/base/web/web.go @@ -55,9 +55,9 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool { func(key string, cmd *ice.Command) { msg.Log(ROUTE, "%s <- %s", c.Name, key) f.HandleFunc(key, func(w http.ResponseWriter, r *http.Request) { - msg.TryCatch(msg.Spawn(), true, func(msg *ice.Message) { _serve_handle(key, cmd, msg, w, r) }) + m.TryCatch(m.Spawn(w, r, c, cmd, key), true, func(msg *ice.Message) { _serve_handle(key, cmd, msg, w, r) }) }) - ice.Info.Route[path.Join(list[c], key)] = ctx.FileURI(cmd.GetFileLine()) + ice.Info.Route[path.Join(list[c], key)] = ctx.FileURI(cmd.GetFileLines()) }(key, cmd) } }) @@ -68,7 +68,7 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool { cb(f) default: m.Cmd(tcp.SERVER, tcp.LISTEN, mdb.TYPE, WEB, m.OptionSimple(mdb.NAME, tcp.HOST, tcp.PORT), func(l net.Listener) { - mdb.HashCreate(m, mdb.NAME, WEB, arg, m.OptionSimple(tcp.PROTO, ice.DEV), cli.STATUS, tcp.START) + mdb.HashCreate(m, m.OptionSimple(mdb.NAME, tcp.PROTO), arg, cli.STATUS, tcp.START) defer mdb.HashModify(m, m.OptionSimple(mdb.NAME), cli.STATUS, tcp.STOP) m.Warn(f.Server.Serve(l)) }) diff --git a/conf.go b/conf.go index 459a1c17..38e4dc71 100644 --- a/conf.go +++ b/conf.go @@ -312,6 +312,7 @@ const ( // mdb ) const ( // ice MDB = "mdb" + GDB = "gdb" AAA = "aaa" CLI = "cli" ) diff --git a/core/chat/favor.go b/core/chat/favor.go index 454c371b..44c31ef0 100644 --- a/core/chat/favor.go +++ b/core/chat/favor.go @@ -81,6 +81,7 @@ func init() { ctx.Run(m, arg...) }}, }, mdb.HashAction(), ctx.CmdAction(), KeyboardAction()), Hand: func(m *ice.Message, arg ...string) { + m.Debug(m.FormatChain()) if len(arg) > 0 && arg[0] == ctx.ACTION { m.Option(mdb.TYPE, m.Cmd("", m.Option(mdb.HASH)).Append(mdb.TYPE)) gdb.Event(m, FAVOR_ACTION, arg) diff --git a/core/chat/header.go b/core/chat/header.go index 9db473c4..3a61376c 100644 --- a/core/chat/header.go +++ b/core/chat/header.go @@ -26,9 +26,6 @@ func _header_share(m *ice.Message, arg ...string) { if m.Warn(m.Option(ice.MSG_USERNAME) == "", ice.ErrNotLogin, "没有登录") { return } - if m.Warn(m.Option(web.SHARE) != "", ice.ErrNotRight, "没有权限") { - return - } for i := 0; i < len(arg)-1; i += 2 { m.Option(arg[i], arg[i+1]) } diff --git a/init.go b/init.go index 2e5de700..62cec7c7 100644 --- a/init.go +++ b/init.go @@ -92,6 +92,14 @@ func Run(arg ...string) string { arg = kit.Simple(os.Args[1:], kit.Split(kit.Env(CTX_ARG))) } Pulse.meta[MSG_DETAIL] = arg + kit.Fetch(kit.Sort(os.Environ()), func(env string) { + if ls := strings.SplitN(env, EQ, 2); strings.ToLower(ls[0]) == ls[0] && ls[0] != "_" { + Pulse.Option(ls[0], ls[1]) + } + }) + if Pulse._cmd == nil { + Pulse._cmd = &Command{RawHand: logs.FileLines(3)} + } switch Index.Merge(Index).Begin(Pulse, arg...); kit.Select("", arg, 0) { case SERVE, SPACE: if Index.Start(Pulse, arg...) { diff --git a/logs.go b/logs.go index d06d3700..e4c58252 100644 --- a/logs.go +++ b/logs.go @@ -5,6 +5,7 @@ import ( "runtime" "strings" "time" + "unicode" kit "shylinux.com/x/toolkits" "shylinux.com/x/toolkits/logs" @@ -75,6 +76,9 @@ func (m *Message) Log(level string, str string, arg ...Any) *Message { } func (m *Message) Logs(level string, arg ...Any) *Message { str, meta := m.join(arg...) + if unicode.IsUpper([]rune(level)[0]) { + meta = []Any{logs.FileLineMeta("")} + } return m.log(level, str, meta...) } @@ -84,8 +88,9 @@ func (m *Message) Auth(arg ...Any) *Message { } func (m *Message) Cost(arg ...Any) *Message { str, meta := m.join(arg...) - if len(arg) == 0 { + if str == "" || len(arg) == 0 { str = kit.Join(m.meta[MSG_DETAIL], SP) + meta = []Any{logs.FileLineMeta(m._fileline())} } list := []string{m.FormatCost(), str} return m.log(LOG_COST, kit.Join(list, SP), meta...) @@ -187,11 +192,12 @@ func (m *Message) FormatChain() string { meta := append([]string{}, NL) for i := len(ms) - 1; i >= 0; i-- { msg := ms[i] - meta = append(meta, kit.Format("%s %s:%d %v %s:%d %v %s:%d %v %s:%d %v", msg.FormatPrefix(), + meta = append(meta, kit.Format("%s %s:%d %v %s:%d %v %s:%d %v %s:%d %v %s", msg.FormatPrefix(), MSG_DETAIL, len(msg.meta[MSG_DETAIL]), msg.meta[MSG_DETAIL], MSG_OPTION, len(msg.meta[MSG_OPTION]), msg.meta[MSG_OPTION], MSG_APPEND, len(msg.meta[MSG_APPEND]), msg.meta[MSG_APPEND], MSG_RESULT, len(msg.meta[MSG_RESULT]), msg.meta[MSG_RESULT], + msg._cmd.GetFileLine(), )) for _, k := range msg.meta[MSG_OPTION] { if v, ok := msg.meta[k]; ok { diff --git a/meta.go b/meta.go index a5c8b45e..b20a89cb 100644 --- a/meta.go +++ b/meta.go @@ -393,6 +393,9 @@ func (m *Message) Detail(arg ...Any) string { return kit.Select("", m.meta[MSG_DETAIL], 0) } func (m *Message) Detailv(arg ...Any) []string { + if len(arg) > 0 { + m.meta[MSG_DETAIL] = kit.Simple(arg...) + } return m.meta[MSG_DETAIL] } func (m *Message) Options(arg ...Any) Any { diff --git a/misc.go b/misc.go index a2621433..e8a06a56 100644 --- a/misc.go +++ b/misc.go @@ -166,17 +166,23 @@ func (m *Message) Design(action Any, help string, input ...Any) { } func (m *Message) _fileline() string { switch m.target.Name { - case MDB, AAA: + case MDB, GDB, AAA: return m._source default: return m._target } } +func (m *Message) ActionHand(cmd *Command, key, sub string, arg ...string) *Message { + if action, ok := cmd.Actions[sub]; !m.Warn(!ok, ErrNotFound, sub, cmd.GetFileLines()) { + return m.Target()._action(m, cmd, key, sub, action, arg...) + } + return m +} func (m *Message) CmdHand(cmd *Command, key string, arg ...string) *Message { if m._key, m._cmd = key, cmd; cmd == nil { return m } - m._target = kit.Join(kit.Slice(kit.Split(cmd.GetFileLine(), PS), -3), PS) + m._target = kit.Join(kit.Slice(kit.Split(cmd.GetFileLines(), PS), -3), PS) if fileline := m._fileline(); key == SELECT { m.Log(LOG_CMDS, "%s.%s %d %v %v", m.Target().Name, key, len(arg), arg, m.Optionv(MSG_FIELDS), logs.FileLineMeta(fileline)) } else { @@ -279,7 +285,7 @@ func (c *Context) _action(m *Message, cmd *Command, key string, sub string, h *A m.Cmdy(kit.Split(h.Name), arg) return m } - if m._sub = sub; len(h.List) > 0 && sub != SEARCH { + if m._key, m._cmd, m._sub = key, cmd, sub; len(h.List) > 0 && sub != SEARCH { order := false for i, v := range h.List { name := kit.Format(kit.Value(v, NAME)) @@ -288,13 +294,17 @@ func (c *Context) _action(m *Message, cmd *Command, key string, sub string, h *A order = true } if order { - m.Option(name, kit.Select(value, arg, i)) - } else { - m.OptionDefault(name, value) + value = kit.Select(value, arg, i) + } + if value != "" { + m.Option(name, value) } } if !order { for i := 0; i < len(arg)-1; i += 2 { + if strings.HasPrefix(arg[i], PS) { + break + } m.Option(arg[i], arg[i+1]) } } diff --git a/misc/vim/tags.go b/misc/vim/tags.go index 717803d6..06c6cfce 100644 --- a/misc/vim/tags.go +++ b/misc/vim/tags.go @@ -99,7 +99,7 @@ func init() { switch args := _tags_split(m.Option(PRE), m.Option(COL)); args[0] { case "field": m.Search(kit.Select(args[1], args, 2), func(key string, cmd *ice.Command) { - ls := kit.Split(cmd.GetFileLine(), ":") + ls := kit.Split(cmd.GetFileLines(), ":") m.Echo("vi +%s %s", ls[1], ls[0]) }) case "qrcode": diff --git a/type.go b/type.go index d16b8cd5..89e86929 100644 --- a/type.go +++ b/type.go @@ -91,7 +91,12 @@ func (c *Context) PrefixKey(arg ...string) string { return kit.Keys(c.Cap(CTX_FOLLOW), arg) } func (c *Command) GetFileLine() string { - if c.RawHand != nil { + return kit.Join(kit.Slice(kit.Split(c.GetFileLines(), PS), -3), PS) +} +func (c *Command) GetFileLines() string { + if c == nil { + return "" + } else if c.RawHand != nil { switch h := c.RawHand.(type) { case string: return h @@ -348,11 +353,11 @@ func (m *Message) Spawn(arg ...Any) *Message { json.Unmarshal(val, &msg.meta) case Option: msg.Option(val.Name, val.Value) - case Map: + case Maps: for k, v := range val { msg.Option(k, v) } - case Maps: + case Map: for k, v := range val { msg.Option(k, v) } @@ -362,6 +367,8 @@ func (m *Message) Spawn(arg ...Any) *Message { msg.R = val case *Context: msg.target = val + case *Command: + msg._cmd = val case string: msg._key = val }