diff --git a/base/aaa/aaa.go b/base/aaa/aaa.go
index abc421da..4c2897be 100644
--- a/base/aaa/aaa.go
+++ b/base/aaa/aaa.go
@@ -2,7 +2,7 @@ package aaa
import (
"github.com/shylinux/icebergs"
- "github.com/shylinux/icebergs/base/cli"
+ // "github.com/shylinux/icebergs/base/cli"
"github.com/shylinux/toolkits"
)
@@ -26,8 +26,6 @@ var Index = &ice.Context{Name: "aaa", Help: "认证模块", Commands: map[string
m.Rich(ROLE, nil, kit.Dict(kit.MDB_NAME, TECH, Black, kit.Dict(), White, kit.Dict()))
m.Rich(ROLE, nil, kit.Dict(kit.MDB_NAME, VOID, White, kit.Dict(), Black, kit.Dict()))
m.Load()
- cli.PassWord = kit.Hashs("uniq")
- _user_create(m, cli.UserName, cli.PassWord)
}},
ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Save(ROLE, USER, SESS)
diff --git a/base/aaa/sess.go b/base/aaa/sess.go
index c9a9cd7c..972bc0c0 100644
--- a/base/aaa/sess.go
+++ b/base/aaa/sess.go
@@ -21,17 +21,19 @@ func _sess_auth(m *ice.Message, sessid string, username string, userrole string)
}
value["username"] = username
m.Log_AUTH(SESSID, sessid, USERNAME, username, USERROLE, userrole)
- m.Echo("%v", value[USERROLE])
})
}
func _sess_check(m *ice.Message, sessid string) {
m.Richs(SESS, nil, sessid, func(value map[string]interface{}) {
- m.Push(sessid, value, []string{USERNAME, USERROLE})
- m.Echo("%s", value[USERROLE])
+ m.Log_AUTH(
+ USERROLE, m.Option(ice.MSG_USERROLE, value[USERROLE]),
+ USERNAME, m.Option(ice.MSG_USERNAME, value[USERNAME]),
+ )
})
}
func _sess_create(m *ice.Message, username string) string {
h := m.Rich(SESS, nil, kit.Dict(
+ kit.MDB_TIME, m.Time(m.Conf(SESS, "meta.expire")),
USERNAME, username, "from", m.Option(ice.MSG_SESSID),
))
m.Log_CREATE(SESSID, h, USERNAME, username)
diff --git a/base/aaa/user.go b/base/aaa/user.go
index 679c1b87..a71b5213 100644
--- a/base/aaa/user.go
+++ b/base/aaa/user.go
@@ -25,12 +25,17 @@ func _user_create(m *ice.Message, name, word string) {
// 创建用户
m.Rich(USER, nil, kit.Dict(
USERNAME, name, PASSWORD, word,
- USERNICK, name, USERNODE, m.Conf(ice.CLI_RUNTIME, "boot.hostname"),
+ USERNICK, name, USERNODE, cli.NodeName,
))
m.Log_CREATE(USERNAME, name)
m.Event(ice.USER_CREATE, name)
}
+func UserRoot(m *ice.Message) {
+ cli.PassWord = kit.Hashs("uniq")
+ cli.PassWord = cli.UserName
+ _user_create(m, cli.UserName, cli.PassWord)
+}
func UserRole(m *ice.Message, username string) string {
if username == cli.UserName {
return ROOT
@@ -42,12 +47,6 @@ func UserLogin(m *ice.Message, username, password string) bool {
m.Option(ice.MSG_USERNAME, username)
m.Option(ice.MSG_USERROLE, UserRole(m, username))
m.Option(ice.MSG_SESSID, SessCreate(m, m.Option(ice.MSG_USERNAME), m.Option(ice.MSG_USERROLE)))
-
- m.Log_AUTH(
- USERROLE, m.Option(ice.MSG_USERROLE),
- USERNAME, m.Option(ice.MSG_USERNAME),
- SESSID, m.Option(ice.MSG_SESSID),
- )
return true
}
return false
@@ -66,43 +65,7 @@ func init() {
_user_login(m, arg[0], arg[1])
}},
}, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
- if len(arg) == 0 {
- _user_list(m)
- return
- }
-
- switch arg[0] {
- case "first":
- // 超级用户
- if m.Richs(ice.AAA_USER, nil, "%", nil) == nil {
- }
-
- case "login":
- // 用户认证
- user := m.Richs(USER, nil, arg[1], nil)
- if word := kit.Select("", arg, 2); user == nil {
- nick := arg[1]
- if len(nick) > 8 {
- nick = nick[:8]
- }
- _user_create(m, arg[1], word)
-
- } else if word != "" {
- if !_user_login(m, arg[1], word) {
- m.Info("login fail user: %s", arg[1])
- break
- }
- }
-
- if m.Options(ice.MSG_SESSID) && m.Cmdx(ice.AAA_SESS, "check", m.Option(ice.MSG_SESSID)) == arg[1] {
- // 复用会话
- m.Echo(m.Option(ice.MSG_SESSID))
- break
- }
-
- // 创建会话
- m.Echo(m.Cmdx(ice.AAA_SESS, "create", arg[1]))
- }
+ _user_list(m)
}},
},
}, nil)
diff --git a/base/cli/cli.go b/base/cli/cli.go
index 55265743..4eb134bd 100644
--- a/base/cli/cli.go
+++ b/base/cli/cli.go
@@ -24,6 +24,12 @@ var HostName = ""
var PathName = ""
var NodeName = ""
+func NodeType(m *ice.Message, kind, name string) {
+ m.Conf(ice.CLI_RUNTIME, "node.type", kind)
+ m.Conf(ice.CLI_RUNTIME, "node.name", name)
+ NodeName = name
+}
+
var Index = &ice.Context{Name: "cli", Help: "命令模块",
Configs: map[string]*ice.Config{
RUNTIME: {Name: "runtime", Help: "运行环境", Value: kit.Dict()},
diff --git a/base/cli/system.go b/base/cli/system.go
index ebbb48d4..57f13be1 100644
--- a/base/cli/system.go
+++ b/base/cli/system.go
@@ -30,7 +30,8 @@ func _system_show(m *ice.Message, cmd *exec.Cmd) {
cmd.Stderr = err
defer m.Cost("%v exit: %v out: %v err: %v ", cmd.Args, 0, out.Len(), err.Len())
- if e := cmd.Run(); !m.Warn(e != nil, "%v run: %s", cmd.Args, kit.Select(e.Error(), err.String())) {
+ if e := cmd.Run(); e != nil {
+ m.Warn(e != nil, "%v run: %s", cmd.Args, kit.Select(e.Error(), err.String()))
}
m.Push(CMD_CODE, int(cmd.ProcessState.ExitCode()))
diff --git a/base/ctx/ctx.go b/base/ctx/ctx.go
index f9b638b8..fb8563f6 100644
--- a/base/ctx/ctx.go
+++ b/base/ctx/ctx.go
@@ -40,9 +40,6 @@ func _config_list(m *ice.Message, all bool) {
func _config_save(m *ice.Message, name string, arg ...string) {
msg := m.Spawn(m.Source())
// 保存配置
- if m.Cap(ice.CTX_STATUS) != ice.ICE_START {
- return
- }
name = path.Join(msg.Conf(ice.CTX_CONFIG, "meta.path"), name)
if f, p, e := kit.Create(name); m.Assert(e) {
data := map[string]interface{}{}
diff --git a/base/ssh/ssh.go b/base/ssh/ssh.go
index bcc9fc34..bc7b77ac 100644
--- a/base/ssh/ssh.go
+++ b/base/ssh/ssh.go
@@ -2,6 +2,7 @@ package ssh
import (
"github.com/shylinux/icebergs"
+ "github.com/shylinux/icebergs/base/aaa"
"github.com/shylinux/toolkits"
"bufio"
@@ -178,6 +179,7 @@ func (f *Frame) Begin(m *ice.Message, arg ...string) ice.Server {
func (f *Frame) Start(m *ice.Message, arg ...string) bool {
m.Option(ice.MSG_PROMPT, m.Confv("prompt", "meta.PS1"))
f.target = m.Source()
+ aaa.UserRoot(m)
switch kit.Select("stdio", arg, 0) {
case "stdio":
diff --git a/base/tcp/tcp.go b/base/tcp/tcp.go
index ccd0e11d..98d41467 100644
--- a/base/tcp/tcp.go
+++ b/base/tcp/tcp.go
@@ -57,7 +57,7 @@ func _ip_islocal(m *ice.Message, ip string) (ok bool) {
})
return ok
}
-func _tcp_port(m *ice.Message) {
+func _tcp_port(m *ice.Message) string {
current := kit.Int(m.Conf(GETPORT, "meta.current"))
end := kit.Int(m.Conf(GETPORT, "meta.end"))
if current >= end {
@@ -67,15 +67,19 @@ func _tcp_port(m *ice.Message) {
if m.Cmd(cli.SYSTEM, "lsof", "-i", kit.Format(":%d", i)).Append(cli.CMD_CODE) != "0" {
m.Conf(GETPORT, "meta.current", i)
m.Log_CREATE(GETPORT, i)
- m.Echo("%d", i)
+ return kit.Format("%d", i)
break
}
}
+ return ""
}
func IPIsLocal(m *ice.Message, ip string) bool {
return _ip_islocal(m, ip)
}
+func TCPPort(m *ice.Message) string {
+ return _tcp_port(m)
+}
var Index = &ice.Context{Name: "tcp", Help: "通信模块",
Caches: map[string]*ice.Cache{},
@@ -92,7 +96,7 @@ var Index = &ice.Context{Name: "tcp", Help: "通信模块",
_ip_list(m, "")
}},
GETPORT: {Name: "getport", Help: "分配端口", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
- _tcp_port(m)
+ m.Echo(_tcp_port(m))
}},
"ip": {Name: "ifconfig [name]", Help: "网络配置", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
diff --git a/base/web/cache.go b/base/web/cache.go
index e4abef2d..c2510561 100644
--- a/base/web/cache.go
+++ b/base/web/cache.go
@@ -101,6 +101,12 @@ func _cache_watch(m *ice.Message, key, file string) {
}
func _cache_catch(m *ice.Message, arg ...string) []string {
+ if r, ok := m.Optionv("response").(*http.Response); ok {
+ return _cache_download(m, r, arg...)
+ } else if m.R != nil {
+ return _cache_upload(m, arg...)
+ }
+
if f, e := os.Open(arg[2]); m.Assert(e) {
defer f.Close()
@@ -188,16 +194,9 @@ func init() {
}
switch arg[0] {
- case "catch":
+ case "download", "upload", "catch":
arg = _cache_catch(m, arg...)
fallthrough
- case "download", "upload":
- if r, ok := m.Optionv("response").(*http.Response); ok {
- arg = _cache_download(m, r, arg...)
- } else if m.R != nil {
- arg = _cache_upload(m, arg...)
- }
- fallthrough
case "add":
_cache_save(m, arg[0], arg[1], arg[2], arg[3], arg[4:]...)
case "watch":
diff --git a/base/web/dream.go b/base/web/dream.go
new file mode 100644
index 00000000..78ed2d24
--- /dev/null
+++ b/base/web/dream.go
@@ -0,0 +1,87 @@
+package web
+
+import (
+ ice "github.com/shylinux/icebergs"
+ kit "github.com/shylinux/toolkits"
+
+ "io/ioutil"
+ "os"
+ "path"
+ "strings"
+ "time"
+)
+
+func init() {
+ Index.Merge(&ice.Context{
+ Configs: map[string]*ice.Config{
+ ice.WEB_DREAM: {Name: "dream", Help: "梦想家", Value: kit.Data("path", "usr/local/work",
+ // "cmd", []interface{}{ice.CLI_SYSTEM, "ice.sh", "start", ice.WEB_SPACE, "connect"},
+ "cmd", []interface{}{ice.CLI_SYSTEM, "ice.bin", ice.WEB_SPACE, "connect"},
+ )},
+ },
+ Commands: map[string]*ice.Command{
+ ice.WEB_DREAM: {Name: "dream name auto", Help: "梦想家", Meta: kit.Dict(
+ "exports", []string{"you", "name"}, "detail", []interface{}{"启动", "停止"},
+ ), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
+ if len(arg) > 1 && arg[0] == "action" {
+ switch arg[1] {
+ case "启动", "start":
+ arg = []string{arg[4]}
+ case "停止", "stop":
+ m.Cmd(ice.WEB_SPACE, kit.Select(m.Option("name"), arg, 4), "exit", "1")
+ m.Event(ice.DREAM_CLOSE, arg[4])
+ return
+ }
+ }
+
+ if len(arg) == 0 {
+ // 任务列表
+ m.Cmdy("nfs.dir", m.Conf(ice.WEB_DREAM, "meta.path"), "time name")
+ m.Table(func(index int, value map[string]string, head []string) {
+ if m.Richs(ice.WEB_SPACE, nil, value["name"], func(key string, value map[string]interface{}) {
+ m.Push("type", value["type"])
+ m.Push("status", "start")
+ }) == nil {
+ m.Push("type", "none")
+ m.Push("status", "stop")
+ }
+ })
+ m.Sort("name")
+ m.Sort("status")
+ return
+ }
+
+ // 规范命名
+ if !strings.Contains(arg[0], "-") || !strings.HasPrefix(arg[0], "20") {
+ arg[0] = m.Time("20060102-") + arg[0]
+ }
+
+ // 创建目录
+ p := path.Join(m.Conf(ice.WEB_DREAM, "meta.path"), arg[0])
+ os.MkdirAll(p, 0777)
+
+ if b, e := ioutil.ReadFile(path.Join(p, m.Conf(ice.GDB_SIGNAL, "meta.pid"))); e == nil {
+ if s, e := os.Stat("/proc/" + string(b)); e == nil && s.IsDir() {
+ m.Info("already exists %v", string(b))
+ return
+ }
+ }
+
+ if m.Richs(ice.WEB_SPACE, nil, arg[0], nil) == nil {
+ // 启动任务
+ m.Option("cmd_dir", p)
+ m.Option("cmd_type", "daemon")
+ m.Optionv("cmd_env",
+ "ctx_dev", m.Conf(ice.CLI_RUNTIME, "conf.ctx_dev"),
+ "ctx_log", "boot.log", "ctx_mod", "ctx,log,gdb,ssh",
+ "PATH", kit.Path(path.Join(p, "bin"))+":"+os.Getenv("PATH"),
+ )
+ m.Cmd(m.Confv(ice.WEB_DREAM, "meta.cmd"), "self", arg[0])
+ time.Sleep(time.Second * 1)
+ m.Event(ice.DREAM_START, arg...)
+ }
+ m.Cmdy("nfs.dir", p)
+ }},
+ },
+ }, nil)
+}
diff --git a/base/web/serve.go b/base/web/serve.go
new file mode 100644
index 00000000..c0ac8a34
--- /dev/null
+++ b/base/web/serve.go
@@ -0,0 +1,245 @@
+package web
+
+import (
+ ice "github.com/shylinux/icebergs"
+ "github.com/shylinux/icebergs/base/aaa"
+ "github.com/shylinux/icebergs/base/cli"
+ "github.com/shylinux/icebergs/base/tcp"
+ kit "github.com/shylinux/toolkits"
+
+ "encoding/json"
+ "net/http"
+ "net/url"
+ "os"
+ "strings"
+)
+
+func Login(msg *ice.Message, w http.ResponseWriter, r *http.Request) bool {
+ msg.Option(ice.MSG_USERNAME, "")
+ msg.Option(ice.MSG_USERROLE, "")
+
+ if msg.Options(ice.MSG_SESSID) {
+ // 会话认证
+ aaa.SessCheck(msg, msg.Option(ice.MSG_SESSID))
+ }
+
+ if !msg.Options(ice.MSG_USERNAME) && tcp.IPIsLocal(msg, msg.Option(ice.MSG_USERIP)) {
+ // 自动认证
+ if aaa.UserLogin(msg, cli.UserName, cli.PassWord) {
+ Render(msg, "cookie", msg.Option(ice.MSG_SESSID))
+ }
+ }
+
+ if s, ok := msg.Target().Commands[ice.WEB_LOGIN]; ok {
+ // 权限检查
+ msg.Target().Run(msg, s, ice.WEB_LOGIN, kit.Simple(msg.Optionv("cmds"))...)
+
+ } else if ls := strings.Split(msg.Option(ice.MSG_USERURL), "/"); msg.Conf(SERVE, kit.Keys("meta.black", ls[1])) == "true" {
+ return false // black
+
+ } else if msg.Conf(SERVE, kit.Keys("meta.white", ls[1])) == "true" {
+ return true // white
+
+ } else {
+ if msg.Warn(!msg.Options(ice.MSG_USERNAME), "not login %s", msg.Option(ice.MSG_USERURL)) {
+ msg.Render("status", 401, "not login")
+ return false
+ }
+ if !msg.Right(msg.Option(ice.MSG_USERURL)) {
+ msg.Render("status", 403, "not auth")
+ return false
+ }
+ }
+
+ return msg.Option(ice.MSG_USERURL) != ""
+}
+func Trans(web *Frame, m *ice.Message, key string, cmd *ice.Command) {
+ web.HandleFunc(key, func(w http.ResponseWriter, r *http.Request) {
+ m.TryCatch(m.Spawns(), true, func(msg *ice.Message) {
+ defer func() { msg.Cost("%s %v %v", r.URL.Path, msg.Optionv("cmds"), msg.Format("append")) }()
+ if u, e := url.Parse(r.Header.Get("Referer")); e == nil {
+ for k, v := range u.Query() {
+ msg.Logs("refer", k, v)
+ msg.Option(k, v)
+ }
+ }
+
+ // 用户请求
+ msg.Option(ice.MSG_USERWEB, m.Conf(SHARE, "meta.domain"))
+ msg.Option(ice.MSG_USERIP, r.Header.Get(ice.MSG_USERIP))
+ msg.Option(ice.MSG_USERUA, r.Header.Get("User-Agent"))
+ msg.Option(ice.MSG_USERURL, r.URL.Path)
+ if msg.R, msg.W = r, w; r.Header.Get("X-Real-Port") != "" {
+ msg.Option(ice.MSG_USERADDR, msg.Option(ice.MSG_USERIP)+":"+r.Header.Get("X-Real-Port"))
+ } else {
+ msg.Option(ice.MSG_USERADDR, r.RemoteAddr)
+ }
+
+ // 请求变量
+ msg.Option(ice.MSG_SESSID, "")
+ msg.Option(ice.MSG_OUTPUT, "")
+ for _, v := range r.Cookies() {
+ msg.Option(v.Name, v.Value)
+ }
+
+ // 解析引擎
+ switch r.Header.Get("Content-Type") {
+ case "application/json":
+ var data interface{}
+ if e := json.NewDecoder(r.Body).Decode(&data); !msg.Warn(e != nil, "%s", e) {
+ msg.Optionv(ice.MSG_USERDATA, data)
+ msg.Logs("json", "value", kit.Formats(data))
+ }
+
+ switch d := data.(type) {
+ case map[string]interface{}:
+ for k, v := range d {
+ msg.Optionv(k, v)
+ }
+ }
+ default:
+ r.ParseMultipartForm(kit.Int64(kit.Select(r.Header.Get("Content-Length"), "4096")))
+ if r.ParseForm(); len(r.PostForm) > 0 {
+ for k, v := range r.PostForm {
+ msg.Logs("form", k, v)
+ }
+ }
+ }
+
+ // 请求参数
+ for k, v := range r.Form {
+ if msg.Optionv(k, v); k == ice.MSG_SESSID {
+ msg.Render("cookie", v[0])
+ }
+ }
+
+ // 请求命令
+ if msg.Option(ice.MSG_USERPOD, msg.Option("pod")); msg.Optionv("cmds") == nil {
+ if p := strings.TrimPrefix(msg.Option(ice.MSG_USERURL), key); p != "" {
+ msg.Optionv("cmds", strings.Split(p, "/"))
+ }
+ }
+
+ // 执行命令
+ if cmds := kit.Simple(msg.Optionv("cmds")); Login(msg, w, r) {
+ msg.Option("_option", msg.Optionv(ice.MSG_OPTION))
+ msg.Target().Run(msg, cmd, msg.Option(ice.MSG_USERURL), cmds...)
+ }
+
+ // 渲染引擎
+ _args, _ := msg.Optionv(ice.MSG_ARGS).([]interface{})
+ Render(msg, msg.Option(ice.MSG_OUTPUT), _args...)
+ })
+ })
+}
+func (web *Frame) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+ m := web.m
+
+ if r.Header.Get("index.module") == "" {
+ // 解析地址
+ if ip := r.Header.Get("X-Forwarded-For"); ip != "" {
+ r.Header.Set(ice.MSG_USERIP, ip)
+ } else if ip := r.Header.Get("X-Real-Ip"); ip != "" {
+ r.Header.Set(ice.MSG_USERIP, ip)
+ } 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])
+ }
+ m.Info("").Info("%s %s %s", r.Header.Get(ice.MSG_USERIP), r.Method, r.URL)
+
+ r.Header.Set("index.module", m.Target().Name)
+ r.Header.Set("index.path", r.URL.Path)
+ r.Header.Set("index.url", r.URL.String())
+
+ if m.Conf(SERVE, "meta.logheaders") == "true" {
+ // 请求参数
+ for k, v := range r.Header {
+ m.Info("%s: %v", k, kit.Format(v))
+ }
+ m.Info(" ")
+
+ defer func() {
+ // 响应参数
+ for k, v := range w.Header() {
+ m.Info("%s: %v", k, kit.Format(v))
+ }
+ m.Info(" ")
+ }()
+ }
+ }
+
+ if strings.HasPrefix(r.URL.Path, "/debug") {
+ r.URL.Path = strings.Replace(r.URL.Path, "/debug", "/code", -1)
+ }
+
+ if r.URL.Path == "/" && m.Conf(SERVE, "meta.init") != "true" {
+ if _, e := os.Stat(m.Conf(SERVE, "meta.volcanos.path")); e == nil {
+ // 初始化成功
+ m.Conf(SERVE, "meta.init", "true")
+ }
+ m.W = w
+ Render(m, "refresh", m.Conf(SERVE, "meta.volcanos.refresh"))
+ m.Event(ice.SYSTEM_INIT)
+ m.W = nil
+ } else if r.URL.Path == "/share" && r.Method == "GET" {
+ http.ServeFile(w, r, m.Conf(SERVE, "meta.page.share"))
+ } else {
+ web.ServeMux.ServeHTTP(w, r)
+ }
+}
+func init() {
+ Index.Merge(&ice.Context{
+ Configs: map[string]*ice.Config{
+ ice.WEB_SERVE: {Name: "serve", Help: "服务器", Value: kit.Data(
+ "init", "false", "logheaders", "false",
+ "black", kit.Dict(),
+ "white", kit.Dict(
+ "login", true,
+ "share", true,
+ "space", true,
+ "route", true,
+ "static", true,
+ "plugin", true,
+ "publish", true,
+ ),
+
+ "title", "github.com/shylinux/contexts",
+ "legal", []interface{}{`shylinuxc@gmail.com`},
+
+ "static", kit.Dict("/", "usr/volcanos/"),
+ "volcanos", kit.Dict("path", "usr/volcanos", "branch", "master",
+ "repos", "https://github.com/shylinux/volcanos",
+ "require", ".ish/pluged",
+ "refresh", "5",
+ ), "page", kit.Dict(
+ "index", "usr/volcanos/page/index.html",
+ "share", "usr/volcanos/page/share.html",
+ ), "publish", "usr/publish/",
+
+ "template", kit.Dict("path", "usr/template", "list", []interface{}{
+ `{{define "raw"}}{{.Result}}{{end}}`,
+ }),
+ )},
+ },
+ Commands: map[string]*ice.Command{
+ ice.WEB_SERVE: {Name: "serve [random] [ups...]", Help: "服务器", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
+ if cli.NodeType(m, ice.WEB_SERVER, cli.HostName); len(arg) > 0 && arg[0] == "random" {
+ cli.NodeType(m, ice.WEB_SERVER, cli.PathName)
+ // 随机端口
+ SpideCreate(m, "self", "http://random")
+ arg = arg[1:]
+ }
+
+ // 启动服务
+ m.Target().Start(m, "self")
+ defer m.Cmd(ice.WEB_SPACE, "connect", "self")
+ m.Sleep("1s")
+
+ // 连接服务
+ for _, k := range arg {
+ m.Cmd(ice.WEB_SPACE, "connect", k)
+ }
+ }},
+ }}, nil)
+}
diff --git a/base/web/share.go b/base/web/share.go
index 973178bc..3dceb53b 100644
--- a/base/web/share.go
+++ b/base/web/share.go
@@ -10,8 +10,6 @@ import (
"strings"
)
-var SHARE = ice.Name(kit.MDB_SHARE, Index)
-
func _share_list(m *ice.Message, key string, fields ...string) {
if key == "" {
m.Grows(SHARE, nil, "", "", func(index int, value map[string]interface{}) {
@@ -85,7 +83,7 @@ func _share_remote(m *ice.Message, pod string, arg ...string) {
m.Cmdy(ice.WEB_SPACE, pod, "web./publish/", arg)
m.Render(ice.RENDER_RESULT)
}
-func _share_create(m *ice.Message, kind, name, text string, arg ...string) {
+func _share_create(m *ice.Message, kind, name, text string, arg ...string) string {
for _, k := range []string{"river", "storm"} {
arg = append(arg, k, m.Option(k))
}
@@ -103,6 +101,7 @@ func _share_create(m *ice.Message, kind, name, text string, arg ...string) {
))
m.Log_CREATE(kit.MDB_SHARE, h, kit.MDB_TYPE, kind, kit.MDB_NAME, name)
m.Echo(h)
+ return h
}
func _share_story(m *ice.Message, value map[string]interface{}, arg ...string) map[string]interface{} {
@@ -221,6 +220,11 @@ func _trash(m *ice.Message, arg ...string) {
}
}
}
+
+func ShareCreate(m *ice.Message, kind, name, text string, arg ...string) string {
+ return _share_create(m, kind, name, text, arg...)
+}
+
func init() {
Index.Merge(&ice.Context{
Configs: map[string]*ice.Config{
diff --git a/base/web/space.go b/base/web/space.go
index b5a6b06f..07b93f5e 100644
--- a/base/web/space.go
+++ b/base/web/space.go
@@ -58,7 +58,7 @@ func _space_dial(m *ice.Message, dev, name string, arg ...string) {
"socket", s,
))
msg.Log(ice.LOG_CMDS, "%d conn %s success %s", i, dev, u)
- if i = 0; web.HandleWSS(msg, true, s, dev) {
+ if i = 0; HandleWSS(msg, true, web.send, s, dev) {
break
}
}
@@ -112,6 +112,70 @@ func _space_send(m *ice.Message, space string, arg ...string) {
}) == nil, "not found %s", space)
}
+func HandleWSS(m *ice.Message, safe bool, send map[string]*ice.Message, c *websocket.Conn, name string) bool {
+ for running := true; running; {
+ if t, b, e := c.ReadMessage(); m.Warn(e != nil, "space recv %d msg %v", t, e) {
+ // 解析失败
+ break
+ } else {
+ socket, msg := c, m.Spawns(b)
+ target := kit.Simple(msg.Optionv(ice.MSG_TARGET))
+ source := kit.Simple(msg.Optionv(ice.MSG_SOURCE), name)
+ msg.Info("recv %v<-%v %s %v", target, source, msg.Detailv(), msg.Format("meta"))
+
+ if len(target) == 0 {
+ msg.Option(ice.MSG_USERROLE, msg.Cmdx(ice.AAA_ROLE, "check", msg.Option(ice.MSG_USERNAME)))
+ msg.Logs(ice.LOG_AUTH, "role", msg.Option(ice.MSG_USERROLE), "user", msg.Option(ice.MSG_USERNAME))
+ if msg.Optionv(ice.MSG_HANDLE, "true"); !msg.Warn(!safe, "no right") {
+ // 本地执行
+ m.Option("_dev", name)
+ msg = msg.Cmd()
+ msg.Set("_option")
+ msg.Set("_option")
+ }
+ if source, target = []string{}, kit.Revert(source)[1:]; msg.Detail() == "exit" {
+ // 重启进程
+ return true
+ }
+ } else if msg.Richs(ice.WEB_SPACE, nil, target[0], func(key string, value map[string]interface{}) {
+ // 查询节点
+ if s, ok := value["socket"].(*websocket.Conn); ok {
+ socket, source, target = s, source, target[1:]
+ } else {
+ socket, source, target = s, source, target[1:]
+ }
+ }) != nil {
+ // 转发报文
+
+ } else if res, ok := send[msg.Option(ice.MSG_TARGET)]; len(target) == 1 && ok {
+ // 接收响应
+ delete(send, msg.Option(ice.MSG_TARGET))
+ res.Cost("%v->%v %v %v", target, source, res.Detailv(), msg.Format("append"))
+ res.Back(msg)
+ continue
+
+ } else if msg.Warn(msg.Option("_handle") == "true", "space miss") {
+ // 回复失败
+ continue
+
+ } else {
+ // 下发失败
+ msg.Warn(true, "space error")
+ source, target = []string{}, kit.Revert(source)[1:]
+ }
+
+ // 发送报文
+ msg.Optionv(ice.MSG_SOURCE, source)
+ msg.Optionv(ice.MSG_TARGET, target)
+ socket.WriteMessage(t, []byte(msg.Format("meta")))
+ target = append([]string{name}, target...)
+ msg.Info("send %v %v->%v %v %v", t, source, target, msg.Detailv(), msg.Format("meta"))
+ msg.Cost("%v->%v %v %v", source, target, msg.Detailv(), msg.Format("append"))
+ }
+ }
+ return false
+}
+
func init() {
Index.Merge(&ice.Context{
Configs: map[string]*ice.Config{
@@ -180,7 +244,7 @@ func init() {
m.Gos(m, func(m *ice.Message) {
// 监听消息
m.Event(ice.SPACE_START, m.Option("node"), m.Option("name"))
- m.Target().Server().(*Frame).HandleWSS(m, false, s, m.Option("name"))
+ HandleWSS(m, false, m.Target().Server().(*Frame).send, s, m.Option("name"))
m.Log(ice.LOG_CLOSE, "%s: %s", m.Option(kit.MDB_NAME), kit.Format(m.Confv(ice.WEB_SPACE, kit.Keys(kit.MDB_HASH, h))))
m.Event(ice.SPACE_CLOSE, m.Option("node"), m.Option("name"))
m.Confv(ice.WEB_SPACE, kit.Keys(kit.MDB_HASH, h), "")
diff --git a/base/web/spide.go b/base/web/spide.go
new file mode 100644
index 00000000..3e1f1f73
--- /dev/null
+++ b/base/web/spide.go
@@ -0,0 +1,273 @@
+package web
+
+import (
+ ice "github.com/shylinux/icebergs"
+ "github.com/shylinux/icebergs/base/tcp"
+ kit "github.com/shylinux/toolkits"
+
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "mime/multipart"
+ "net/http"
+ "net/url"
+ "os"
+ "path"
+ "strings"
+)
+
+func _spide_list(m *ice.Message, name string) {
+ if name == "" {
+ m.Richs(SPIDE, nil, kit.MDB_FOREACH, func(key string, value map[string]interface{}) {
+ m.Push(key, value["client"], []string{"name", "share", "login", "method", "url"})
+ })
+ m.Sort("name")
+ return
+ }
+
+ m.Richs(SPIDE, nil, name, func(key string, value map[string]interface{}) {
+ m.Push("detail", value)
+ if kit.Value(value, "client.share") != nil {
+ m.Push("key", "share")
+ m.Push("value", fmt.Sprintf(m.Conf(SHARE, "meta.template.text"), m.Conf(SHARE, "meta.domain"), kit.Value(value, "client.share")))
+ }
+ })
+}
+func _spide_show(m *ice.Message, name string) {
+}
+func _spide_login(m *ice.Message, name string) {
+ m.Richs(SPIDE, nil, name, func(key string, value map[string]interface{}) {
+ msg := m.Cmd(SPIDE, name, "msg", "/route/login", "login")
+ if msg.Append(ice.MSG_USERNAME) != "" {
+ m.Echo(msg.Append(ice.MSG_USERNAME))
+ return
+ }
+ if msg.Result() != "" {
+ kit.Value(value, "client.login", msg.Result())
+ kit.Value(value, "client.share", m.Cmdx(SHARE, ice.TYPE_SPIDE, name,
+ kit.Format("%s?sessid=%s", kit.Value(value, "client.url"), kit.Value(value, "cookie.sessid"))))
+ }
+ m.Render(ice.RENDER_QRCODE, kit.Dict(
+ kit.MDB_TYPE, "login", kit.MDB_NAME, name,
+ kit.MDB_TEXT, kit.Value(value, "cookie.sessid"),
+ ))
+ })
+}
+func _spide_create(m *ice.Message, name, address string, arg ...string) {
+ if uri, e := url.Parse(address); e == nil && address != "" {
+ if uri.Host == "random" {
+ uri.Host = ":" + tcp.TCPPort(m)
+ address = strings.Replace(address, "random", uri.Host, -1)
+ }
+
+ if m.Richs(SPIDE, nil, name, func(key string, value map[string]interface{}) {
+ kit.Value(value, "client.hostname", uri.Host)
+ kit.Value(value, "client.url", address)
+ }) == nil {
+ dir, file := path.Split(uri.EscapedPath())
+ m.Rich(SPIDE, nil, kit.Dict(
+ "cookie", kit.Dict(), "header", kit.Dict(), "client", kit.Dict(
+ "share", ShareCreate(m.Spawn(), ice.TYPE_SPIDE, name, address),
+ "name", name, "url", address, "method", "POST",
+ "protocol", uri.Scheme, "hostname", uri.Host,
+ "path", dir, "file", file, "query", uri.RawQuery,
+ "timeout", "100s", "logheaders", false,
+ ),
+ ))
+ }
+ m.Log_CREATE(SPIDE, name, "address", address)
+ }
+}
+
+func SpideCreate(m *ice.Message, name, address string, arg ...string) {
+ _spide_create(m, name, address, arg...)
+}
+func init() {
+ Index.Merge(&ice.Context{
+ Configs: map[string]*ice.Config{
+ SPIDE: {Name: "spide", Help: "蜘蛛侠", Value: kit.Data(kit.MDB_SHORT, "client.name")},
+ },
+ Commands: map[string]*ice.Command{
+ SPIDE: {Name: "spide name=auto [action:select=msg|raw|cache] [method:select=POST|GET] url [format:select=json|form|part|data|file] arg... auto", Help: "蜘蛛侠", Action: map[string]*ice.Action{
+ kit.MDB_CREATE: {Name: "create name address", Help: "", Hand: func(m *ice.Message, arg ...string) {
+ _spide_create(m, arg[0], arg[1])
+ }},
+ "login": {Name: "login name", Help: "", Hand: func(m *ice.Message, arg ...string) {
+ _spide_login(m, arg[0])
+ }},
+ }, Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
+ if len(arg) < 2 || len(arg) > 3 && arg[3] == "" {
+ _spide_list(m, kit.Select("", arg, 1))
+ return
+ }
+
+ m.Richs(SPIDE, nil, arg[0], func(key string, value map[string]interface{}) {
+ client := value["client"].(map[string]interface{})
+ // 缓存数据
+ cache := ""
+ switch arg[1] {
+ case "raw":
+ cache, arg = arg[1], arg[1:]
+ case "msg":
+ cache, arg = arg[1], arg[1:]
+ case "cache":
+ cache, arg = arg[1], arg[1:]
+ }
+
+ // 请求方法
+ method := kit.Select("POST", client["method"])
+ switch arg = arg[1:]; arg[0] {
+ case "POST":
+ method, arg = "POST", arg[1:]
+ case "GET":
+ method, arg = "GET", arg[1:]
+ }
+
+ // 请求地址
+ uri, arg := arg[0], arg[1:]
+
+ // 渲染引擎
+ head := map[string]string{}
+ body, ok := m.Optionv("body").(io.Reader)
+ if !ok && len(arg) > 0 && method != "GET" {
+ switch arg[0] {
+ case "file":
+ if f, e := os.Open(arg[1]); m.Warn(e != nil, "%s", e) {
+ return
+ } else {
+ defer f.Close()
+ body, arg = f, arg[2:]
+ }
+ case "data":
+ body, arg = bytes.NewBufferString(arg[1]), arg[2:]
+ case "part":
+ buf := &bytes.Buffer{}
+ mp := multipart.NewWriter(buf)
+ for i := 1; i < len(arg)-1; i += 2 {
+ if strings.HasPrefix(arg[i+1], "@") {
+ if f, e := os.Open(arg[i+1][1:]); m.Assert(e) {
+ defer f.Close()
+ if p, e := mp.CreateFormFile(arg[i], path.Base(arg[i+1][1:])); m.Assert(e) {
+ io.Copy(p, f)
+ }
+ }
+ } else {
+ mp.WriteField(arg[i], arg[i+1])
+ }
+ }
+ mp.Close()
+ head["Content-Type"] = mp.FormDataContentType()
+ body = buf
+ case "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["Content-Type"] = "application/x-www-form-urlencoded"
+ case "json":
+ arg = arg[1:]
+ fallthrough
+ default:
+ data := map[string]interface{}{}
+ 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["Content-Type"] = "application/json"
+ body = bytes.NewBuffer(b)
+ }
+ m.Log(ice.LOG_EXPORT, "json: %s", kit.Format(data))
+ }
+ arg = arg[:0]
+ } else {
+ body = bytes.NewBuffer([]byte{})
+ }
+
+ // 请求地址
+ uri = kit.MergeURL2(kit.Format(client["url"]), uri, arg)
+ req, e := http.NewRequest(method, uri, body)
+ m.Info("%s %s", req.Method, req.URL)
+ m.Assert(e)
+
+ // 请求变量
+ kit.Fetch(value["cookie"], func(key string, value string) {
+ req.AddCookie(&http.Cookie{Name: key, Value: value})
+ m.Info("%s: %s", key, value)
+ })
+ kit.Fetch(value["header"], func(key string, value string) {
+ req.Header.Set(key, value)
+ })
+ list := kit.Simple(m.Optionv("header"))
+ for i := 0; i < len(list)-1; i += 2 {
+ req.Header.Set(list[i], list[i+1])
+ }
+ for k, v := range head {
+ req.Header.Set(k, v)
+ }
+
+ // 请求代理
+ web := m.Target().Server().(*Frame)
+ if web.Client == nil {
+ web.Client = &http.Client{Timeout: kit.Duration(kit.Format(client["timeout"]))}
+ }
+ if method == "POST" {
+ m.Info("%s: %s", req.Header.Get("Content-Length"), req.Header.Get("Content-Type"))
+ }
+
+ // 发送请求
+ res, e := web.Client.Do(req)
+ if m.Warn(e != nil, "%s", e) {
+ return
+ }
+
+ // 检查结果
+ if m.Cost("%s %s: %s", res.Status, res.Header.Get("Content-Length"), res.Header.Get("Content-Type")); m.Warn(res.StatusCode != http.StatusOK, "%s", res.Status) {
+ return
+ }
+
+ // 缓存变量
+ for _, v := range res.Cookies() {
+ kit.Value(value, "cookie."+v.Name, v.Value)
+ m.Log(ice.LOG_IMPORT, "%s: %s", v.Name, v.Value)
+ }
+
+ // 解析引擎
+ switch cache {
+ case "cache":
+ m.Optionv("response", res)
+ CacheCatch(m, res.Header.Get("Content-Type"), uri)
+ m.Echo(m.Append("data"))
+ case "raw":
+ if b, e := ioutil.ReadAll(res.Body); m.Assert(e) {
+ m.Echo(string(b))
+ }
+ case "msg":
+ var data map[string][]string
+ m.Assert(json.NewDecoder(res.Body).Decode(&data))
+ m.Info("res: %s", kit.Formats(data))
+ for _, k := range data[ice.MSG_APPEND] {
+ for i := range data[k] {
+ m.Push(k, data[k][i])
+ }
+ }
+ m.Resultv(data[ice.MSG_RESULT])
+ default:
+ if strings.HasPrefix(res.Header.Get("Content-Type"), "text/html") {
+ b, _ := ioutil.ReadAll(res.Body)
+ m.Echo(string(b))
+ break
+ }
+
+ var data interface{}
+ m.Assert(json.NewDecoder(res.Body).Decode(&data))
+ data = kit.KeyValue(map[string]interface{}{}, "", data)
+ m.Info("res: %s", kit.Formats(data))
+ m.Push("", data)
+ }
+ })
+ }},
+ }}, nil)
+}
diff --git a/base/web/web.go b/base/web/web.go
index a0806b6a..c1226e27 100644
--- a/base/web/web.go
+++ b/base/web/web.go
@@ -1,31 +1,23 @@
package web
import (
- "github.com/gorilla/websocket"
ice "github.com/shylinux/icebergs"
- "github.com/shylinux/icebergs/base/aaa"
- "github.com/shylinux/icebergs/base/cli"
- "github.com/shylinux/icebergs/base/tcp"
kit "github.com/shylinux/toolkits"
"github.com/skip2/go-qrcode"
- "bytes"
- "encoding/json"
"fmt"
- "io"
- "io/ioutil"
- "mime/multipart"
"net/http"
- "net/url"
- "os"
"path"
"strings"
"sync"
- "text/template"
"time"
)
-var SERVE = ice.Name("serve", Index)
+const (
+ SPIDE = "spide"
+ SERVE = "serve"
+ SHARE = "share"
+)
type Frame struct {
*http.Client
@@ -99,306 +91,6 @@ func Render(msg *ice.Message, cmd string, args ...interface{}) {
}
msg.Append(ice.MSG_OUTPUT, ice.RENDER_OUTPUT)
}
-func IsLocalIP(msg *ice.Message, ip string) (ok bool) {
- if ip == "::1" || strings.HasPrefix(ip, "127.") {
- return true
- }
-
- msg.Log_AUTH("ip", ip)
- if msg.Richs(SERVE, kit.Keys("meta.white"), ip, nil) != nil {
- msg.Log_AUTH("ip", ip)
- return true
- }
-
- msg.Cmd("tcp.ifconfig").Table(func(index int, value map[string]string, head []string) {
- if value["ip"] == ip {
- ok = true
- }
- })
- return ok
-}
-
-func (web *Frame) Login(msg *ice.Message, w http.ResponseWriter, r *http.Request) bool {
- msg.Option(ice.MSG_USERNAME, "")
- msg.Option(ice.MSG_USERROLE, "")
-
- if msg.Options(ice.MSG_SESSID) {
- // 会话认证
- sub := aaa.SessCheck(msg.Spawn(), msg.Option(ice.MSG_SESSID))
- msg.Log_AUTH(
- aaa.USERROLE, msg.Option(ice.MSG_USERROLE, sub.Append(aaa.USERROLE)),
- aaa.USERNAME, msg.Option(ice.MSG_USERNAME, sub.Append(aaa.USERNAME)),
- )
- }
-
- if !msg.Options(ice.MSG_USERNAME) && tcp.IPIsLocal(msg, msg.Option(ice.MSG_USERIP)) {
- // 自动认证
- if aaa.UserLogin(msg, cli.UserName, cli.PassWord) {
- Render(msg, "cookie", msg.Option(ice.MSG_SESSID))
- }
- }
-
- if s, ok := msg.Target().Commands[ice.WEB_LOGIN]; ok {
- // 权限检查
- msg.Target().Run(msg, s, ice.WEB_LOGIN, kit.Simple(msg.Optionv("cmds"))...)
- } else if ls := strings.Split(msg.Option(ice.MSG_USERURL), "/"); kit.IndexOf([]string{
- "static", "plugin", "login", "space", "route", "share",
- "publish",
- }, ls[1]) > -1 {
-
- } else {
- if msg.Warn(!msg.Options(ice.MSG_USERNAME), "not login %s", msg.Option(ice.MSG_USERURL)) {
- msg.Render("status", 401, "not login")
- return false
- }
- if !msg.Right(msg.Option(ice.MSG_USERURL)) {
- msg.Render("status", 403, "not auth")
- return false
- }
- }
-
- return msg.Option(ice.MSG_USERURL) != ""
-}
-func (web *Frame) HandleWSS(m *ice.Message, safe bool, c *websocket.Conn, name string) bool {
- for running := true; running; {
- if t, b, e := c.ReadMessage(); m.Warn(e != nil, "space recv %d msg %v", t, e) {
- // 解析失败
- break
- } else {
- socket, msg := c, m.Spawns(b)
- target := kit.Simple(msg.Optionv(ice.MSG_TARGET))
- source := kit.Simple(msg.Optionv(ice.MSG_SOURCE), name)
- msg.Info("recv %v<-%v %s %v", target, source, msg.Detailv(), msg.Format("meta"))
-
- if len(target) == 0 {
- msg.Option(ice.MSG_USERROLE, msg.Cmdx(ice.AAA_ROLE, "check", msg.Option(ice.MSG_USERNAME)))
- msg.Logs(ice.LOG_AUTH, "role", msg.Option(ice.MSG_USERROLE), "user", msg.Option(ice.MSG_USERNAME))
- if msg.Optionv(ice.MSG_HANDLE, "true"); !msg.Warn(!safe, "no right") {
- // 本地执行
- m.Option("_dev", name)
- msg = msg.Cmd()
- msg.Set("_option")
- msg.Set("_option")
- }
- if source, target = []string{}, kit.Revert(source)[1:]; msg.Detail() == "exit" {
- // 重启进程
- return true
- }
- } else if msg.Richs(ice.WEB_SPACE, nil, target[0], func(key string, value map[string]interface{}) {
- // 查询节点
- if s, ok := value["socket"].(*websocket.Conn); ok {
- socket, source, target = s, source, target[1:]
- } else {
- socket, source, target = s, source, target[1:]
- }
- }) != nil {
- // 转发报文
-
- } else if res, ok := web.send[msg.Option(ice.MSG_TARGET)]; len(target) == 1 && ok {
- // 接收响应
- delete(web.send, msg.Option(ice.MSG_TARGET))
- res.Cost("%v->%v %v %v", target, source, res.Detailv(), msg.Format("append"))
- res.Back(msg)
- continue
-
- } else if msg.Warn(msg.Option("_handle") == "true", "space miss") {
- // 回复失败
- continue
-
- } else {
- // 下发失败
- msg.Warn(true, "space error")
- source, target = []string{}, kit.Revert(source)[1:]
- }
-
- // 发送报文
- msg.Optionv(ice.MSG_SOURCE, source)
- msg.Optionv(ice.MSG_TARGET, target)
- socket.WriteMessage(t, []byte(msg.Format("meta")))
- target = append([]string{name}, target...)
- msg.Info("send %v %v->%v %v %v", t, source, target, msg.Detailv(), msg.Format("meta"))
- msg.Cost("%v->%v %v %v", source, target, msg.Detailv(), msg.Format("append"))
- }
- }
- return false
-}
-func (web *Frame) HandleCGI(m *ice.Message, alias map[string]interface{}, which string) *template.Template {
- cgi := template.FuncMap{}
-
- tmpl := template.New(ice.WEB_TMPL)
- cb := func(k string, p []string, v *ice.Command) {
- cgi[k] = func(arg ...interface{}) (res interface{}) {
- m.TryCatch(m.Spawn(), true, func(msg *ice.Message) {
- msg.Target().Run(msg, v, k, kit.Simple(p, arg)...)
-
- buffer := bytes.NewBuffer([]byte{})
- m.Assert(tmpl.ExecuteTemplate(buffer, msg.Option(ice.WEB_TMPL), msg))
- res = string(buffer.Bytes())
- })
- return
- }
- }
- for k, v := range alias {
- list := kit.Simple(v)
- if v, ok := m.Target().Commands[list[0]]; ok {
- cb(k, list[1:], v)
- }
- }
- for k, v := range m.Target().Commands {
- if strings.HasPrefix(k, "/") || strings.HasPrefix(k, "_") {
- continue
- }
- cb(k, nil, v)
- }
-
- tmpl = tmpl.Funcs(cgi)
- // tmpl = template.Must(tmpl.ParseGlob(path.Join(m.Conf(ice.WEB_SERVE, ice.Meta("template", "path")), "/*.tmpl")))
- // tmpl = template.Must(tmpl.ParseGlob(path.Join(m.Conf(ice.WEB_SERVE, ice.Meta("template", "path")), m.Target().Name, "/*.tmpl")))
- tmpl, e := tmpl.ParseFiles(which)
- if e != nil {
- }
- // m.Confm(ice.WEB_SERVE, ice.Meta("template", "list"), func(index int, value string) { tmpl = template.Must(tmpl.Parse(value)) })
- return tmpl
-}
-func (web *Frame) HandleCmd(m *ice.Message, key string, cmd *ice.Command) {
- web.HandleFunc(key, func(w http.ResponseWriter, r *http.Request) {
- m.TryCatch(m.Spawns(), true, func(msg *ice.Message) {
- defer func() { msg.Cost("%s %v %v", r.URL.Path, msg.Optionv("cmds"), msg.Format("append")) }()
- if u, e := url.Parse(r.Header.Get("Referer")); e == nil {
- for k, v := range u.Query() {
- msg.Logs("refer", k, v)
- msg.Option(k, v)
- }
- }
-
- // 用户请求
- msg.Option(ice.MSG_USERWEB, m.Conf(ice.WEB_SHARE, "meta.domain"))
- msg.Option(ice.MSG_USERIP, r.Header.Get(ice.MSG_USERIP))
- msg.Option(ice.MSG_USERUA, r.Header.Get("User-Agent"))
- msg.Option(ice.MSG_USERURL, r.URL.Path)
- if msg.R, msg.W = r, w; r.Header.Get("X-Real-Port") != "" {
- msg.Option(ice.MSG_USERADDR, msg.Option(ice.MSG_USERIP)+":"+r.Header.Get("X-Real-Port"))
- } else {
- msg.Option(ice.MSG_USERADDR, r.RemoteAddr)
- }
-
- // 请求变量
- msg.Option(ice.MSG_SESSID, "")
- msg.Option(ice.MSG_OUTPUT, "")
- for _, v := range r.Cookies() {
- msg.Option(v.Name, v.Value)
- }
-
- // 解析引擎
- switch r.Header.Get("Content-Type") {
- case "application/json":
- var data interface{}
- if e := json.NewDecoder(r.Body).Decode(&data); !msg.Warn(e != nil, "%s", e) {
- msg.Optionv(ice.MSG_USERDATA, data)
- msg.Info("%s", kit.Formats(data))
- }
-
- switch d := data.(type) {
- case map[string]interface{}:
- for k, v := range d {
- msg.Optionv(k, v)
- }
- }
- default:
- r.ParseMultipartForm(kit.Int64(kit.Select(r.Header.Get("Content-Length"), "4096")))
- if r.ParseForm(); len(r.PostForm) > 0 {
- for k, v := range r.PostForm {
- msg.Logs("form", k, v)
- }
- }
- }
-
- // 请求参数
- for k, v := range r.Form {
- if msg.Optionv(k, v); k == ice.MSG_SESSID {
- msg.Render("cookie", v[0])
- }
- }
-
- // 请求命令
- if msg.Option(ice.MSG_USERPOD, msg.Option("pod")); msg.Optionv("cmds") == nil {
- if p := strings.TrimPrefix(msg.Option(ice.MSG_USERURL), key); p != "" {
- msg.Optionv("cmds", strings.Split(p, "/"))
- }
- }
-
- // 执行命令
- if cmds := kit.Simple(msg.Optionv("cmds")); web.Login(msg, w, r) {
- msg.Option("_option", msg.Optionv(ice.MSG_OPTION))
- msg.Target().Run(msg, cmd, msg.Option(ice.MSG_USERURL), cmds...)
- }
-
- // 渲染引擎
- _args, _ := msg.Optionv(ice.MSG_ARGS).([]interface{})
- Render(msg, msg.Option(ice.MSG_OUTPUT), _args...)
- })
- })
-}
-func (web *Frame) ServeHTTP(w http.ResponseWriter, r *http.Request) {
- m, index := web.m, r.Header.Get("index.module") == ""
- if index {
- // 解析地址
- if ip := r.Header.Get("X-Forwarded-For"); ip != "" {
- r.Header.Set(ice.MSG_USERIP, ip)
- } else if ip := r.Header.Get("X-Real-Ip"); ip != "" {
- r.Header.Set(ice.MSG_USERIP, ip)
- } 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])
- }
- m.Info("").Info("%s %s %s", r.Header.Get(ice.MSG_USERIP), r.Method, r.URL)
-
- // 解析地址
- r.Header.Set("index.module", "some")
- r.Header.Set("index.path", r.URL.Path)
- r.Header.Set("index.url", r.URL.String())
- }
-
- if index && kit.Right(m.Conf(ice.WEB_SERVE, "meta.logheaders")) {
- // 请求参数
- for k, v := range r.Header {
- m.Info("%s: %v", k, kit.Format(v))
- }
- m.Info(" ")
- }
-
- if strings.HasPrefix(r.URL.Path, "/debug") {
- r.URL.Path = strings.Replace(r.URL.Path, "/debug", "/code", -1)
- }
-
- if r.URL.Path == "/" && m.Conf(ice.WEB_SERVE, "meta.init") != "true" {
- if _, e := os.Stat(m.Conf(ice.WEB_SERVE, "meta.volcanos.path")); e == nil {
- // 初始化成功
- m.Conf(ice.WEB_SERVE, "meta.init", "true")
- }
- m.W = w
- Render(m, "refresh", m.Conf(ice.WEB_SERVE, "meta.volcanos.refresh"))
- m.Event(ice.SYSTEM_INIT)
- m.W = nil
- } else if r.URL.Path == "/share" && r.Method == "GET" {
- http.ServeFile(w, r, m.Conf(ice.WEB_SERVE, "meta.page.share"))
-
- // } else if r.URL.Path == "/" && r.Method == "GET" {
- // http.ServeFile(w, r, m.Conf(ice.WEB_SERVE, "meta.page.index"))
- //
- } else {
- web.ServeMux.ServeHTTP(w, r)
- }
-
- if index && kit.Right(m.Conf(ice.WEB_SERVE, "meta.logheaders")) {
- // 响应参数
- for k, v := range w.Header() {
- m.Info("%s: %v", k, kit.Format(v))
- }
- m.Info(" ")
- }
-}
func (web *Frame) Spawn(m *ice.Message, c *ice.Context, arg ...string) ice.Server {
return &Frame{}
@@ -417,7 +109,7 @@ func (web *Frame) Start(m *ice.Message, arg ...string) bool {
// 静态路由
msg := m.Spawns(s)
- m.Confm(ice.WEB_SERVE, "meta.static", func(key string, value string) {
+ m.Confm(SERVE, "meta.static", func(key string, value string) {
m.Log("route", "%s <- %s <- %s", s.Name, key, value)
w.Handle(key, http.StripPrefix(key, http.FileServer(http.Dir(value))))
})
@@ -433,7 +125,7 @@ func (web *Frame) Start(m *ice.Message, arg ...string) bool {
m.Travel(func(p *ice.Context, sub *ice.Context, k string, x *ice.Command) {
if s == sub && k[0] == '/' {
msg.Log("route", "%s <- %s", s.Name, k)
- w.HandleCmd(msg, k, x)
+ Trans(w, msg, k, x)
}
})
}
@@ -460,41 +152,15 @@ func (web *Frame) Close(m *ice.Message, arg ...string) bool {
}
var Index = &ice.Context{Name: "web", Help: "网络模块",
- Caches: map[string]*ice.Cache{},
- Configs: map[string]*ice.Config{
- ice.WEB_SPIDE: {Name: "spide", Help: "蜘蛛侠", Value: kit.Data(kit.MDB_SHORT, "client.name")},
- ice.WEB_SERVE: {Name: "serve", Help: "服务器", Value: kit.Data(
- "title", "github.com/shylinux/contexts",
- "legal", []interface{}{`shylinuxc@gmail.com`},
- "page", kit.Dict(
- "index", "usr/volcanos/page/index.html",
- "share", "usr/volcanos/page/share.html",
- ),
- "static", kit.Dict("/", "usr/volcanos/"),
- "publish", "usr/publish/",
- "volcanos", kit.Dict("path", "usr/volcanos", "branch", "master",
- "repos", "https://github.com/shylinux/volcanos",
- "require", ".ish/pluged",
- "refresh", "5",
- ),
- "template", kit.Dict("path", "usr/template", "list", []interface{}{
- `{{define "raw"}}{{.Result}}{{end}}`,
- }),
- "logheaders", "false", "init", "false",
- "black", kit.Dict(),
- )},
- ice.WEB_DREAM: {Name: "dream", Help: "梦想家", Value: kit.Data("path", "usr/local/work",
- // "cmd", []interface{}{ice.CLI_SYSTEM, "ice.sh", "start", ice.WEB_SPACE, "connect"},
- "cmd", []interface{}{ice.CLI_SYSTEM, "ice.bin", ice.WEB_SPACE, "connect"},
- )},
- },
+ Caches: map[string]*ice.Cache{},
+ Configs: map[string]*ice.Config{},
Commands: map[string]*ice.Command{
ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Load()
- m.Cmd(ice.WEB_SPIDE, "add", "self", kit.Select("http://:9020", m.Conf(ice.CLI_RUNTIME, "conf.ctx_self")))
- m.Cmd(ice.WEB_SPIDE, "add", "dev", kit.Select("http://:9020", m.Conf(ice.CLI_RUNTIME, "conf.ctx_dev")))
- m.Cmd(ice.WEB_SPIDE, "add", "shy", kit.Select("https://shylinux.com:443", m.Conf(ice.CLI_RUNTIME, "conf.ctx_shy")))
+ SpideCreate(m, "self", kit.Select("http://:9020", m.Conf(ice.CLI_RUNTIME, "conf.ctx_self")))
+ SpideCreate(m, "dev", kit.Select("http://:9020", m.Conf(ice.CLI_RUNTIME, "conf.ctx_dev")))
+ SpideCreate(m, "shy", kit.Select("https://shylinux.com:443", m.Conf(ice.CLI_RUNTIME, "conf.ctx_shy")))
m.Cmd(ice.APP_SEARCH, "add", "favor", "base", m.AddCmd(&ice.Command{Name: "search word", Help: "搜索引擎", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
switch arg[0] {
@@ -594,332 +260,7 @@ var Index = &ice.Context{Name: "web", Help: "网络模块",
}
})
}},
-
- ice.WEB_SPIDE: {Name: "spide name=auto [action:select=msg|raw|cache] [method:select=POST|GET] url [format:select=json|form|part|data|file] arg... auto", Help: "蜘蛛侠", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
- if len(arg) == 0 || arg[0] == "" {
- // 爬虫列表
- m.Richs(ice.WEB_SPIDE, nil, "*", func(key string, value map[string]interface{}) {
- m.Push(key, value["client"], []string{"name", "share", "login", "method", "url"})
- })
- m.Sort("name")
- return
- }
- if len(arg) == 1 || len(arg) > 3 && arg[3] == "" {
- // 爬虫详情
- m.Richs(ice.WEB_SPIDE, nil, arg[0], func(key string, value map[string]interface{}) {
- m.Push("detail", value)
- if kit.Value(value, "client.share") != nil {
- m.Push("key", "share")
- m.Push("value", fmt.Sprintf(m.Conf(ice.WEB_SHARE, "meta.template.text"), m.Conf(ice.WEB_SHARE, "meta.domain"), kit.Value(value, "client.share")))
- }
- })
- return
- }
-
- switch arg[0] {
- case "add":
- // 添加爬虫
- if uri, e := url.Parse(arg[2]); e == nil && arg[2] != "" {
- if uri.Host == "random" {
- uri.Host = ":" + m.Cmdx("tcp.getport")
- arg[2] = strings.Replace(arg[2], "random", uri.Host, -1)
- }
- dir, file := path.Split(uri.EscapedPath())
- if m.Richs(ice.WEB_SPIDE, nil, arg[1], func(key string, value map[string]interface{}) {
- // kit.Value(value, "client.name", arg[1])
- // kit.Value(value, "client.text", arg[2])
- kit.Value(value, "client.hostname", uri.Host)
- kit.Value(value, "client.url", arg[2])
- }) == nil {
- m.Rich(ice.WEB_SPIDE, nil, kit.Dict(
- "cookie", kit.Dict(), "header", kit.Dict(), "client", kit.Dict(
- "share", m.Cmdx(ice.WEB_SHARE, ice.TYPE_SPIDE, arg[1], arg[2]),
- // "type", "POST", "name", arg[1], "text", arg[2],
- "name", arg[1], "url", arg[2], "method", "POST",
- "protocol", uri.Scheme, "hostname", uri.Host,
- "path", dir, "file", file, "query", uri.RawQuery,
- "timeout", "100s", "logheaders", false,
- ),
- ))
- }
- m.Log(ice.LOG_CREATE, "%s: %v", arg[1], arg[2:])
- }
- return
- case "login":
- m.Richs(ice.WEB_SPIDE, nil, arg[1], func(key string, value map[string]interface{}) {
- msg := m.Cmd(ice.WEB_SPIDE, arg[1], "msg", "/route/login", "login")
- if msg.Append(ice.MSG_USERNAME) != "" {
- m.Echo(msg.Append(ice.MSG_USERNAME))
- return
- }
- if msg.Result() != "" {
- kit.Value(value, "client.login", msg.Result())
- kit.Value(value, "client.share", m.Cmdx(ice.WEB_SHARE, ice.TYPE_SPIDE, arg[1],
- kit.Format("%s?sessid=%s", kit.Value(value, "client.url"), kit.Value(value, "cookie.sessid"))))
- }
- m.Render(ice.RENDER_QRCODE, kit.Dict(
- kit.MDB_TYPE, "login", kit.MDB_NAME, arg[1],
- kit.MDB_TEXT, kit.Value(value, "cookie.sessid"),
- ))
- })
- return
- }
-
- m.Richs(ice.WEB_SPIDE, nil, arg[0], func(key string, value map[string]interface{}) {
- client := value["client"].(map[string]interface{})
- // 缓存数据
- cache := ""
- switch arg[1] {
- case "raw":
- cache, arg = arg[1], arg[1:]
- case "msg":
- cache, arg = arg[1], arg[1:]
- case "cache":
- cache, arg = arg[1], arg[1:]
- }
-
- // 请求方法
- method := kit.Select("POST", client["method"])
- switch arg = arg[1:]; arg[0] {
- case "POST":
- method, arg = "POST", arg[1:]
- case "GET":
- method, arg = "GET", arg[1:]
- }
-
- // 请求地址
- uri, arg := arg[0], arg[1:]
-
- // 渲染引擎
- head := map[string]string{}
- body, ok := m.Optionv("body").(io.Reader)
- if !ok && len(arg) > 0 && method != "GET" {
- switch arg[0] {
- case "file":
- if f, e := os.Open(arg[1]); m.Warn(e != nil, "%s", e) {
- return
- } else {
- defer f.Close()
- body, arg = f, arg[2:]
- }
- case "data":
- body, arg = bytes.NewBufferString(arg[1]), arg[2:]
- case "part":
- buf := &bytes.Buffer{}
- mp := multipart.NewWriter(buf)
- for i := 1; i < len(arg)-1; i += 2 {
- if strings.HasPrefix(arg[i+1], "@") {
- if f, e := os.Open(arg[i+1][1:]); m.Assert(e) {
- defer f.Close()
- if p, e := mp.CreateFormFile(arg[i], path.Base(arg[i+1][1:])); m.Assert(e) {
- io.Copy(p, f)
- }
- }
- } else {
- mp.WriteField(arg[i], arg[i+1])
- }
- }
- mp.Close()
- head["Content-Type"] = mp.FormDataContentType()
- body = buf
- case "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["Content-Type"] = "application/x-www-form-urlencoded"
- case "json":
- arg = arg[1:]
- fallthrough
- default:
- data := map[string]interface{}{}
- 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["Content-Type"] = "application/json"
- body = bytes.NewBuffer(b)
- }
- m.Log(ice.LOG_EXPORT, "json: %s", kit.Format(data))
- }
- arg = arg[:0]
- } else {
- body = bytes.NewBuffer([]byte{})
- }
-
- // 请求地址
- uri = kit.MergeURL2(kit.Format(client["url"]), uri, arg)
- req, e := http.NewRequest(method, uri, body)
- m.Info("%s %s", req.Method, req.URL)
- m.Assert(e)
-
- // 请求变量
- kit.Fetch(value["cookie"], func(key string, value string) {
- req.AddCookie(&http.Cookie{Name: key, Value: value})
- m.Info("%s: %s", key, value)
- })
- kit.Fetch(value["header"], func(key string, value string) {
- req.Header.Set(key, value)
- })
- list := kit.Simple(m.Optionv("header"))
- for i := 0; i < len(list)-1; i += 2 {
- req.Header.Set(list[i], list[i+1])
- }
- for k, v := range head {
- req.Header.Set(k, v)
- }
-
- // 请求代理
- web := m.Target().Server().(*Frame)
- if web.Client == nil {
- web.Client = &http.Client{Timeout: kit.Duration(kit.Format(client["timeout"]))}
- }
- if method == "POST" {
- m.Info("%s: %s", req.Header.Get("Content-Length"), req.Header.Get("Content-Type"))
- }
-
- // 发送请求
- res, e := web.Client.Do(req)
- if m.Warn(e != nil, "%s", e) {
- return
- }
-
- // 检查结果
- if m.Cost("%s %s: %s", res.Status, res.Header.Get("Content-Length"), res.Header.Get("Content-Type")); m.Warn(res.StatusCode != http.StatusOK, "%s", res.Status) {
- return
- }
-
- // 缓存变量
- for _, v := range res.Cookies() {
- kit.Value(value, "cookie."+v.Name, v.Value)
- m.Log(ice.LOG_IMPORT, "%s: %s", v.Name, v.Value)
- }
-
- // 解析引擎
- switch cache {
- case "cache":
- m.Optionv("response", res)
- m.Cmdy(ice.WEB_CACHE, "download", res.Header.Get("Content-Type"), uri)
- m.Echo(m.Append("data"))
- case "raw":
- if b, e := ioutil.ReadAll(res.Body); m.Assert(e) {
- m.Echo(string(b))
- }
- case "msg":
- var data map[string][]string
- m.Assert(json.NewDecoder(res.Body).Decode(&data))
- m.Info("res: %s", kit.Formats(data))
- for _, k := range data[ice.MSG_APPEND] {
- for i := range data[k] {
- m.Push(k, data[k][i])
- }
- }
- m.Resultv(data[ice.MSG_RESULT])
- default:
- if strings.HasPrefix(res.Header.Get("Content-Type"), "text/html") {
- b, _ := ioutil.ReadAll(res.Body)
- m.Echo(string(b))
- break
- }
-
- var data interface{}
- m.Assert(json.NewDecoder(res.Body).Decode(&data))
- data = kit.KeyValue(map[string]interface{}{}, "", data)
- m.Info("res: %s", kit.Formats(data))
- m.Push("", data)
- }
- })
- }},
- ice.WEB_SERVE: {Name: "serve [random] [ups...]", Help: "服务器", Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
- m.Conf(ice.CLI_RUNTIME, "node.name", m.Conf(ice.CLI_RUNTIME, "boot.hostname"))
- m.Conf(ice.CLI_RUNTIME, "node.type", ice.WEB_SERVER)
-
- if len(arg) > 0 && arg[0] == "random" {
- // 随机端口
- m.Conf(ice.CLI_RUNTIME, "node.name", m.Conf(ice.CLI_RUNTIME, "boot.pathname"))
- m.Cmd(ice.WEB_SPIDE, "add", "self", "http://random")
- arg = arg[1:]
- }
-
- // 启动服务
- m.Target().Start(m, "self")
- m.Sleep("1s")
-
- // 连接服务
- m.Cmd(ice.WEB_SPACE, "connect", "self")
- for _, k := range arg {
- m.Cmd(ice.WEB_SPACE, "connect", k)
- }
-
- m.Watch(ice.SYSTEM_INIT, "web.code.git.repos", "volcanos", m.Conf(ice.WEB_SERVE, "meta.volcanos.path"),
- m.Conf(ice.WEB_SERVE, "meta.volcanos.repos"), m.Conf(ice.WEB_SERVE, "meta.volcanos.branch"))
- m.Conf(ice.WEB_FAVOR, "meta.template", favor_template)
- m.Conf(ice.WEB_SHARE, "meta.template", share_template)
- }},
- ice.WEB_DREAM: {Name: "dream name auto", Help: "梦想家", Meta: kit.Dict(
- "exports", []string{"you", "name"}, "detail", []interface{}{"启动", "停止"},
- ), Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
- if len(arg) > 1 && arg[0] == "action" {
- switch arg[1] {
- case "启动", "start":
- arg = []string{arg[4]}
- case "停止", "stop":
- m.Cmd(ice.WEB_SPACE, kit.Select(m.Option("name"), arg, 4), "exit", "1")
- m.Event(ice.DREAM_CLOSE, arg[4])
- return
- }
- }
-
- if len(arg) == 0 {
- // 任务列表
- m.Cmdy("nfs.dir", m.Conf(ice.WEB_DREAM, "meta.path"), "time name")
- m.Table(func(index int, value map[string]string, head []string) {
- if m.Richs(ice.WEB_SPACE, nil, value["name"], func(key string, value map[string]interface{}) {
- m.Push("type", value["type"])
- m.Push("status", "start")
- }) == nil {
- m.Push("type", "none")
- m.Push("status", "stop")
- }
- })
- m.Sort("name")
- m.Sort("status")
- return
- }
-
- // 规范命名
- if !strings.Contains(arg[0], "-") || !strings.HasPrefix(arg[0], "20") {
- arg[0] = m.Time("20060102-") + arg[0]
- }
-
- // 创建目录
- p := path.Join(m.Conf(ice.WEB_DREAM, "meta.path"), arg[0])
- os.MkdirAll(p, 0777)
-
- if b, e := ioutil.ReadFile(path.Join(p, m.Conf(ice.GDB_SIGNAL, "meta.pid"))); e == nil {
- if s, e := os.Stat("/proc/" + string(b)); e == nil && s.IsDir() {
- m.Info("already exists %v", string(b))
- return
- }
- }
-
- if m.Richs(ice.WEB_SPACE, nil, arg[0], nil) == nil {
- // 启动任务
- m.Option("cmd_dir", p)
- m.Option("cmd_type", "daemon")
- m.Optionv("cmd_env",
- "ctx_dev", m.Conf(ice.CLI_RUNTIME, "conf.ctx_dev"),
- "ctx_log", "boot.log", "ctx_mod", "ctx,log,gdb,ssh",
- "PATH", kit.Path(path.Join(p, "bin"))+":"+os.Getenv("PATH"),
- )
- m.Cmd(m.Confv(ice.WEB_DREAM, "meta.cmd"), "self", arg[0])
- time.Sleep(time.Second * 1)
- m.Event(ice.DREAM_START, arg...)
- }
- m.Cmdy("nfs.dir", p)
- }},
},
}
-func init() { ice.Index.Register(Index, &Frame{}) }
+func init() { ice.Index.Register(Index, &Frame{}, SERVE) }
diff --git a/misc/lark/lark.go b/misc/lark/lark.go
index 831933bd..e0b229d6 100644
--- a/misc/lark/lark.go
+++ b/misc/lark/lark.go
@@ -66,7 +66,7 @@ var Index = &ice.Context{Name: "lark", Help: "机器人",
Commands: map[string]*ice.Command{
ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Load()
- m.Cmd(ice.WEB_SPIDE, "add", LARK, m.Conf(APP, "meta.lark"))
+ web.SpideCreate(m, LARK, m.Conf(APP, "meta.lark"))
m.Cmd(DUTY, "boot", m.Conf(ice.CLI_RUNTIME, "boot.hostname"), m.Time())
}},
ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
diff --git a/misc/mp/mp.go b/misc/mp/mp.go
index 721b5adc..0ba088fa 100644
--- a/misc/mp/mp.go
+++ b/misc/mp/mp.go
@@ -22,7 +22,7 @@ var Index = &ice.Context{Name: "mp", Help: "小程序",
Commands: map[string]*ice.Command{
ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Load()
- m.Cmd(ice.WEB_SPIDE, "add", "weixin", m.Conf("login", "meta.weixin"))
+ web.SpideCreate(m, "weixin", m.Conf("login", "meta.weixin"))
m.Confm("login", "meta.userrole", func(key string, value string) {
m.Cmd(ice.AAA_ROLE, value, key)
})
diff --git a/misc/railway/railway.go b/misc/railway/railway.go
index c9ca6e5d..ab34360b 100644
--- a/misc/railway/railway.go
+++ b/misc/railway/railway.go
@@ -14,7 +14,7 @@ var Index = &ice.Context{Name: "railway", Help: "railway",
Commands: map[string]*ice.Command{
ice.ICE_INIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Load()
- m.Cmd(ice.WEB_SPIDE, "add", "12306", m.Conf("railway", "meta.site"))
+ web.SpideCreate(m, "12306", m.Conf("railway", "meta.site"))
}},
ice.ICE_EXIT: {Hand: func(m *ice.Message, c *ice.Context, cmd string, arg ...string) {
m.Save("railway")