diff --git a/base/aaa/role.go b/base/aaa/role.go index 34a901a2..3765fb02 100644 --- a/base/aaa/role.go +++ b/base/aaa/role.go @@ -133,7 +133,7 @@ func RoleRight(m *ice.Message, role string, key ...string) bool { } func Right(m *ice.Message, key ...ice.Any) bool { return m.Option(ice.MSG_USERROLE) == ROOT || !m.Warn(m.Cmdx(ROLE, RIGHT, m.Option(ice.MSG_USERROLE), key) != ice.OK, - ice.ErrNotRight, kit.Keys(key...), USERROLE, m.Option(ice.MSG_USERROLE), logs.FileLineMeta(logs.FileLine(2))) + ice.ErrNotRight, kit.Keys(key...), USERROLE, m.Option(ice.MSG_USERROLE), logs.FileLineMeta(2)) } func White(m *ice.Message, key ...string) { diff --git a/base/aaa/sess.go b/base/aaa/sess.go index c267489e..2363c7bc 100644 --- a/base/aaa/sess.go +++ b/base/aaa/sess.go @@ -67,9 +67,9 @@ 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("aaa.checker", logs.FileLine(2)) + m.Option("aaa.checker", logs.FileLine(-1)) m.Options(ice.MSG_USERNAME, "", ice.MSG_USERNICK, "", ice.MSG_USERROLE, VOID) - return sessid != "" && m.Cmdy(SESS, CHECK, sessid).Option(ice.MSG_USERNAME) != "" + return sessid != "" && m.Cmdy(SESS, CHECK, sessid, logs.FileLineMeta(-1)).Option(ice.MSG_USERNAME) != "" } func SessAuth(m *ice.Message, value ice.Any, arg ...string) *ice.Message { return m.Auth( diff --git a/base/ctx/command.go b/base/ctx/command.go index 6aecf779..adaaa900 100644 --- a/base/ctx/command.go +++ b/base/ctx/command.go @@ -120,15 +120,16 @@ func Run(m *ice.Message, arg ...string) { } } } - if !PodCmd(m, arg) && aaa.Right(m, arg) { + if Upload(m); !PodCmd(m, arg) && aaa.Right(m, arg) { m.Cmdy(arg) } } + +var Upload = func(*ice.Message) {} + func PodCmd(m *ice.Message, arg ...ice.Any) bool { if pod := m.Option(ice.POD); pod != "" { - if m.Option(ice.POD, ""); len(kit.Simple(m.Optionv(ice.MSG_UPLOAD))) == 1 { - m.Cmdy("cache", "upload").Option(ice.MSG_UPLOAD, m.Append(mdb.HASH), m.Append(mdb.NAME), m.Append(nfs.SIZE)) - } + m.Option(ice.POD, "") m.Cmdy(append(kit.List(ice.SPACE, pod), arg...)...) return true } diff --git a/base/gdb/event.go b/base/gdb/event.go index 8fee16b6..1e4f1286 100644 --- a/base/gdb/event.go +++ b/base/gdb/event.go @@ -13,11 +13,14 @@ const ( ) const EVENT = "event" +var list map[string]int = map[string]int{} + func init() { Index.MergeCommands(ice.Commands{ EVENT: {Name: "event event id auto listen happen", Help: "事件流", Actions: ice.MergeActions(ice.Actions{ LISTEN: {Name: "listen event cmd", Help: "监听", Hand: func(m *ice.Message, arg ...string) { mdb.ZoneInsert(m, m.OptionSimple(EVENT, ice.CMD)) + list[m.Option(EVENT)]++ }}, HAPPEN: {Name: "happen event", Help: "触发", Hand: func(m *ice.Message, arg ...string) { defer m.Cost() @@ -55,7 +58,10 @@ 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, logs.FileLineMeta(logs.FileLine(-1))) + if list[key] == 0 { + return m + } + return m.Cmdy(EVENT, HAPPEN, EVENT, kit.Select(kit.Keys(m.CommandKey(), m.ActionKey()), key), arg, logs.FileLineMeta(-1)) } func EventDeferEvent(m *ice.Message, key string, arg ...ice.Any) func(string, ...ice.Any) { Event(m, key, arg...) diff --git a/base/mdb/hash.go b/base/mdb/hash.go index 4abb589c..fa241b2e 100644 --- a/base/mdb/hash.go +++ b/base/mdb/hash.go @@ -169,7 +169,7 @@ func HashCreate(m *ice.Message, arg ...Any) string { if len(arg) == 0 { arg = append(arg, m.OptionSimple(HashField(m))) } - return m.Echo(m.Cmdx(append(kit.List(INSERT, m.PrefixKey(), "", HASH, logs.FileLineMeta(logs.FileLine(-1))), arg...)...)).Result() + return m.Echo(m.Cmdx(append(kit.List(INSERT, m.PrefixKey(), "", HASH, logs.FileLineMeta(-1)), arg...)...)).Result() } func HashRemove(m *ice.Message, arg ...Any) *ice.Message { if args := kit.Simple(arg); len(args) == 0 { @@ -191,7 +191,7 @@ func HashSelect(m *ice.Message, arg ...string) *ice.Message { } else { m.Fields(len(kit.Slice(arg, 0, 1)), HashField(m)) } - m.Cmdy(SELECT, m.PrefixKey(), "", HASH, HashShort(m), arg) + m.Cmdy(SELECT, m.PrefixKey(), "", HASH, HashShort(m), arg, logs.FileLineMeta(-1)) if m.PushAction(m.Config(ACTION), REMOVE); !m.FieldsIsDetail() { return m.StatusTimeCount() } diff --git a/base/mdb/render.go b/base/mdb/render.go index c56b9307..66cd4880 100644 --- a/base/mdb/render.go +++ b/base/mdb/render.go @@ -27,12 +27,13 @@ func RenderAction(args ...ice.Any) ice.Actions { m.Cmdy(INSERT, m.PrefixKey(), "", HASH, m.OptionSimple(TYPE, NAME, TEXT)) }}, SELECT: {Name: "select type name text auto create", Hand: func(m *ice.Message, arg ...string) { - if len(arg) < 2 || arg[0] == "" || arg[1] == "" { + if len(arg) < 2 || arg[0] == "" { HashSelect(m, arg...) return } for _, k := range kit.Split(arg[0]) { HashSelect(m.Spawn(ice.OptionFields("")), k).Tables(func(value ice.Maps) { + m.Debug("what %v", m.OptionFields()) m.Cmdy(kit.Keys(value[TEXT], value[NAME]), m.CommandKey(), k, arg[1], kit.Select("", arg, 2), kit.Slice(arg, 3)) }) } diff --git a/base/mdb/zone.go b/base/mdb/zone.go index cb48266a..272f41cf 100644 --- a/base/mdb/zone.go +++ b/base/mdb/zone.go @@ -73,7 +73,9 @@ func _zone_export(m *ice.Message, prefix, chain, file string) { defer Lock(m, prefix, chain)() Grows(m, prefix, chain, "", "", func(value ice.Map) { value = kit.GetMeta(value) - w.Write(kit.Simple(head, func(k string) string { return kit.Select(kit.Format(kit.Value(val, k)), kit.Format(kit.Value(value, k))) })) + w.Write(kit.Simple(head, func(k string) string { + return kit.Select(kit.Format(kit.Value(val, k)), kit.Format(kit.Value(value, k))) + })) count++ }) }) @@ -155,7 +157,9 @@ func ZoneKey(m *ice.Message) string { } return ZoneShort(m) } -func ZoneShort(m *ice.Message) string { return kit.Select(ZONE, m.Config(SHORT), m.Config(SHORT) != UNIQ) } +func ZoneShort(m *ice.Message) string { + return kit.Select(ZONE, m.Config(SHORT), m.Config(SHORT) != UNIQ) +} func ZoneField(m *ice.Message) string { return kit.Select(ZONE_FIELD, m.Config(FIELD)) } func ZoneInputs(m *ice.Message, arg ...Any) { m.Cmdy(INPUTS, m.PrefixKey(), "", ZONE, m.Option(ZoneKey(m)), arg) @@ -188,7 +192,7 @@ func ZoneModify(m *ice.Message, arg ...Any) { func ZoneSelect(m *ice.Message, arg ...string) *ice.Message { arg = kit.Slice(arg, 0, 2) m.Fields(len(arg), kit.Select(kit.Fields(TIME, m.Config(SHORT), COUNT), m.Config(FIELDS)), ZoneField(m)) - if m.Cmdy(SELECT, m.PrefixKey(), "", ZONE, arg, logs.FileLineMeta(logs.FileLine(-1))); len(arg) == 0 { + if m.Cmdy(SELECT, m.PrefixKey(), "", ZONE, arg, logs.FileLineMeta(-1)); len(arg) == 0 { m.Sort(ZoneShort(m)).StatusTimeCount().PushAction(m.Config(ACTION), REMOVE) } else if len(arg) == 1 { m.StatusTimeCountTotal(_mdb_getmeta(m, "", kit.Keys(HASH, HashSelectField(m, arg[0], HASH)), COUNT)) diff --git a/base/nfs/dir.go b/base/nfs/dir.go index ceec201c..98db5370 100644 --- a/base/nfs/dir.go +++ b/base/nfs/dir.go @@ -168,8 +168,7 @@ func init() { ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { aaa.White(m, ice.SRC, ice.BIN, ice.USR, ice.USR_PUBLISH, ice.USR_LOCAL_GO) aaa.Black(m, ice.BIN_BOOT_LOG, ice.USR_LOCAL) - }}, - mdb.UPLOAD: {Hand: func(m *ice.Message, arg ...string) { m.Cmdy("web.cache", "upload_watch", m.Option(PATH)) }}, + }}, mdb.UPLOAD: {}, TRASH: {Hand: func(m *ice.Message, arg ...string) { m.Cmd(TRASH, mdb.CREATE, m.Option(PATH)) }}, }, Hand: func(m *ice.Message, arg ...string) { root, dir := kit.Select(PWD, m.Option(DIR_ROOT)), kit.Select(PWD, arg, 0) diff --git a/base/nfs/pack.go b/base/nfs/pack.go index 0db271e1..307b44db 100644 --- a/base/nfs/pack.go +++ b/base/nfs/pack.go @@ -150,8 +150,8 @@ func CloseFile(m *ice.Message, p ice.Any) { } } -func CopyFile(m *ice.Message, to io.WriteCloser, from io.ReadCloser, total int, cb ice.Any) { - size, buf := 0, make([]byte, ice.MOD_BUFS) +func CopyFile(m *ice.Message, to io.WriteCloser, from io.ReadCloser, bufs, total int, cb ice.Any) { + size, buf := 0, make([]byte, bufs) for { n, e := from.Read(buf) to.Write(buf[0:n]) @@ -167,7 +167,7 @@ func CopyFile(m *ice.Message, to io.WriteCloser, from io.ReadCloser, total int, default: m.ErrorNotImplement(cb) } - if m.Warn(e) { + if e == io.EOF || m.Warn(e) { break } } diff --git a/base/web/cache.go b/base/web/cache.go index fe6dfc97..eeefb04f 100644 --- a/base/web/cache.go +++ b/base/web/cache.go @@ -1,67 +1,62 @@ package web import ( + "fmt" "io" "net/http" "os" "path" + "strings" ice "shylinux.com/x/icebergs" + "shylinux.com/x/icebergs/base/ctx" "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/nfs" kit "shylinux.com/x/toolkits" "shylinux.com/x/toolkits/miss" ) -func _cache_name(m *ice.Message, h string) string { - return path.Join(ice.VAR_FILE, h[:2], h) -} -func _cache_type(m *ice.Message, kind, name string) string { - if kind == "application/octet-stream" { +func _cache_name(m *ice.Message, h string) string { return path.Join(ice.VAR_FILE, h[:2], h) } +func _cache_mime(m *ice.Message, mime, name string) string { + if mime == "application/octet-stream" { if kit.ExtIsImage(name) { - kind = "image/"+kit.Ext(name) + mime = "image/" + kit.Ext(name) } else if kit.ExtIsVideo(name) { - kind = "video/"+kit.Ext(name) + mime = "video/" + kit.Ext(name) } + } else if mime == "" { + return kit.Ext(name) } - return kind + return mime } -func _cache_save(m *ice.Message, kind, name, text string, arg ...string) { +func _cache_save(m *ice.Message, mime, name, text string, arg ...string) { if m.Warn(name == "", ice.ErrNotValid, mdb.NAME) { return - } - if len(text) > 512 || kind == nfs.GO { + } else if len(text) > 512 { p := m.Cmdx(nfs.SAVE, _cache_name(m, kit.Hashs(text)), text) text, arg = p, kit.Simple(p, len(text)) } file, size := kit.Select("", arg, 0), kit.Int(kit.Select(kit.Format(len(text)), arg, 1)) - kind, text = _cache_type(m, kind, name), kit.Select(file, text) - h := mdb.HashCreate(m, kit.SimpleKV("", kind, name, text), nfs.FILE, file, nfs.SIZE, size) - m.Push(mdb.TIME, m.Time()) - m.Push(mdb.TYPE, kind) - m.Push(mdb.NAME, name) - m.Push(mdb.TEXT, text) - m.Push(nfs.FILE, file) - m.Push(nfs.SIZE, size) - m.Push(mdb.HASH, h) - m.Push(mdb.DATA, h) + mime, text = _cache_mime(m, mime, name), kit.Select(file, text) + m.Push(mdb.TIME, m.Time()).Push(mdb.HASH, mdb.HashCreate(m.Spawn(), kit.SimpleKV("", mime, name, text), nfs.FILE, file, nfs.SIZE, size)) + m.Push(mdb.TYPE, mime).Push(mdb.NAME, name).Push(mdb.TEXT, text).Push(nfs.FILE, file).Push(nfs.SIZE, size) } -func _cache_watch(m *ice.Message, key, file string) { +func _cache_watch(m *ice.Message, key, path string) { mdb.HashSelect(m.Spawn(), key).Tables(func(value ice.Maps) { if value[nfs.FILE] == "" { - m.Cmdy(nfs.SAVE, file, value[mdb.TEXT]) + m.Cmdy(nfs.SAVE, path, value[mdb.TEXT]) } else { - m.Cmdy(nfs.LINK, file, value[nfs.FILE]) + m.Cmdy(nfs.LINK, path, value[nfs.FILE]) } }) } -func _cache_catch(m *ice.Message, name string) (file, size string) { - if msg := m.Cmd(nfs.DIR, name, "hash,size"); msg.Length() > 0 { - return m.Cmdx(nfs.LINK, _cache_name(m, msg.Append(mdb.HASH)), name), msg.Append(nfs.SIZE) +func _cache_catch(m *ice.Message, path string) (file string, size string) { + if msg := m.Cmd(nfs.DIR, path, "hash,size"); msg.Length() > 0 { + return m.Cmdx(nfs.LINK, _cache_name(m, msg.Append(mdb.HASH)), path), msg.Append(nfs.SIZE) } return "", "0" } -func _cache_upload(m *ice.Message, r *http.Request) (kind, name, file, size string) { +func _cache_upload(m *ice.Message, r *http.Request) (mime, name, file, size string) { if b, h, e := r.FormFile(UPLOAD); !m.Warn(e, ice.ErrNotValid, UPLOAD) { defer b.Close() if f, p, e := miss.CreateFile(_cache_name(m, kit.Hashs(b))); !m.Warn(e, ice.ErrNotValid, UPLOAD) { @@ -75,11 +70,20 @@ func _cache_upload(m *ice.Message, r *http.Request) (kind, name, file, size stri } return "", "", "", "0" } -func _cache_download(m *ice.Message, r *http.Response, file string) string { +func _cache_download(m *ice.Message, r *http.Response, file string, cb ice.Any) string { defer r.Body.Close() - if f, p, e := miss.CreateFile(file); m.Warn(e, ice.ErrNotValid, DOWNLOAD) { + if f, p, e := miss.CreateFile(file); !m.Warn(e, ice.ErrNotValid, DOWNLOAD) { defer f.Close() - nfs.CopyFile(m, f, r.Body, kit.Int(kit.Select("100", r.Header.Get(ContentLength))), m.OptionCB(SPIDE)) + last, step, bufs := 0, 10, 40960 + if cb == nil { + cb = func(size, total, count int) { + if count/step != last { + m.Logs(mdb.EXPORT, nfs.FILE, p, nfs.SIZE, size, mdb.TOTAL, total, mdb.COUNT, count) + } + last = count / step + } + } + nfs.CopyFile(m, f, r.Body, bufs, kit.Int(kit.Select("100", r.Header.Get(ContentLength))), cb) return p } return "" @@ -92,80 +96,91 @@ const ( UPLOAD = "upload" DOWNLOAD = "download" DISPLAY = "display" - - UPLOAD_WATCH = "upload_watch" ) const CACHE = "cache" func init() { Index.MergeCommands(ice.Commands{ - CACHE: {Name: "cache hash auto", Help: "缓存池", Actions: ice.MergeActions(ice.Actions{ - WATCH: {Name: "watch key file", Help: "释放", Hand: func(m *ice.Message, arg ...string) { - _cache_watch(m, arg[0], arg[1]) + CACHE: {Name: "cache hash auto write catch upload", Help: "缓存池", Actions: ice.MergeActions(ice.Actions{ + WATCH: {Name: "watch hash* path*", Help: "释放", Hand: func(m *ice.Message, arg ...string) { + _cache_watch(m, m.Option(mdb.HASH), m.Option(nfs.PATH)) }}, - CATCH: {Name: "catch type name", Help: "捕获", Hand: func(m *ice.Message, arg ...string) { - file, size := _cache_catch(m, arg[1]) - _cache_save(m, arg[0], arg[1], "", file, size) + WRITE: {Name: "write type name* text*", Help: "创建", Hand: func(m *ice.Message, arg ...string) { + _cache_save(m, m.Option(mdb.TYPE), m.Option(mdb.NAME), m.Option(mdb.TEXT)) }}, - WRITE: {Name: "write type name text", Help: "添加", Hand: func(m *ice.Message, arg ...string) { - _cache_save(m, arg[0], arg[1], arg[2]) + CATCH: {Name: "catch path* type", Help: "添加", Hand: func(m *ice.Message, arg ...string) { + file, size := _cache_catch(m, m.Option(nfs.PATH)) + _cache_save(m, m.Option(mdb.TYPE), m.Option(nfs.PATH), "", file, size) }}, - UPLOAD: {Name: "upload", Help: "上传", Hand: func(m *ice.Message, arg ...string) { - kind, name, file, size := _cache_upload(m, m.R) - _cache_save(m, kind, name, "", file, size) + UPLOAD: {Hand: func(m *ice.Message, arg ...string) { + mime, name, file, size := _cache_upload(m, m.R) + _cache_save(m, mime, name, "", file, size) }}, - DOWNLOAD: {Name: "download type name", Help: "下载", Hand: func(m *ice.Message, arg ...string) { - if r, ok := m.Optionv(RESPONSE).(*http.Response); ok { - file, size := _cache_catch(m, _cache_download(m, r, path.Join(ice.VAR_TMP, kit.Hashs(mdb.UNIQ)))) - _cache_save(m, arg[0], arg[1], "", file, size) + DOWNLOAD: {Name: "download type name*", Hand: func(m *ice.Message, arg ...string) { + if r, ok := m.Optionv(RESPONSE).(*http.Response); !m.Warn(!ok, ice.ErrNotValid, RESPONSE) { + file, size := _cache_catch(m, _cache_download(m, r, path.Join(ice.VAR_TMP, kit.Hashs(mdb.UNIQ)), nil)) + _cache_save(m, m.Option(mdb.TYPE), m.Option(mdb.NAME), "", file, size) } }}, - UPLOAD_WATCH: {Name: "upload_watch", Help: "上传", Hand: func(m *ice.Message, arg ...string) { - up := kit.Simple(m.Optionv(ice.MSG_UPLOAD)) - if len(up) < 2 { - msg := m.Cmd(CACHE, UPLOAD) - up = kit.Simple(msg.Append(mdb.HASH), msg.Append(mdb.NAME), msg.Append(nfs.SIZE)) - } - if p := path.Join(arg[0], up[1]); m.Option(ice.MSG_USERPOD) == "" { - m.Cmdy(CACHE, WATCH, up[0], p) - } else { - m.Cmdy(SPIDE, ice.DEV, nfs.SAVE, p, SPIDE_GET, MergeURL2(m, path.Join(SHARE_CACHE, up[0]))) - } + ice.RENDER_DOWNLOAD: {Hand: func(m *ice.Message, arg ...string) { + p := kit.Select(arg[0], arg, 1) + p = kit.Select("", SHARE_LOCAL, !strings.HasPrefix(p, ice.PS) && !strings.HasPrefix(p, ice.HTTP)) + p + args := []string{ice.POD, m.Option(ice.MSG_USERPOD), "filename", kit.Select("", arg[0], len(arg) > 1)} + m.Echo(fmt.Sprintf(`%s`, MergeURL2(m, p, args), path.Base(arg[0]), arg[0])) }}, - }, mdb.HashAction(mdb.SHORT, mdb.TEXT, mdb.FIELD, "time,hash,size,type,name,text,file")), Hand: func(m *ice.Message, arg ...string) { - if mdb.HashSelect(m, arg...); len(arg) == 0 { + ice.PS: {Hand: func(m *ice.Message, arg ...string) { + mdb.HashSelectDetail(m, arg[0], func(value ice.Map) { + if kit.Format(value[nfs.FILE]) == "" { + m.RenderResult(value[mdb.TEXT]) + } else { + m.RenderDownload(value[nfs.FILE]) + } + }) + }}, + }, mdb.HashAction(mdb.SHORT, mdb.TEXT, mdb.FIELD, "time,hash,size,type,name,text,file", ctx.ACTION, WATCH), ice.RenderAction(ice.RENDER_DOWNLOAD)), Hand: func(m *ice.Message, arg ...string) { + if mdb.HashSelect(m, arg...); len(arg) == 0 || m.R.Method == http.MethodGet { return } if m.Append(nfs.FILE) == "" { - m.PushScript("inner", m.Append(mdb.TEXT)) + m.PushScript(mdb.TEXT, m.Append(mdb.TEXT)) } else { - m.PushDownload(m.Append(mdb.NAME), MergeURL2(m, SHARE_CACHE+arg[0])) + PushDisplay(m, m.Append(mdb.TYPE), m.Append(mdb.NAME), MergeURL2(m, SHARE_CACHE+arg[0])) } }}, - PP(CACHE): {Name: "/cache/", Help: "缓存池", Hand: func(m *ice.Message, arg ...string) { - mdb.HashSelectDetail(m, arg[0], func(value ice.Map) { - if kit.Format(value[nfs.FILE]) == "" { - m.RenderResult(value[mdb.TEXT]) - } else { - m.RenderDownload(value[nfs.FILE]) - } - }) - }}, }) ice.AddMerges(func(c *ice.Context, key string, cmd *ice.Command, sub string, action *ice.Action) (ice.Handler, ice.Handler) { switch sub { case UPLOAD: - if key == CACHE { + if c.Name == WEB && key == CACHE { break } - hand := action.Hand - action.Hand = func(m *ice.Message, arg ...string) { - if len(kit.Simple(m.Optionv(ice.MSG_UPLOAD))) == 1 { - m.Cmdy(CACHE, UPLOAD) + watch := action.Hand == nil + action.Hand = ice.MergeHand(func(m *ice.Message, arg ...string) { + up := kit.Simple(m.Optionv(ice.MSG_UPLOAD)) + m.Assert(len(up) > 1) + m.Cmd(CACHE, m.Option(ice.MSG_UPLOAD)).Tables(func(value ice.Maps) { m.Options(value) }) + if m.Options(mdb.HASH, up[0], mdb.NAME, up[1]); watch { + m.Cmdy(CACHE, WATCH, m.Option(mdb.HASH), path.Join(m.Option(nfs.PATH), m.Option(mdb.NAME))) } - hand(m, arg...) - } + }, action.Hand) } return nil, nil }) + ctx.Upload = Upload +} +func Upload(m *ice.Message) { + if up := kit.Simple(m.Optionv(ice.MSG_UPLOAD)); len(up) == 1 { + if m.Cmdy(CACHE, UPLOAD).Optionv(ice.MSG_UPLOAD, kit.Simple(m.Append(mdb.HASH), m.Append(mdb.NAME), m.Append(nfs.SIZE))); m.Option(ice.MSG_USERPOD) != "" { + m.Cmd(SPACE, m.Option(ice.MSG_USERPOD), SPIDE, ice.DEV, SPIDE_CACHE, http.MethodGet, MergeURL2(m, path.Join(SHARE_CACHE, m.Append(mdb.HASH)))) + } + } +} +func PushDisplay(m *ice.Message, mime, name, link string) { + if strings.HasPrefix(mime, "image/") || kit.ExtIsImage(name) { + m.PushImages(nfs.FILE, link) + } else if strings.HasPrefix(mime, "video/") || kit.ExtIsImage(name) { + m.PushVideos(nfs.FILE, link) + } else { + m.PushDownload(nfs.FILE, name, link) + } } diff --git a/base/web/option.go b/base/web/option.go index e57237da..a0f74332 100644 --- a/base/web/option.go +++ b/base/web/option.go @@ -12,18 +12,11 @@ import ( "shylinux.com/x/icebergs/base/ctx" "shylinux.com/x/icebergs/base/gdb" "shylinux.com/x/icebergs/base/mdb" - "shylinux.com/x/icebergs/base/nfs" "shylinux.com/x/icebergs/base/tcp" kit "shylinux.com/x/toolkits" "shylinux.com/x/toolkits/file" ) -func Upload(m *ice.Message) *ice.Message { - if len(kit.Simple(m.Optionv(ice.MSG_UPLOAD))) == 1 { - m.Cmdy(CACHE, UPLOAD).Option(ice.MSG_UPLOAD, m.Append(mdb.HASH), m.Append(mdb.NAME), m.Append(nfs.SIZE)) - } - return m -} func PushNotice(m *ice.Message, arg ...ice.Any) { if m.Option(ice.MSG_DAEMON) == "" { return diff --git a/base/web/route.go b/base/web/route.go deleted file mode 100644 index 56132f79..00000000 --- a/base/web/route.go +++ /dev/null @@ -1,112 +0,0 @@ -package web - -import ( - ice "shylinux.com/x/icebergs" - "shylinux.com/x/icebergs/base/aaa" - "shylinux.com/x/icebergs/base/cli" - "shylinux.com/x/icebergs/base/ctx" - "shylinux.com/x/icebergs/base/lex" - "shylinux.com/x/icebergs/base/mdb" - "shylinux.com/x/icebergs/base/tcp" - kit "shylinux.com/x/toolkits" -) - -func _route_travel(m *ice.Message, route string) { - m.Cmd(SPACE, func(val ice.Maps) { - switch val[mdb.TYPE] { - case SERVER: // 远程查询 - if val[mdb.NAME] == ice.Info.NodeName { - return // 避免循环 - } - - m.Cmd(SPACE, val[mdb.NAME], ROUTE, func(value ice.Maps) { - m.Push(mdb.TYPE, value[mdb.TYPE]) - m.Push(ROUTE, kit.Keys(val[mdb.NAME], value[ROUTE])) - }) - fallthrough - case WORKER: // 本机查询 - m.Push(mdb.TYPE, val[mdb.TYPE]) - m.Push(ROUTE, val[mdb.NAME]) - } - }) -} -func _route_list(m *ice.Message) *ice.Message { - m.Tables(func(value ice.Maps) { - switch m.PushAnchor(value[ROUTE], MergePod(m, value[ROUTE])); value[mdb.TYPE] { - case SERVER: - m.PushButton(tcp.START, aaa.INVITE) - case WORKER: - fallthrough - default: - m.PushButton("") - } - }) - - // 网卡信息 - u := OptionUserWeb(m) - m.Cmd(tcp.HOST, func(value ice.Maps) { - m.Push(mdb.TYPE, MYSELF) - m.Push(ROUTE, ice.Info.NodeName) - m.PushAnchor(value[aaa.IP], kit.Format("%s://%s:%s", u.Scheme, value[aaa.IP], u.Port())) - m.PushButton(tcp.START) - }) - - // 本机信息 - m.Push(mdb.TYPE, MYSELF) - m.Push(ROUTE, ice.Info.NodeName) - m.PushAnchor(tcp.LOCALHOST, kit.Format("%s://%s:%s", u.Scheme, tcp.LOCALHOST, u.Port())) - m.PushButton(tcp.START) - return m -} - -const ROUTE = "route" - -func init() { - Index.MergeCommands(ice.Commands{ - ROUTE: {Name: "route route index auto invite spide", Help: "路由器", Actions: ice.Actions{ - aaa.INVITE: {Name: "invite", Help: "添加", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(SPACE, m.Option(ROUTE), SPACE, aaa.INVITE, arg).ProcessInner() - }}, - cli.START: {Name: "start name repos template", Help: "启动", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(SPACE, m.Option(ROUTE), DREAM, tcp.START, arg).ProcessInner() - }}, - ctx.COMMAND: {Name: "command", Help: "命令", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(SPACE, m.Option(ROUTE), m.Option(ctx.INDEX), arg) - }}, - ice.RUN: {Name: "run", Help: "执行", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(SPACE, m.Option(ROUTE), arg) - }}, - SPIDE: {Name: "spide", Help: "架构图", Hand: func(m *ice.Message, arg ...string) { - if m.Option(ROUTE) == "" { // 路由列表 route - ctx.DisplayStorySpide(m, lex.PREFIX, SPIDE, lex.SPLIT, ice.PT) - m.Cmdy(ROUTE).Cut(ROUTE) - - } else if m.Option(ctx.CONTEXT) == "" { // 模块列表 context - m.Cmdy(SPACE, m.Option(ROUTE), ctx.CONTEXT, ice.ICE, ctx.CONTEXT).Cut(mdb.NAME).RenameAppend(mdb.NAME, ctx.CONTEXT) - m.Option(lex.SPLIT, ice.PT) - - } else if m.Option(mdb.NAME) == "" { // 命令列表 name - m.Cmdy(SPACE, m.Option(ROUTE), ctx.CONTEXT, SPIDE, "", m.Option(ctx.CONTEXT), m.Option(ctx.CONTEXT)).Cut(mdb.NAME) - - } else { // 命令详情 index name help meta list - m.Cmdy(SPACE, m.Option(ROUTE), ctx.CONTEXT, SPIDE, "", m.Option(ctx.CONTEXT), m.Option(mdb.NAME)) - } - }}, - }, Hand: func(m *ice.Message, arg ...string) { - if len(arg) == 0 || arg[0] == "" { // 路由列表 - if _route_travel(m, kit.Select("", arg, 0)); m.W != nil { - _route_list(m).Sort("type,route") - } - - } else if len(arg) == 1 || arg[1] == "" { // 模块列表 - m.Cmd(SPACE, arg[0], ctx.COMMAND, mdb.SEARCH, ctx.COMMAND, ice.OptionFields(ctx.INDEX, mdb.NAME, mdb.HELP)).Table(func(index int, value ice.Maps, head []string) { - m.Push("", value, head) - }) - - } else { // 命令详情 - m.Cmdy(SPACE, arg[0], ctx.COMMAND, arg[1]) - m.ProcessField(ctx.ACTION, ctx.COMMAND) - } - }}, - }) -} diff --git a/base/web/serve.go b/base/web/serve.go index cd609da1..2b2a4526 100644 --- a/base/web/serve.go +++ b/base/web/serve.go @@ -56,10 +56,12 @@ func _serve_main(m *ice.Message, w http.ResponseWriter, r *http.Request) bool { 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)) - 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 + if r.Method == http.MethodGet { + 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 } @@ -106,7 +108,6 @@ func _serve_handle(key string, cmd *ice.Command, m *ice.Message, w http.Response m.CmdHand(cmd, key, cmds...) } } - 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 { @@ -227,12 +228,20 @@ func init() { m.Cmdy("web.chat./cmd/", arg) }}, }) - ice.AddMerges(func(ctx *ice.Context, key string, cmd *ice.Command, sub string, action *ice.Action) (ice.Handler, ice.Handler) { + ice.AddMerges(func(c *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) } } - ctx.Commands[sub] = &ice.Command{Name: sub, Help: cmd.Help, Actions: cmd.Actions, Hand: action.Hand} + // c.Commands[sub] = &ice.Command{Name: sub, Help: cmd.Help, Actions: cmd.Actions, Hand: action.Hand} + actions := ice.Actions{} + for k, v := range cmd.Actions { + switch k { + case ctx.COMMAND, ice.RUN: + actions[k] = v + } + } + c.Commands[sub] = &ice.Command{Name: sub, Help: cmd.Help, Actions: actions, Hand: action.Hand} } return nil, nil }) diff --git a/base/web/share.go b/base/web/share.go index 96c35079..e18ceaa7 100644 --- a/base/web/share.go +++ b/base/web/share.go @@ -1,7 +1,6 @@ package web import ( - "fmt" "net/http" "path" "strings" @@ -19,16 +18,8 @@ import ( "shylinux.com/x/toolkits/logs" ) -func _share_render(m *ice.Message, arg ...string) { - ice.AddRender(ice.RENDER_DOWNLOAD, func(msg *ice.Message, arg ...ice.Any) string { - args := kit.Simple(arg...) - list := []string{ice.POD, msg.Option(ice.MSG_USERPOD), "filename", kit.Select("", args[0], len(args) > 1)} - return fmt.Sprintf(`%s`, _share_link(msg, kit.Select(args[0], args, 1), list), path.Base(args[0]), args[0]) - }) -} -func _share_link(m *ice.Message, p string, arg ...ice.Any) string { - p = kit.Select("", SHARE_LOCAL, !strings.HasPrefix(p, ice.PS) && !strings.HasPrefix(p, ice.HTTP)) + p - return tcp.PublishLocalhost(m, MergeLink(m, p, arg...)) +func _share_link(m *ice.Message, p string) string { + return tcp.PublishLocalhost(m, MergeLink(m, kit.Select("", SHARE_LOCAL, !strings.HasPrefix(p, ice.PS) && !strings.HasPrefix(p, ice.HTTP))+p)) } func _share_cache(m *ice.Message, arg ...string) { if pod := m.Option(ice.POD); ctx.PodCmd(m, CACHE, arg[0]) { @@ -39,8 +30,11 @@ func _share_cache(m *ice.Message, arg ...string) { _share_local(m, m.Append(nfs.FILE)) } } else { - msg := m.Cmd(CACHE, arg[0]) - m.RenderDownload(msg.Append(nfs.FILE), msg.Append(mdb.TYPE), msg.Append(mdb.NAME)) + if m.Cmdy(CACHE, arg[0]); m.Append(nfs.FILE) == "" { + m.RenderResult(m.Append(mdb.TEXT)) + } else { + m.RenderDownload(m.Append(nfs.FILE), m.Append(mdb.TYPE), m.Append(mdb.NAME)) + } } } func _share_local(m *ice.Message, arg ...string) { @@ -65,11 +59,9 @@ func _share_local(m *ice.Message, arg ...string) { cache, size = s.ModTime(), s.Size() } if p == ice.BIN_ICE_BIN { - aaa.UserRoot(m).Cmd(SPACE, m.Option(ice.POD), SPIDE, "submit", MergeURL2(m, SHARE_PROXY, nfs.PATH, ""), m.Option(ice.POD), p, size, cache.Format(ice.MOD_TIME)) - } else { - m.Cmd(SPACE, m.Option(ice.POD), SPIDE, ice.DEV, SPIDE_RAW, MergeURL2(m, SHARE_PROXY, nfs.PATH, ""), - SPIDE_PART, m.OptionSimple(ice.POD), nfs.PATH, p, nfs.SIZE, size, CACHE, cache.Format(ice.MOD_TIME), UPLOAD, "@"+p) + m.Option(ice.MSG_USERROLE, aaa.TECH) } + m.Cmd(SPACE, m.Option(ice.POD), SPIDE, ice.DEV, SPIDE_RAW, MergeLink(m, SHARE_PROXY), SPIDE_PART, m.OptionSimple(ice.POD), nfs.PATH, p, nfs.SIZE, size, CACHE, cache.Format(ice.MOD_TIME), UPLOAD, "@"+p) if !m.Warn(!file.ExistsFile(pp), ice.ErrNotFound, pp) { m.RenderDownload(pp) } @@ -77,10 +69,11 @@ func _share_local(m *ice.Message, arg ...string) { func _share_proxy(m *ice.Message) { switch p := path.Join(ice.VAR_PROXY, m.Option(ice.POD), m.Option(nfs.PATH)); m.R.Method { case http.MethodGet: - m.RenderDownload(path.Join(p, m.Option(mdb.NAME))) + m.RenderDownload(p, m.Option(mdb.TYPE), m.Option(mdb.NAME)) case http.MethodPost: - m.Cmdy(CACHE, UPLOAD) - m.Cmdy(CACHE, WATCH, m.Option(mdb.DATA), p) + if _, _, e := m.R.FormFile(UPLOAD); e == nil { + m.Cmdy(CACHE, UPLOAD).Cmdy(CACHE, WATCH, m.Option(mdb.HASH), p) + } m.RenderResult(m.Option(nfs.PATH)) } } @@ -92,11 +85,10 @@ const ( STORM = "storm" FIELD = "field" - SHARE_TOAST = "/share/toast/" SHARE_CACHE = "/share/cache/" SHARE_LOCAL = "/share/local/" SHARE_PROXY = "/share/proxy/" - SHARE_REPOS = "/share/repos/" + SHARE_TOAST = "/share/toast/" SHARE_LOCAL_AVATAR = "/share/local/avatar/" SHARE_LOCAL_BACKGROUND = "/share/local/background/" @@ -105,24 +97,17 @@ const SHARE = "share" func init() { Index.MergeCommands(ice.Commands{ - SHARE: {Name: "share hash auto prunes", Help: "共享链", Actions: ice.MergeActions(ice.Actions{ - ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { _share_render(m) }}, + SHARE: {Name: "share hash auto login prunes", Help: "共享链", Actions: ice.MergeActions(ice.Actions{ mdb.CREATE: {Name: "create type name text", Hand: func(m *ice.Message, arg ...string) { mdb.HashCreate(m, arg, aaa.USERNAME, m.Option(ice.MSG_USERNAME), aaa.USERNICK, m.Option(ice.MSG_USERNICK), aaa.USERROLE, m.Option(ice.MSG_USERROLE)) - m.Option(mdb.LINK, _share_link(m, PP(SHARE)+m.Result())) + m.Option(mdb.LINK, _share_link(m, P(SHARE, m.Result()))) }}, - LOGIN: {Name: "login userrole=void,tech username", Hand: func(m *ice.Message, arg ...string) { + LOGIN: {Hand: func(m *ice.Message, arg ...string) { m.EchoQRCode(m.Cmd(SHARE, mdb.CREATE, mdb.TYPE, LOGIN).Option(mdb.LINK)).ProcessInner() }}, SERVE_PARSE: {Hand: func(m *ice.Message, arg ...string) { - if kit.Select("", arg, 0) != SHARE { - return - } - switch arg[1] { - case "local": - default: - m.Logs("Refer", arg[0], arg[1]) - m.Option(arg[0], arg[1]) + if kit.Select("", arg, 0) == SHARE { + m.Logs("Refer", arg[0], arg[1]).Option(arg[0], arg[1]) } }}, SERVE_LOGIN: {Hand: func(m *ice.Message, arg ...string) { @@ -133,6 +118,23 @@ func init() { } } }}, + ice.PS: {Hand: func(m *ice.Message, arg ...string) { + if m.Warn(len(arg) == 0 || arg[0] == "", ice.ErrNotValid, SHARE) { + return + } + msg := m.Cmd(SHARE, m.Option(SHARE, arg[0])) + if IsNotValidShare(m, msg.Append(mdb.TIME)) { + m.RenderResult(kit.Format("共享超时, 请联系 %s(%s), 重新分享 %s %s", + msg.Append(aaa.USERNAME), msg.Append(aaa.USERNICK), msg.Append(mdb.TYPE), msg.Append(mdb.NAME))) + return + } + switch msg.Append(mdb.TYPE) { + case LOGIN: + m.RenderRedirect(ice.PS, ice.MSG_SESSID, aaa.SessCreate(m, msg.Append(aaa.USERNAME))) + default: + RenderIndex(m, "") + } + }}, }, mdb.HashAction(mdb.FIELD, "time,hash,username,usernick,userrole,river,storm,type,name,text", mdb.EXPIRE, "72h"), ServeAction(), aaa.WhiteAction()), Hand: func(m *ice.Message, arg ...string) { if ctx.PodCmd(m, SHARE, arg) { return @@ -142,45 +144,20 @@ func init() { m.PushQRCode(cli.QRCODE, link) m.PushScript(nfs.SCRIPT, link) m.PushAnchor(link) - } else { - m.Action(LOGIN) } }}, - PP(SHARE): {Name: "/share/", Help: "共享链", Hand: func(m *ice.Message, arg ...string) { - msg := m.Cmd(SHARE, m.Option(SHARE, kit.Select(m.Option(SHARE), arg, 0))) - if IsNotValidShare(m, msg.Append(mdb.TIME)) { - m.RenderResult(kit.Format("共享超时, 请联系 %s(%s), 重新分享 %s %s", - msg.Append(aaa.USERNAME), msg.Append(aaa.USERNICK), msg.Append(mdb.TYPE), msg.Append(mdb.NAME))) - return - } - switch msg.Append(mdb.TYPE) { - case LOGIN: - m.RenderRedirect(ice.PS, ice.MSG_SESSID, aaa.SessCreate(m, msg.Append(aaa.USERNAME))) - default: - RenderIndex(m, ice.VOLCANOS) - } - }}, - SHARE_TOAST: {Name: "/share/toast/", Help: "推送流", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(SPACE, m.Option(ice.POD), m.Optionv("cmds")) - }}, - SHARE_CACHE: {Name: "/share/cache/", Help: "缓存池", Hand: func(m *ice.Message, arg ...string) { - _share_cache(m, arg...) - }}, - SHARE_LOCAL: {Name: "/share/local/", Help: "文件夹", Hand: func(m *ice.Message, arg ...string) { - _share_local(m, arg...) - }}, - SHARE_LOCAL_AVATAR: {Name: "avatar", Help: "头像", Hand: func(m *ice.Message, arg ...string) { + SHARE_CACHE: {Hand: func(m *ice.Message, arg ...string) { _share_cache(m, arg...) }}, + SHARE_LOCAL: {Hand: func(m *ice.Message, arg ...string) { _share_local(m, arg...) }}, + SHARE_LOCAL_AVATAR: {Hand: func(m *ice.Message, arg ...string) { m.RenderDownload(strings.TrimPrefix(m.CmdAppend(aaa.USER, m.Option(ice.MSG_USERNAME), aaa.AVATAR), SHARE_LOCAL)) }}, - SHARE_LOCAL_BACKGROUND: {Name: "background", Help: "背景", Hand: func(m *ice.Message, arg ...string) { + SHARE_LOCAL_BACKGROUND: {Hand: func(m *ice.Message, arg ...string) { m.RenderDownload(strings.TrimPrefix(m.CmdAppend(aaa.USER, m.Option(ice.MSG_USERNAME), aaa.BACKGROUND), SHARE_LOCAL)) }}, - SHARE_PROXY: {Name: "/share/proxy/", Help: "文件流", Hand: func(m *ice.Message, arg ...string) { - _share_proxy(m) - }}, + SHARE_PROXY: {Hand: func(m *ice.Message, arg ...string) { _share_proxy(m) }}, + SHARE_TOAST: {Hand: func(m *ice.Message, arg ...string) { m.Cmdy(SPACE, m.Option(ice.POD), m.Optionv("cmds")) }}, }) } - func IsNotValidShare(m *ice.Message, time string) bool { return m.Warn(time < m.Time(), ice.ErrNotValid, m.Option(SHARE), time, m.Time(), logs.FileLineMeta(2)) } diff --git a/base/web/space.go b/base/web/space.go index cbe2a307..f1acbe75 100644 --- a/base/web/space.go +++ b/base/web/space.go @@ -9,6 +9,7 @@ import ( ice "shylinux.com/x/icebergs" "shylinux.com/x/icebergs/base/aaa" "shylinux.com/x/icebergs/base/cli" + "shylinux.com/x/icebergs/base/ctx" "shylinux.com/x/icebergs/base/gdb" "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/tcp" @@ -178,8 +179,9 @@ func init() { aaa.SessAuth(m, kit.Dict(aaa.USERNAME, m.Option(ice.MSG_USERNAME), aaa.USERNICK, m.Option(ice.MSG_USERNICK), aaa.USERROLE, m.Option(ice.MSG_USERROLE))) }}, DOMAIN: {Hand: func(m *ice.Message, arg ...string) { m.Echo(_space_domain(m)) }}, + OPEN: {Hand: func(m *ice.Message, arg ...string) { ctx.ProcessOpen(m, MergePod(m, m.Option(mdb.NAME), arg)) }}, ice.PS: {Hand: func(m *ice.Message, arg ...string) { _space_fork(m) }}, - }, mdb.HashAction(mdb.SHORT, mdb.NAME, mdb.FIELD, "time,type,name,text", + }, mdb.HashAction(mdb.SHORT, mdb.NAME, mdb.FIELD, "time,type,name,text", ctx.ACTION, OPEN, REDIAL, kit.Dict("a", 3000, "b", 1000, "c", 1000), TIMEOUT, kit.Dict("c", "30s"), BUFFER, kit.Dict("r", ice.MOD_BUFS, "w", ice.MOD_BUFS), ), mdb.ClearHashOnExitAction(), SpaceAction(), aaa.WhiteAction()), Hand: func(m *ice.Message, arg ...string) { @@ -224,5 +226,9 @@ func back(m *ice.Message, res *ice.Message) bool { } return false } -func addSend(m *ice.Message, msg *ice.Message) string { return m.Target().Server().(*Frame).addSend(kit.Format(m.Target().ID()), msg) } -func getSend(m *ice.Message, key string) *ice.Message { return m.Target().Server().(*Frame).getSend(key) } +func addSend(m *ice.Message, msg *ice.Message) string { + return m.Target().Server().(*Frame).addSend(kit.Format(m.Target().ID()), msg) +} +func getSend(m *ice.Message, key string) *ice.Message { + return m.Target().Server().(*Frame).getSend(key) +} diff --git a/base/web/spide.go b/base/web/spide.go index 5a822393..fdd34cb9 100644 --- a/base/web/spide.go +++ b/base/web/spide.go @@ -13,7 +13,6 @@ import ( "time" ice "shylinux.com/x/icebergs" - "shylinux.com/x/icebergs/base/aaa" "shylinux.com/x/icebergs/base/cli" "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/nfs" @@ -22,8 +21,7 @@ import ( ) func _spide_create(m *ice.Message, name, address string) { - // if uri, e := url.Parse(address); !m.Warn(e != nil || address == "", address) { - if uri, e := url.Parse(address); m.Assert(e == nil) { + if uri, e := url.Parse(address); !m.Warn(e != nil || address == "", address) { m.Logs(mdb.CREATE, SPIDE, name, ADDRESS, address) dir, file := path.Split(uri.EscapedPath()) mdb.HashCreate(m, CLIENT_NAME, name) @@ -37,15 +35,14 @@ func _spide_create(m *ice.Message, name, address string) { }) } } -func _spide_list(m *ice.Message, arg ...string) { +func _spide_show(m *ice.Message, arg ...string) { msg := mdb.HashSelects(m.Spawn(), arg[0]) if len(arg) == 2 && msg.Append(arg[1]) != "" { m.Echo(msg.Append(arg[1])) return } - cache, save := "", "" - switch arg[1] { // 缓存方法 + switch arg[1] { case SPIDE_RAW: cache, arg = arg[1], arg[1:] case SPIDE_MSG: @@ -55,9 +52,8 @@ func _spide_list(m *ice.Message, arg ...string) { case SPIDE_CACHE: cache, arg = arg[1], arg[1:] } - method := kit.Select(SPIDE_POST, msg.Append(CLIENT_METHOD)) - switch arg = arg[1:]; arg[0] { // 请求方法 + switch arg = arg[1:]; arg[0] { case SPIDE_GET: method, arg = SPIDE_GET, arg[1:] case SPIDE_PUT: @@ -67,44 +63,30 @@ func _spide_list(m *ice.Message, arg ...string) { case SPIDE_DELETE: method, arg = SPIDE_DELETE, arg[1:] } - - // 构造请求 uri, arg := arg[0], arg[1:] body, head, arg := _spide_body(m, method, arg...) req, e := http.NewRequest(method, kit.MergeURL2(msg.Append(CLIENT_URL), uri, arg), body) if m.Warn(e, ice.ErrNotValid, uri) { return } - - // 请求变量 - mdb.HashSelectDetail(m, msg.Append(CLIENT_NAME), func(value ice.Map) { - _spide_head(m, req, head, value) - }) - - // 发送请求 + mdb.HashSelectDetail(m, msg.Append(CLIENT_NAME), func(value ice.Map) { _spide_head(m, req, head, value) }) res, e := _spide_send(m, msg.Append(CLIENT_NAME), req, kit.Format(msg.Append(CLIENT_TIMEOUT))) if m.Warn(e, ice.ErrNotFound, uri) { return } defer res.Body.Close() - - // 请求日志 if m.Config(LOGHEADERS) == ice.TRUE { for k, v := range res.Header { m.Logs(mdb.IMPORT, k, v) } } m.Cost(cli.STATUS, res.Status, nfs.SIZE, res.Header.Get(ContentLength), mdb.TYPE, res.Header.Get(ContentType)) - - // 响应变量 mdb.HashSelectUpdate(m, msg.Append(CLIENT_NAME), func(value ice.Map) { for _, v := range res.Cookies() { kit.Value(value, kit.Keys(SPIDE_COOKIE, v.Name), v.Value) m.Logs(mdb.IMPORT, v.Name, v.Value) } }) - - // 处理异常 if m.Warn(res.StatusCode != http.StatusOK, ice.ErrNotValid, uri, cli.STATUS, res.Status) { switch m.SetResult(); res.StatusCode { case http.StatusNotFound: @@ -115,8 +97,6 @@ func _spide_list(m *ice.Message, arg ...string) { return } } - - // 解析结果 _spide_save(m, cache, save, uri, res) } func _spide_body(m *ice.Message, method string, arg ...string) (io.Reader, ice.Maps, []string) { @@ -128,42 +108,23 @@ func _spide_body(m *ice.Message, method string, arg ...string) (io.Reader, ice.M } switch arg[0] { case SPIDE_FORM: - data := []string{} - for i := 1; i < len(arg)-1; i += 2 { - data = append(data, url.QueryEscape(arg[i])+"="+url.QueryEscape(arg[i+1])) - } - body = bytes.NewBufferString(strings.Join(data, "&")) - head[ContentType] = ContentFORM - + arg = kit.Simple(arg, func(v string) string { return url.QueryEscape(v) }) + head[ContentType], body = ContentFORM, bytes.NewBufferString(kit.JoinKV("=", "&", arg[1:]...)) case SPIDE_PART: - body, head[ContentType] = _spide_part(m, arg...) - + head[ContentType], body = _spide_part(m, arg...) case SPIDE_DATA: - if len(arg) == 1 { - arg = append(arg, "{}") - } - body, arg = bytes.NewBufferString(arg[1]), arg[2:] - head[ContentType] = ContentJSON - + head[ContentType], body = ContentJSON, bytes.NewBufferString(kit.Select("{}", arg, 1)) case SPIDE_FILE: if f, e := nfs.OpenFile(m, arg[1]); m.Assert(e) { - defer f.Close() - body, arg = f, arg[2:] + body = f } - case SPIDE_JSON: arg = arg[1:] fallthrough default: data := ice.Map{} - for i := 0; i < len(arg)-1; i += 2 { - kit.Value(data, arg[i], arg[i+1]) - } - if b, e := json.Marshal(data); m.Assert(e) { - head[ContentType] = ContentJSON - body = bytes.NewBuffer(b) - } - m.Logs(mdb.EXPORT, SPIDE_JSON, kit.Format(data)) + kit.Fetch(arg, func(k, v string) { kit.Value(data, k, v) }) + head[ContentType], body = ContentJSON, bytes.NewBufferString(kit.Format(data)) } arg = arg[:0] } else { @@ -171,33 +132,29 @@ func _spide_body(m *ice.Message, method string, arg ...string) (io.Reader, ice.M } return body, head, arg } -func _spide_part(m *ice.Message, arg ...string) (io.Reader, string) { +func _spide_part(m *ice.Message, arg ...string) (string, io.Reader) { buf := &bytes.Buffer{} mp := multipart.NewWriter(buf) defer mp.Close() - - cache := time.Now().Add(-time.Hour * 240000) - var size int64 + size, cache := int64(0), time.Now().Add(-time.Hour*240000) for i := 1; i < len(arg)-1; i += 2 { if arg[i] == nfs.SIZE { size = kit.Int64(arg[i+1]) - } - if arg[i] == SPIDE_CACHE { + } else if arg[i] == SPIDE_CACHE { if t, e := time.ParseInLocation(ice.MOD_TIME, arg[i+1], time.Local); e == nil { cache = t } - } - if strings.HasPrefix(arg[i+1], "@") { + } else if strings.HasPrefix(arg[i+1], ice.AT) { if s, e := nfs.StatFile(m, arg[i+1][1:]); e == nil { - m.Logs(mdb.IMPORT, "local", s.ModTime(), nfs.SIZE, s.Size(), CACHE, cache, nfs.SIZE, size) if s.Size() == size && s.ModTime().Before(cache) { - // break + continue } + m.Logs(mdb.IMPORT, "local", s.ModTime(), nfs.SIZE, s.Size(), CACHE, cache, nfs.SIZE, size) } - if f, e := nfs.OpenFile(m, arg[i+1][1:]); m.Assert(e) { + if f, e := nfs.OpenFile(m, arg[i+1][1:]); !m.Warn(e, ice.ErrNotValid, arg[i+1]) { defer f.Close() - if p, e := mp.CreateFormFile(arg[i], path.Base(arg[i+1][1:])); m.Assert(e) { - if n, e := io.Copy(p, f); m.Assert(e) { + if p, e := mp.CreateFormFile(arg[i], path.Base(arg[i+1][1:])); !m.Warn(e, ice.ErrNotValid, arg[i+1]) { + if n, e := io.Copy(p, f); !m.Warn(e, ice.ErrNotValid, arg[i+1]) { m.Logs(mdb.EXPORT, nfs.FILE, arg[i+1], nfs.SIZE, n) } } @@ -206,34 +163,32 @@ func _spide_part(m *ice.Message, arg ...string) (io.Reader, string) { mp.WriteField(arg[i], arg[i+1]) } } - return buf, mp.FormDataContentType() + return mp.FormDataContentType(), buf } func _spide_head(m *ice.Message, req *http.Request, head ice.Maps, value ice.Map) { - m.Info("%s %s", req.Method, req.URL) - kit.Fetch(value[SPIDE_HEADER], func(key string, value string) { - req.Header.Set(key, value) - m.Logs(key, value) - }) - kit.Fetch(value[SPIDE_COOKIE], func(key string, value string) { - req.AddCookie(&http.Cookie{Name: key, Value: value}) - m.Logs(key, value) - }) - list := kit.Simple(m.Optionv(SPIDE_COOKIE)) - for i := 0; i < len(list)-1; i += 2 { - req.AddCookie(&http.Cookie{Name: list[i], Value: list[i+1]}) - m.Logs(list[i], list[i+1]) - } - - list = kit.Simple(m.Optionv(SPIDE_HEADER)) - for i := 0; i < len(list)-1; i += 2 { - req.Header.Set(list[i], list[i+1]) - m.Logs(list[i], list[i+1]) - } - for k, v := range head { + m.Logs(req.Method, req.URL) + kit.Fetch(value[SPIDE_HEADER], func(k string, v string) { req.Header.Set(k, v) - } + m.Logs("Header", k, v) + }) + kit.Fetch(value[SPIDE_COOKIE], func(k string, v string) { + req.AddCookie(&http.Cookie{Name: k, Value: v}) + m.Logs("Cookie", k, v) + }) + kit.Fetch(kit.Simple(m.Optionv(SPIDE_COOKIE)), func(k, v string) { + req.AddCookie(&http.Cookie{Name: k, Value: v}) + m.Logs("Cookie", k, v) + }) + kit.Fetch(kit.Simple(m.Optionv(SPIDE_HEADER)), func(k, v string) { + req.Header.Set(k, v) + m.Logs("Header", k, v) + }) + kit.Fetch(head, func(k, v string) { + req.Header.Set(k, v) + m.Logs("Header", k, v) + }) if req.Method == SPIDE_POST { - m.Logs(req.Header.Get(ContentLength), req.Header.Get(ContentType)) + m.Logs(kit.Select(ice.AUTO, req.Header.Get(ContentLength)), req.Header.Get(ContentType)) } } func _spide_send(m *ice.Message, name string, req *http.Request, timeout string) (*http.Response, error) { @@ -243,80 +198,53 @@ func _spide_send(m *ice.Message, name string, req *http.Request, timeout string) func _spide_save(m *ice.Message, cache, save, uri string, res *http.Response) { switch cache { case SPIDE_RAW: - b, _ := ioutil.ReadAll(res.Body) - if strings.HasPrefix(res.Header.Get(ContentType), ContentJSON) { + if b, _ := ioutil.ReadAll(res.Body); strings.HasPrefix(res.Header.Get(ContentType), ContentJSON) { m.Echo(kit.Formats(kit.UnMarshal(string(b)))) } else { m.Echo(string(b)) } - case SPIDE_MSG: var data map[string][]string m.Assert(json.NewDecoder(res.Body).Decode(&data)) - for _, k := range data[ice.MSG_APPEND] { - for i := range data[k] { - m.Push(k, data[k][i]) - } - } + kit.Fetch(data[ice.MSG_APPEND], func(k string) { kit.Fetch(data[k], func(v string) { m.Push(k, v) }) }) m.Resultv(data[ice.MSG_RESULT]) - case SPIDE_SAVE: - _cache_download(m, res, save) - + _cache_download(m, res, save, m.OptionCB(SPIDE)) case SPIDE_CACHE: m.Optionv(RESPONSE, res) m.Cmdy(CACHE, DOWNLOAD, res.Header.Get(ContentType), uri) m.Echo(m.Append(mdb.DATA)) - default: - b, _ := ioutil.ReadAll(res.Body) - var data ice.Any - if e := json.Unmarshal(b, &data); e != nil { - m.Echo(string(b)) - break + if b, e := ioutil.ReadAll(res.Body); !m.Warn(e) { + if json.Unmarshal(b, &data) == nil { + m.Push("", kit.KeyValue(ice.Map{}, "", m.Optionv(SPIDE_RES, data))) + } else { + m.Echo(string(b)) + } } - - m.Optionv(SPIDE_RES, data) - data = kit.KeyValue(ice.Map{}, "", data) - m.Push("", data) } } -func _cache_download(m *ice.Message, r *http.Response, file string) string { - defer r.Body.Close() - if f, p, e := miss.CreateFile(file); m.Warn(e, ice.ErrNotValid, DOWNLOAD) { - defer f.Close() - nfs.CopyFile(m, f, r.Body, kit.Int(kit.Select("100", r.Header.Get(ContentLength))), m.OptionCB(SPIDE)) - return p - } - return "" -} const ( - // 缓存方法 SPIDE_RAW = "raw" SPIDE_MSG = "msg" SPIDE_SAVE = "save" SPIDE_CACHE = "cache" - // 请求方法 - SPIDE_GET = "GET" - SPIDE_PUT = "PUT" - SPIDE_POST = "POST" - SPIDE_DELETE = "DELETE" + SPIDE_GET = http.MethodGet + SPIDE_PUT = http.MethodPut + SPIDE_POST = http.MethodPost + SPIDE_DELETE = http.MethodDelete - // 请求参数 SPIDE_BODY = "body" SPIDE_FORM = "form" SPIDE_PART = "part" SPIDE_JSON = "json" SPIDE_DATA = "data" SPIDE_FILE = "file" + SPIDE_RES = "content_data" - // 响应数据 - SPIDE_RES = "content_data" - - // 请求头 Bearer = "Bearer" Authorization = "Authorization" ContentType = "Content-Type" @@ -325,7 +253,6 @@ const ( Referer = "Referer" Accept = "Accept" - // 数据格式 ContentFORM = "application/x-www-form-urlencoded" ContentJSON = "application/json" ContentPNG = "image/png" @@ -338,6 +265,9 @@ const ( SPIDE_HEADER = "header" SPIDE_COOKIE = "cookie" + CLIENT_PROTOCOL = "client.protocol" + CLIENT_HOSTNAME = "client.hostname" + CLIENT_NAME = "client.name" CLIENT_METHOD = "client.method" CLIENT_TIMEOUT = "client.timeout" @@ -349,12 +279,10 @@ const ( LINK = "link" HTTP = "http" FORM = "form" + MERGE = "merge" ADDRESS = "address" REQUEST = "request" RESPONSE = "response" - - MERGE = "merge" - SUBMIT = "submit" ) const SPIDE = "spide" @@ -363,34 +291,25 @@ func init() { SPIDE: {Name: "spide client.name action=raw,msg,save,cache method=GET,PUT,POST,DELETE url format=form,part,json,data,file arg run create", Help: "蜘蛛侠", Actions: ice.MergeActions(ice.Actions{ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { conf := m.Confm(cli.RUNTIME, cli.CONF) - m.Cmd(SPIDE, mdb.CREATE, ice.OPS, kit.Select("http://127.0.0.1:9020", conf[cli.CTX_OPS])) - m.Cmd(SPIDE, mdb.CREATE, ice.DEV, kit.Select("http://contexts.woa.com:80", conf[cli.CTX_DEV])) - m.Cmd(SPIDE, mdb.CREATE, ice.SHY, kit.Select("https://shylinux.com:443", conf[cli.CTX_SHY])) - m.Cmd(aaa.ROLE, aaa.WHITE, aaa.VOID, SPIDE, SUBMIT) + m.Cmd("", mdb.CREATE, ice.OPS, kit.Select("http://127.0.0.1:9020", conf[cli.CTX_OPS])) + m.Cmd("", mdb.CREATE, ice.DEV, kit.Select("http://contexts.woa.com:80", conf[cli.CTX_DEV])) + m.Cmd("", mdb.CREATE, ice.COM, kit.Select("https://contexts.com:443", conf[cli.CTX_COM])) + m.Cmd("", mdb.CREATE, ice.SHY, kit.Select("https://shylinux.com:443", conf[cli.CTX_SHY])) }}, - mdb.CREATE: {Name: "create name address", Help: "添加", Hand: func(m *ice.Message, arg ...string) { - _spide_create(m, m.Option(mdb.NAME), m.Option(ADDRESS)) - }}, - MERGE: {Name: "merge name path", Help: "拼接", Hand: func(m *ice.Message, arg ...string) { - m.Echo(kit.MergeURL2(m.CmdAppend(SPIDE, arg[0], CLIENT_URL), arg[1], arg[2:])) - }}, - SUBMIT: {Name: "submit dev pod path size cache", Help: "发布", Hand: func(m *ice.Message, arg ...string) { - m.Cmdy(SPIDE, ice.DEV, SPIDE_RAW, m.Option(ice.DEV), SPIDE_PART, m.OptionSimple(ice.POD), nfs.PATH, ice.BIN_ICE_BIN, UPLOAD, "@"+ice.BIN_ICE_BIN) - }}, - "client": {Hand: func(m *ice.Message, arg ...string) { + mdb.CREATE: {Name: "create name address", Hand: func(m *ice.Message, arg ...string) { _spide_create(m, m.Option(mdb.NAME), m.Option(ADDRESS)) }}, + tcp.CLIENT: {Hand: func(m *ice.Message, arg ...string) { msg := m.Cmd("", kit.Select(ice.DEV, arg, 0)) - ls := kit.Split(msg.Append("client.hostname"), ice.DF) - m.Push(tcp.HOST, ls[0]) - m.Push(tcp.PORT, kit.Select(kit.Select("443", "80", msg.Append("client.protocol") == ice.HTTP), ls, 1)) - m.Push(tcp.HOSTNAME, msg.Append("client.hostname")) - m.Push(tcp.PROTOCOL, msg.Append("client.protocol")) - m.Push(DOMAIN, msg.Append("client.protocol")+"://"+msg.Append("client.hostname")+kit.Select("", arg, 1)) + ls := kit.Split(msg.Append(CLIENT_HOSTNAME), ice.DF) + m.Push(tcp.HOST, ls[0]).Push(tcp.PORT, kit.Select(kit.Select("443", "80", msg.Append(CLIENT_PROTOCOL) == ice.HTTP), ls, 1)) + m.Push(DOMAIN, msg.Append(CLIENT_PROTOCOL)+"://"+msg.Append(CLIENT_HOSTNAME)+kit.Select("", arg, 1)) + m.Push(tcp.PROTOCOL, msg.Append(CLIENT_PROTOCOL)).Push(tcp.HOSTNAME, msg.Append(CLIENT_HOSTNAME)) }}, + MERGE: {Hand: func(m *ice.Message, arg ...string) { m.Echo(kit.MergeURL2(m.CmdAppend("", arg[0], CLIENT_URL), arg[1], arg[2:])) }}, }, mdb.HashAction(mdb.SHORT, CLIENT_NAME, mdb.FIELD, "time,client.name,client.url", LOGHEADERS, ice.FALSE), mdb.ClearHashOnExitAction()), Hand: func(m *ice.Message, arg ...string) { if len(arg) < 2 || arg[0] == "" || (len(arg) > 3 && arg[3] == "") { mdb.HashSelect(m, kit.Slice(arg, 0, 1)...).Sort(CLIENT_NAME) } else { - _spide_list(m, arg...) + _spide_show(m, arg...) } }}, SPIDE_GET: {Name: "GET url key value run", Help: "蜘蛛侠", Hand: func(m *ice.Message, arg ...string) { @@ -408,18 +327,10 @@ func init() { }) } -func SpideGet(m *ice.Message, arg ...ice.Any) ice.Any { - return kit.UnMarshal(m.Cmdx(SPIDE_GET, arg)) -} -func SpidePut(m *ice.Message, arg ...ice.Any) ice.Any { - return kit.UnMarshal(m.Cmdx(SPIDE_PUT, arg)) -} -func SpidePost(m *ice.Message, arg ...ice.Any) ice.Any { - return kit.UnMarshal(m.Cmdx(SPIDE_POST, arg)) -} -func SpideDelete(m *ice.Message, arg ...ice.Any) ice.Any { - return kit.UnMarshal(m.Cmdx(SPIDE_DELETE, arg)) -} +func SpideGet(m *ice.Message, arg ...ice.Any) ice.Any { return kit.UnMarshal(m.Cmdx(SPIDE_GET, arg)) } +func SpidePut(m *ice.Message, arg ...ice.Any) ice.Any { return kit.UnMarshal(m.Cmdx(SPIDE_PUT, arg)) } +func SpidePost(m *ice.Message, arg ...ice.Any) ice.Any { return kit.UnMarshal(m.Cmdx(SPIDE_POST, arg)) } +func SpideDelete(m *ice.Message, arg ...ice.Any) ice.Any { return kit.UnMarshal(m.Cmdx(SPIDE_DELETE, arg)) } func SpideSave(m *ice.Message, file, link string, cb func(int, int, int)) *ice.Message { return m.Cmd("web.spide", ice.DEV, SPIDE_SAVE, file, SPIDE_GET, link, cb) } diff --git a/base/web/web.go b/base/web/web.go index 859b876c..8561d9ba 100644 --- a/base/web/web.go +++ b/base/web/web.go @@ -39,7 +39,7 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool { msg := m.Spawn(c) if pf, ok := p.Server().(*Frame); ok && pf.ServeMux != nil { route := ice.PS + c.Name + ice.PS - msg.Log(ROUTE, "%s <= %s", p.Name, route) + msg.Log("route", "%s <= %s", p.Name, route) pf.Handle(route, http.StripPrefix(path.Dir(route), f)) list[c] = path.Join(list[p], route) } @@ -48,7 +48,7 @@ func (f *Frame) Start(m *ice.Message, arg ...string) bool { continue } func(key string, cmd *ice.Command) { - msg.Log(ROUTE, "%s <- %s", c.Name, key) + msg.Log("route", "%s <- %s", c.Name, key) f.HandleFunc(key, func(w http.ResponseWriter, r *http.Request) { m.TryCatch(m.Spawn(key, cmd, c, w, r), true, func(msg *ice.Message) { _serve_handle(key, cmd, msg, w, r) }) }) @@ -96,7 +96,7 @@ const WEB = "web" var Index = &ice.Context{Name: WEB, Help: "网络模块"} func init() { - ice.Index.Register(Index, &Frame{}, BROAD, SERVE, SPACE, DREAM, SHARE, CACHE, SPIDE, ROUTE) + ice.Index.Register(Index, &Frame{}, BROAD, SERVE, SPACE, DREAM, CACHE, SPIDE, SHARE) } func ApiAction(arg ...string) ice.Actions { return ice.Actions{kit.Select(ice.PS, arg, 0): {}} } diff --git a/core/chat/favor.go b/core/chat/favor.go index 44c31ef0..599c6be0 100644 --- a/core/chat/favor.go +++ b/core/chat/favor.go @@ -57,8 +57,7 @@ func init() { mdb.HashCreate(m, m.OptionSimple()) }}, web.UPLOAD: {Hand: func(m *ice.Message, arg ...string) { - msg := web.Upload(m) - m.Cmd("", mdb.CREATE, msg.AppendSimple(mdb.TYPE, mdb.NAME, mdb.TEXT)) + m.Cmd("", mdb.CREATE, m.OptionSimple(mdb.TYPE, mdb.NAME, mdb.TEXT)) }}, web.DOWNLOAD: {Hand: func(m *ice.Message, arg ...string) { ctx.ProcessOpen(m, web.MergeURL2(m, web.SHARE_LOCAL+m.Option(mdb.TEXT), "filename", m.Option(mdb.NAME))) diff --git a/core/chat/pod.go b/core/chat/pod.go index e6a63198..bb23c45e 100644 --- a/core/chat/pod.go +++ b/core/chat/pod.go @@ -22,7 +22,7 @@ func init() { web.SERVE_PARSE: {Hand: func(m *ice.Message, arg ...string) { switch kit.Select("", arg, 0) { case CHAT: - for i := 1; i < len(arg)-1; i++ { + for i := 1; i < len(arg)-1; i += 2 { m.Logs("refer", arg[i], arg[i+1]) m.Option(arg[i], arg[i+1]) } diff --git a/core/chat/trans.go b/core/chat/trans.go index b6041613..7e61824b 100644 --- a/core/chat/trans.go +++ b/core/chat/trans.go @@ -42,11 +42,11 @@ func init() { }}, }, ctx.CmdAction()), Hand: func(m *ice.Message, arg ...string) { if len(arg) == 0 { - m.Cmdy(web.ROUTE).RenameAppend(web.ROUTE, FROM) + m.Cmdy(web.SPACE).RenameAppend(mdb.NAME, FROM) return } if len(arg) == 1 { - m.Cmdy(web.ROUTE).RenameAppend(web.ROUTE, TO) + m.Cmdy(web.SPACE).RenameAppend(mdb.NAME, TO) return } ctx.DisplayLocal(m, "") diff --git a/core/code/pprof.go b/core/code/pprof.go index 88eb5d8c..4e7755cf 100644 --- a/core/code/pprof.go +++ b/core/code/pprof.go @@ -24,14 +24,13 @@ const ( const PPROF = "pprof" func init() { + web.Index.MergeCommands(ice.Commands{"/debug/": {Hand: func(m *ice.Message, arg ...string) { + defer m.Render(ice.RENDER_VOID) + m.R.URL.Path = "/debug" + m.R.URL.Path + http.DefaultServeMux.ServeHTTP(m.W, m.R) + }}}) Index.MergeCommands(ice.Commands{ PPROF: {Name: "pprof zone id auto", Help: "性能分析", Actions: ice.MergeActions(ice.Actions{ - web.SERVE_REWRITE: {Hand: func(m *ice.Message, arg ...string) { - if strings.HasPrefix(arg[1], "/debug/") { - m.R.URL.Path = strings.Replace(m.R.URL.Path, "/debug/", "/code/", -1) - m.Debug("rewrite %v -> %v", arg[1], m.R.URL.Path) - } - }}, mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) { switch arg[0] { case BINNARY: @@ -58,7 +57,7 @@ func init() { m.Cmd(cli.DAEMON, m.Configv(PPROF), "-http="+p, m.Option(BINNARY), m.Option(nfs.FILE)) m.Echo("http://%s/ui/top", p).ProcessInner() }}, - }, mdb.ZoneAction(mdb.SHORT, mdb.ZONE, mdb.FIELD, "time,id,text,file", PPROF, kit.List(GO, "tool", PPROF)), web.ServeAction()), Hand: func(m *ice.Message, arg ...string) { + }, mdb.ZoneAction(mdb.SHORT, mdb.ZONE, mdb.FIELD, "time,id,text,file", PPROF, kit.List(GO, "tool", PPROF))), Hand: func(m *ice.Message, arg ...string) { m.Fields(len(arg), "time,zone,count,binnary,service,seconds", mdb.ZoneField(m)) if mdb.ZoneSelect(m, arg...); len(arg) == 0 { m.EchoAnchor(web.MergeLink(m, "/code/pprof/")) @@ -71,10 +70,5 @@ func init() { }) } }}, - web.PP(PPROF): {Name: "/pprof/", Help: "性能分析", Hand: func(m *ice.Message, arg ...string) { - defer m.Render(ice.RENDER_VOID) - m.R.URL.Path = "/debug" + m.R.URL.Path - http.DefaultServeMux.ServeHTTP(m.W, m.R) - }}, }) } diff --git a/core/wiki/wiki.go b/core/wiki/wiki.go index df62ec9b..9ff70c85 100644 --- a/core/wiki/wiki.go +++ b/core/wiki/wiki.go @@ -48,6 +48,7 @@ func _wiki_list(m *ice.Message, arg ...string) bool { } m.Cmdy(nfs.DIR, kit.Slice(arg, 0, 1), kit.Dict(nfs.DIR_TYPE, nfs.CAT, nfs.DIR_REG, m.Config(lex.REGEXP))) m.StatusTimeCount() + m.SortTimeR(mdb.TIME) return true } ctx.DisplayLocal(m, path.Join(kit.PathName(2), kit.Keys(kit.FileName(2), ice.JS))) @@ -60,7 +61,7 @@ func _wiki_save(m *ice.Message, name, text string, arg ...string) { m.Cmd(nfs.SAVE, name, text, kit.Dict(nfs.DIR_ROOT, _wiki_path(m))) } func _wiki_upload(m *ice.Message, dir string) { - m.Cmdy(web.CACHE, web.UPLOAD_WATCH, _wiki_path(m, dir)) + m.Cmdy(web.CACHE, web.WATCH, m.Option(ice.MSG_UPLOAD), _wiki_path(m, dir, m.Option(mdb.NAME))) } func _wiki_template(m *ice.Message, name, text string, arg ...string) *ice.Message { return _option(m, m.CommandKey(), name, strings.TrimSpace(text), arg...).RenderTemplate(m.Config(nfs.TEMPLATE), &Message{m}) @@ -81,8 +82,8 @@ func init() { func WikiAction(dir string, ext ...string) ice.Actions { return ice.Actions{ice.CTX_INIT: mdb.AutoConfig(nfs.PATH, dir, lex.REGEXP, kit.FileReg(ext...)), web.UPLOAD: {Hand: func(m *ice.Message, arg ...string) { _wiki_upload(m, m.Option(nfs.PATH)) }}, - nfs.SAVE: {Name: "save path text", Hand: func(m *ice.Message, arg ...string) { _wiki_save(m, m.Option(nfs.PATH), m.Option(mdb.TEXT)) }}, - nfs.TRASH: {Hand: func(m *ice.Message, arg ...string) { nfs.Trash(m, _wiki_path(m, m.Option(nfs.PATH))) }}, + nfs.TRASH: {Name: "trash path*", Hand: func(m *ice.Message, arg ...string) { nfs.Trash(m, _wiki_path(m, m.Option(nfs.PATH))) }}, + nfs.SAVE: {Name: "save path* text", Hand: func(m *ice.Message, arg ...string) { _wiki_save(m, m.Option(nfs.PATH), m.Option(mdb.TEXT)) }}, mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) { switch arg[0] { case nfs.PATH: diff --git a/logs.go b/logs.go index 05a3099f..89854f15 100644 --- a/logs.go +++ b/logs.go @@ -44,7 +44,7 @@ func (m *Message) join(arg ...Any) (string, []Any) { return kit.Join(list, SP), meta } func (m *Message) log(level string, str string, arg ...Any) *Message { - _source := logs.FileLineMeta(logs.FileLine(3)) + _source := logs.FileLineMeta(3) if Info.Log != nil { Info.Log(m, m.FormatPrefix(), level, logs.Format(str, append(arg, _source)...)) } @@ -76,7 +76,7 @@ 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]) { + if len(level) > 0 && unicode.IsUpper([]rune(level)[0]) { meta = []Any{logs.FileLineMeta("")} } return m.log(level, str, meta...) @@ -99,7 +99,7 @@ func (m *Message) Info(str string, arg ...Any) *Message { return m.log(LOG_INFO, str, arg...) } func (m *Message) WarnTimeNotValid(time Any, arg ...Any) bool { - return m.Warn(kit.Format(time) < m.Time(), ErrNotValid, kit.Simple(arg), time, m.Time(), logs.FileLineMeta(logs.FileLine(2))) + return m.Warn(kit.Format(time) < m.Time(), ErrNotValid, kit.Simple(arg), time, m.Time(), logs.FileLineMeta(2)) } func (m *Message) Warn(err Any, arg ...Any) bool { switch err := err.(type) { diff --git a/meta.go b/meta.go index b20a89cb..051ecf7e 100644 --- a/meta.go +++ b/meta.go @@ -401,6 +401,12 @@ func (m *Message) Detailv(arg ...Any) []string { func (m *Message) Options(arg ...Any) Any { for i := 0; i < len(arg); i += 2 { switch val := arg[i].(type) { + case Maps: + for k, v := range val { + m.Optionv(k, v) + } + i-- + continue case []string: for i := 0; i < len(val)-1; i += 2 { m.Optionv(val[i], val[i+1]) diff --git a/misc.go b/misc.go index ccd2645e..31c51e3a 100644 --- a/misc.go +++ b/misc.go @@ -289,23 +289,25 @@ func (c *Context) _action(m *Message, cmd *Command, key string, sub string, h *A order := false for i, v := range h.List { name := kit.Format(kit.Value(v, NAME)) - value := kit.Format(kit.Value(v, VALUE)) - if i == 0 && len(arg) > 0 && arg[0] != name { - order = true + if i == 0 { + if len(arg) > 0 && arg[0] == name { + for i := 0; i < len(arg)-1; i += 2 { + if strings.HasPrefix(arg[i], PS) { + break + } + m.Option(arg[i], arg[i+1]) + } + } else { + order = true + } } if order { - 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 + if value := kit.Select("", arg, i); value != "" { + m.Option(name, value) } - m.Option(arg[i], arg[i+1]) + } + if m.Warn(m.OptionDefault(name, kit.Format(kit.Value(v, VALUE))) == "" && kit.Value(v, "need") == "must") { + return m } } } @@ -449,3 +451,18 @@ func SplitCmd(name string, actions Actions) (list []Any) { } return list } +func MergeHand(hand ...Handler) Handler { + if len(hand) == 0 { + return nil + } + if len(hand) == 1 { + return hand[0] + } + return func(m *Message, arg ...string) { + for _, h := range hand { + if h != nil { + h(m, arg...) + } + } + } +} diff --git a/misc/git/server.go b/misc/git/server.go index fbfd17e2..c7dfa29c 100644 --- a/misc/git/server.go +++ b/misc/git/server.go @@ -111,15 +111,10 @@ func _server_reader(m *ice.Message) (io.ReadCloser, error) { const SERVER = "server" func init() { + web.Index.MergeCommands(ice.Commands{"/x/": {Hand: func(m *ice.Message, arg ...string) { m.Cmdy("web.code.git.repository", arg) }}}) Index.MergeCommands(ice.Commands{ web.WEB_LOGIN: {Hand: func(m *ice.Message, arg ...string) { m.Render(ice.RENDER_VOID) }}, - "repository": {Name: "repository", Help: "代码库", Actions: ice.MergeActions(ice.Actions{ - web.SERVE_REWRITE: {Hand: func(m *ice.Message, arg ...string) { - if strings.HasPrefix(arg[1], "/x/") { - _server_rewrite(m, arg[1], m.R) - } - }}, - }, web.ServeAction(), web.ApiAction()), Hand: func(m *ice.Message, arg ...string) { + "repository": {Name: "repository", Help: "代码库", Hand: func(m *ice.Message, arg ...string) { if m.Option("go-get") == "1" { // 下载地址 p := web.MergeLink(m, "/x/"+path.Join(arg...)) m.RenderResult(kit.Format(``, "go-import", kit.Format(`%s git %s`, strings.Split(p, "://")[1], p))) @@ -138,8 +133,7 @@ func init() { m.Logs(mdb.CREATE, REPOS, repos) } case "upload-pack": // 下载代码 - if !nfs.ExistsFile(m, repos) { - web.RenderStatus(m.W, http.StatusNotFound, kit.Format("not found: %s", arg[0])) + if m.Warn(!nfs.ExistsFile(m, repos), ice.ErrNotFound, arg[0]) { return } } diff --git a/render.go b/render.go index 9885766b..f2bf497b 100644 --- a/render.go +++ b/render.go @@ -10,6 +10,14 @@ import ( func AddRender(key string, render func(*Message, ...Any) string) { Info.render[key] = render } +func RenderAction(key ...string) Actions { + return Actions{CTX_INIT: {Hand: func(m *Message, arg ...string) { + cmd := m.CommandKey() + for _, key := range key { + AddRender(key, func(m *Message, arg ...Any) string { return m.Cmd(cmd, key, arg).Result() }) + } + }}} +} func Render(m *Message, cmd string, args ...Any) string { if render, ok := Info.render[cmd]; ok { return render(m, args...)