1
0
mirror of https://shylinux.com/x/ContextOS synced 2025-04-25 16:58:06 +08:00

mac pro web

This commit is contained in:
shaoying 2018-07-01 01:52:28 +08:00
parent ea2d45692d
commit 723d1824d6
3 changed files with 357 additions and 351 deletions

View File

@ -680,10 +680,9 @@ func (m *Message) Assert(e interface{}, msg ...string) bool { // {{{
func (m *Message) TryCatch(msg *Message, safe bool, hand ...func(msg *Message)) *Message { // {{{
defer func() {
if e := recover(); e != nil {
switch e.(type) {
switch v := e.(type) {
case *Message:
panic(e)
e = strings.Join(v.Meta["result"][1:], "")
}
msg.Log("error", nil, "error: %v", e)
@ -1203,6 +1202,39 @@ func (m *Message) Table(cb func(map[string]string, []string, int) bool) *Message
return m
}
// }}}
func (m *Message) Matrix(index int, arg ...interface{}) string { // {{{
if len(m.Meta["append"]) == 0 || index < 0 {
return ""
}
key := m.Meta["append"][0]
if len(arg) > 0 {
switch v := arg[0].(type) {
case string:
for _, k := range m.Meta["append"] {
if k == v {
key = v
}
}
if key != v {
return ""
}
case int:
if v < len(m.Meta["append"]) {
key = m.Meta["append"][v]
} else {
return ""
}
}
}
if index < len(m.Meta[key]) {
return m.Meta[key][index]
}
return ""
}
// }}}
func (m *Message) Sort(key string, arg ...string) { // {{{
table := []map[string]string{}
@ -1633,57 +1665,54 @@ func (m *Message) Confx(key string, arg ...interface{}) string { // {{{
return value
}
skip := false
value := ""
switch v := arg[0].(type) {
case string:
value = v
case []string:
which := 0
if len(arg) > 1 {
if x, ok := arg[1].(int); ok {
which = x
arg = arg[1:]
}
}
if which < len(v) {
value = v[which]
}
default:
x := fmt.Sprintf("%v", v)
if v != nil && x != "" {
value = x
}
}
force := false
if len(arg) > 1 {
if v, ok := arg[1].(bool); ok {
arg = arg[1:]
force = v
}
}
if !force && value == "" {
value = m.Conf(key)
}
format := "%s"
if len(arg) > 1 {
switch v := arg[1].(type) {
case bool:
skip = !v
case string:
if v, ok := arg[1].(string); ok {
arg = arg[1:]
format = v
}
}
if len(arg) > 0 {
switch v := arg[0].(type) {
case string:
if skip || v == "" {
v = m.Conf(key)
}
if v == "" {
return v
}
return fmt.Sprintf(format, v)
case []string:
which := 0
if len(arg) > 1 {
if x, ok := arg[1].(int); ok {
which = x
}
}
value := ""
if which < len(v) {
value = v[which]
} else {
value = m.Conf(key)
}
if len(arg) > 2 {
format = arg[2].(string)
}
if value == "" {
return value
}
return fmt.Sprintf(format, value)
default:
x := fmt.Sprintf("%v", v)
if skip || v == nil || x == "" {
return m.Conf(key)
}
return x
if value != "" {
args := []interface{}{value}
for _, v := range arg[1:] {
args = append(args, v)
}
value = fmt.Sprintf(format, args...)
}
return ""
return value
}
// }}}
@ -2641,9 +2670,9 @@ var Index = &Context{Name: "ctx", Help: "模块中心",
Hand: func(m *Message, c *Context, key string, arg ...string) {
switch len(arg) { // {{{
case 0:
m.Travel(m.target.root, func(msg *Message) bool {
if msg.Cap("status") == "start" {
msg.Echo("%s(%s): %s\n", msg.target.Name, msg.Cap("stream"), msg.target.Help)
m.Travel(m.target.root, func(m *Message) bool {
if m.Cap("status") == "start" {
m.Echo("%s(%s): %s\n", m.target.Name, m.Cap("stream"), m.target.Help)
}
return true
})
@ -2651,24 +2680,20 @@ var Index = &Context{Name: "ctx", Help: "模块中心",
default:
switch arg[0] {
case "spawn":
if len(arg) > 1 {
msg := m.Spawn(m.Target())
msg.Detail(0, arg[2:])
msg.Target().Spawn(msg, arg[0], arg[1])
if len(arg) > 2 {
msg := m.Spawn().Set("detail", arg[3:]...)
msg.target.Spawn(msg, arg[1], arg[2])
m.target = msg.target
}
case "begin":
msg := m.Spawn(m.Target())
msg.Detail(0, arg)
msg.Target().Begin(msg)
msg := m.Spawn().Set("detail", arg...)
msg.target.Begin(msg)
case "start":
msg := m.Spawn(m.Target())
msg.Detail(0, arg)
msg.Target().Start(msg)
msg := m.Spawn().Set("detail", arg...)
msg.target.Start(msg)
case "close":
msg := m.Spawn(m.Target())
msg.Detail(0, arg)
msg.Target().Close(msg)
msg := m.Spawn().Set("detail", arg...)
msg.target.Close(msg)
}
}
// }}}

View File

@ -25,11 +25,11 @@ type MDB struct {
func (mdb *MDB) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server {
c.Caches = map[string]*ctx.Cache{
"database": &ctx.Cache{Name: "数据库", Value: m.Confx("database", arg, 0), Help: "数据库驱动"},
"username": &ctx.Cache{Name: "用户名", Value: m.Confx("username", arg, 1), Help: "数据库驱动"},
"password": &ctx.Cache{Name: "密码", Value: m.Confx("password", arg, 2), Help: "数据库驱动"},
"protocol": &ctx.Cache{Name: "协议", Value: m.Confx("protocol", arg, 4), Help: "数据库驱动"},
"address": &ctx.Cache{Name: "地址", Value: m.Confx("address", arg, 3), Help: "数据库驱动"},
"database": &ctx.Cache{Name: "数据库", Value: m.Confx("database", arg, 0), Help: "数据库"},
"username": &ctx.Cache{Name: "账户", Value: m.Confx("username", arg, 1), Help: "账户"},
"password": &ctx.Cache{Name: "密码", Value: m.Confx("password", arg, 2), Help: "密码"},
"address": &ctx.Cache{Name: "服务地址", Value: m.Confx("address", arg, 3), Help: "服务地址"},
"protocol": &ctx.Cache{Name: "服务协议(tcp)", Value: m.Confx("protocol", arg, 4), Help: "服务协议"},
"driver": &ctx.Cache{Name: "数据库驱动(mysql)", Value: m.Confx("driver", arg, 5), Help: "数据库驱动"},
}
c.Configs = map[string]*ctx.Config{
@ -62,8 +62,7 @@ func (mdb *MDB) Start(m *ctx.Message, arg ...string) bool { // {{{
m.Cap("username"), m.Cap("password"), m.Cap("protocol"), m.Cap("address"), m.Cap("database")))
m.Assert(e)
mdb.DB = db
m.Log("info", nil, "%d open %s %s", m.Capi("nsource"), m.Cap("driver"), m.Cap("stream", m.Cap("database")))
m.Log("info", nil, "mdb open %s", m.Cap("database"))
return false
}
@ -72,7 +71,7 @@ func (mdb *MDB) Close(m *ctx.Message, arg ...string) bool { // {{{
switch mdb.Context {
case m.Target():
if mdb.DB != nil {
m.Log("info", nil, "close")
m.Log("info", nil, "mdb close %s", m.Cap("database"))
mdb.DB.Close()
mdb.DB = nil
}
@ -89,11 +88,11 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
"nsource": &ctx.Cache{Name: "数据源数量", Value: "0", Help: "已打开数据库的数量"},
},
Configs: map[string]*ctx.Config{
"database": &ctx.Config{Name: "默认数据库", Value: "demo", Help: "数据库驱动"},
"username": &ctx.Config{Name: "默认用户名", Value: "demo", Help: "数据库驱动"},
"password": &ctx.Config{Name: "默认密码", Value: "demo", Help: "数据库驱动"},
"protocol": &ctx.Config{Name: "默认协议", Value: "tcp", Help: "数据库驱动"},
"address": &ctx.Config{Name: "默认地址", Value: "", Help: "数据库驱动"},
"database": &ctx.Config{Name: "默认数据库", Value: "demo", Help: "默认数据库"},
"username": &ctx.Config{Name: "默认用户名", Value: "demo", Help: "默认用户名"},
"password": &ctx.Config{Name: "默认密码", Value: "demo", Help: "默认密码"},
"protocol": &ctx.Config{Name: "默认协议", Value: "tcp", Help: "默认协议"},
"address": &ctx.Config{Name: "默认地址", Value: "", Help: "默认地址"},
"driver": &ctx.Config{Name: "数据库驱动(mysql)", Value: "mysql", Help: "数据库驱动"},
"dbhelp": &ctx.Config{Name: "默认帮助", Value: "数据存储", Help: "默认帮助"},
@ -105,17 +104,18 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
// }}}
}},
"csv_sep": &ctx.Config{Name: "字段分隔符", Value: "\t", Help: "字段分隔符"},
"csv_col_sep": &ctx.Config{Name: "字段分隔符", Value: "\t", Help: "字段分隔符"},
"csv_row_sep": &ctx.Config{Name: "记录分隔符", Value: "\n", Help: "记录分隔符"},
},
Commands: map[string]*ctx.Command{
"open": &ctx.Command{
Name: "open [database [username [password [address [protocol [driver]]]]]] [dbname name] [dbhelp help]",
Help: "open打开数据库, database: 数据库名, username: 用户名, password: 密码, address: 主机地址, protocol: 主机协议, driver: 数据库类型, dbname: 模块名称, dbhelp: 帮助信息",
Help: "open打开数据库, database: 数据库名, username: 用户名, password: 密码, address: 服务地址, protocol: 服务协议, driver: 数据库类型, dbname: 模块名称, dbhelp: 帮助信息",
Form: map[string]int{"dbname": 1, "dbhelp": 1},
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
m.Start(m.Confx("dbname"), m.Confx("dbhelp"), arg...)
}},
"exec": &ctx.Command{Name: "exec sql [arg]", Help: "操作数据库, sql: SQL语句, arg: 查询参数",
"exec": &ctx.Command{Name: "exec sql [arg]", Help: "操作数据库, sql: SQL语句, arg: 操作参数",
Appends: map[string]string{"last": "最后插入元组的标识", "nrow": "修改元组的数量"},
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if mdb, ok := m.Target().Server.(*MDB); m.Assert(ok) { // {{{
@ -179,11 +179,10 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
}
// }}}
}},
"db": &ctx.Command{Name: "db", Help: "查看关系表信息which: 表名, field: 字段名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
"db": &ctx.Command{Name: "db [which]", Help: "查看或选择数据库信息", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if mdb, ok := m.Target().Server.(*MDB); m.Assert(ok) { // {{{
msg := m.Spawn()
if len(arg) == 0 {
msg.Cmd("query", "show databases")
msg := m.Spawn().Cmd("query", "show databases")
mdb.db = []string{}
for i, v := range msg.Meta[msg.Meta["append"][0]] {
mdb.db = append(mdb.db, v)
@ -193,20 +192,18 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
}
db := arg[0]
index, e := strconv.Atoi(arg[0])
if e == nil && index < len(mdb.db) {
db = mdb.db[index]
if i, e := strconv.Atoi(arg[0]); e == nil && i < len(mdb.db) {
db = mdb.db[i]
}
m.Assert(m.Spawn().Cmd("exec", fmt.Sprintf("use %s", db)))
m.Cap("database", db)
mdb.Exec(fmt.Sprintf("use %s", db))
}
// }}}
}},
"table": &ctx.Command{Name: "table [which [field]]", Help: "查看关系表信息which: 表名, field: 字段名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if mdb, ok := m.Target().Server.(*MDB); m.Assert(ok) { // {{{
msg := m.Spawn()
if len(arg) == 0 {
msg.Cmd("query", "show tables")
msg := m.Spawn().Cmd("query", "show tables")
mdb.table = []string{}
for i, v := range msg.Meta[msg.Meta["append"][0]] {
mdb.table = append(mdb.table, v)
@ -216,12 +213,11 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
}
table := arg[0]
index, e := strconv.Atoi(arg[0])
if e == nil && index < len(mdb.table) {
table = mdb.table[index]
if i, e := strconv.Atoi(arg[0]); e == nil && i < len(mdb.table) {
table = mdb.table[i]
}
msg.Cmd("query", fmt.Sprintf("desc %s", table))
msg := m.Spawn().Cmd("query", fmt.Sprintf("desc %s", table))
if len(arg) == 1 {
for _, v := range msg.Meta[msg.Meta["append"][0]] {
m.Echo("%s\n", v)
@ -267,11 +263,10 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
offset := m.Confx("offset", m.Option("offset"), "offset %s")
msg := m.Spawn().Cmd("query", fmt.Sprintf("select %s from %s %s %s %s %s %s", field, table, where, group, order, limit, offset), m.Meta["other"])
if !m.Options("save") {
if m.Optioni("query", msg.Code()); !m.Options("save") {
m.Color(31, table).Echo(" %s %s %s %s %s %v\n", where, group, order, limit, offset, m.Meta["other"])
}
m.Optioni("query", msg.Code())
msg.Table(func(maps map[string]string, lists []string, line int) bool {
for i, v := range lists {
if m.Options("save") {
@ -282,10 +277,10 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
m.Echo(v)
}
if i < len(lists)-1 {
m.Echo(m.Conf("csv_sep"))
m.Echo(m.Conf("csv_col_sep"))
}
}
m.Echo("\n")
m.Echo(m.Conf("csv_row_sep"))
return true
})
@ -300,20 +295,25 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
}
} // }}}
}},
"get": &ctx.Command{Name: "get field table where offset [parse func field]", Help: "执行查询语句",
"get": &ctx.Command{Name: "get field offset table where [parse func field]", Help: "执行查询语句",
Form: map[string]int{"parse": 2},
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
field := m.Confx("field", arg, 0) // {{{
table := m.Confx("table", arg, 1, "from %s")
where := m.Confx("where", arg, 2, "where %s")
index := 0 // {{{
if len(arg) > 1 {
if i, e := strconv.Atoi(arg[1]); e == nil {
index = i
}
}
field := m.Confx("field", arg, 0)
offset := m.Confx("offset", arg, 1, "offset %s")
table := m.Confx("table", arg, 2, "from %s")
where := m.Confx("where", arg, 3, "where %s")
limit := "limit 1"
offset := m.Confx("offset", arg, 3, "offset %s")
msg := m.Spawn().Cmd("query", fmt.Sprintf("select %s %s %s %s %s", field, table, where, limit, offset))
value := m.Append(msg.Meta["append"][0])
value := msg.Matrix(index, field)
parse := m.Confx("parse", m.Option("parse"))
switch parse {
switch m.Confx("parse", m.Option("parse")) {
case "json":
extra := ""
if len(m.Meta["parse"]) > 1 {
@ -330,7 +330,6 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
default:
m.Echo("%v", value)
}
return
// }}}
}},
},

View File

@ -41,9 +41,6 @@ type WEB struct {
client *http.Client
cookie map[string]*http.Cookie
list map[string][]string
list_key []string
*ctx.Message
*ctx.Context
}
@ -220,9 +217,6 @@ func (web *WEB) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{
}
}
}
web.list = map[string][]string{}
return web
}
@ -235,6 +229,7 @@ func (web *WEB) Start(m *ctx.Message, arg ...string) bool { // {{{
m.Travel(m.Target(), func(m *ctx.Message) bool {
if h, ok := m.Target().Server.(http.Handler); ok && m.Cap("register") == "no" {
m.Cap("register", "yes")
m.Capi("nroute", 1)
p, i := m.Target(), 0
m.BackTrace(func(m *ctx.Message) bool {
@ -258,6 +253,14 @@ func (web *WEB) Start(m *ctx.Message, arg ...string) bool { // {{{
return true
})
web.Configs["template_dir"] = &ctx.Config{Name: "template_dir", Value: "usr/template/", Help: "通用模板路径"}
web.Configs["common_tmpl"] = &ctx.Config{Name: "common_tmpl", Value: "common/*.html", Help: "通用模板路径"}
web.Configs["common_main"] = &ctx.Config{Name: "common_main", Value: "main.html", Help: "通用模板框架"}
web.Configs["upload_tmpl"] = &ctx.Config{Name: "upload_tmpl", Value: "upload.html", Help: "上传文件模板"}
web.Configs["upload_main"] = &ctx.Config{Name: "upload_main", Value: "main.html", Help: "上传文件框架"}
web.Configs["travel_tmpl"] = &ctx.Config{Name: "travel_tmpl", Value: "travel.html", Help: "浏览模块模板"}
web.Configs["travel_main"] = &ctx.Config{Name: "travel_main", Value: "main.html", Help: "浏览模块框架"}
web.Caches["address"] = &ctx.Cache{Name: "服务地址", Value: ":9191", Help: "服务地址"}
web.Caches["protocol"] = &ctx.Cache{Name: "服务协议", Value: "http", Help: "服务协议"}
if len(arg) > 1 {
@ -274,6 +277,7 @@ func (web *WEB) Start(m *ctx.Message, arg ...string) bool { // {{{
web.Server = &http.Server{Addr: m.Cap("address"), Handler: web}
web.Configs["logheaders"] = &ctx.Config{Name: "日志输出报文头(yes/no)", Value: "yes", Help: "日志输出报文头"}
m.Capi("nserve", 1)
if web.Message = m; m.Cap("protocol") == "https" {
web.Caches["cert"] = &ctx.Cache{Name: "服务证书", Value: m.Conf("cert"), Help: "服务证书"}
@ -302,270 +306,248 @@ func (web *WEB) Close(m *ctx.Message, arg ...string) bool { // {{{
var Index = &ctx.Context{Name: "web", Help: "应用中心",
Caches: map[string]*ctx.Cache{
"count": &ctx.Cache{Name: "count", Value: "0", Help: "主机协议"},
},
Configs: map[string]*ctx.Config{
"protocol": &ctx.Config{Name: "protocol", Value: "", Help: "主机协议"},
"hostname": &ctx.Config{Name: "hostname", Value: "", Help: "主机地址"},
"port": &ctx.Config{Name: "port", Value: "", Help: "主机端口"},
"dir": &ctx.Config{Name: "dir", Value: "/", Help: "主机路由"},
"file": &ctx.Config{Name: "file", Value: "", Help: "主机文件"},
"query": &ctx.Config{Name: "query", Value: "", Help: "主机参数"},
"output": &ctx.Config{Name: "output", Value: "stdout", Help: "响应输出"},
"editor": &ctx.Config{Name: "editor", Value: "vim", Help: "响应编辑器"},
"template_dir": &ctx.Config{Name: "template_dir", Value: "usr/template/", Help: "通用模板路径"},
"common_tmpl": &ctx.Config{Name: "common_tmpl", Value: "common/*.html", Help: "通用模板路径"},
"common_main": &ctx.Config{Name: "common_main", Value: "main.html", Help: "通用模板框架"},
"upload_tmpl": &ctx.Config{Name: "upload_tmpl", Value: "upload.html", Help: "上传文件模板"},
"upload_main": &ctx.Config{Name: "upload_main", Value: "main.html", Help: "上传文件框架"},
"travel_tmpl": &ctx.Config{Name: "travel_tmpl", Value: "travel.html", Help: "浏览模块模板"},
"travel_main": &ctx.Config{Name: "travel_main", Value: "main.html", Help: "浏览模块框架"},
"nserve": &ctx.Cache{Name: "nserve", Value: "0", Help: "主机数量"},
"nroute": &ctx.Cache{Name: "nroute", Value: "0", Help: "路由数量"},
},
Configs: map[string]*ctx.Config{},
Commands: map[string]*ctx.Command{
"serve": &ctx.Command{Name: "serve [directory [address [protocol]]]", Help: "开启应用服务", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
m.Set("detail", arg...).Target().Start(m)
}},
"route": &ctx.Command{Name: "route directory|template|script route content", Help: "添加应用内容", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
mux, ok := m.Target().Server.(MUX) // {{{
m.Assert(ok, "模块类型错误")
m.Assert(len(arg) == 3, "缺少参数")
switch arg[0] {
case "directory":
mux.Handle(arg[1]+"/", http.StripPrefix(arg[1], http.FileServer(http.Dir(arg[2]))))
case "template":
mux.Trans(m, arg[1], func(m *ctx.Message, c *ctx.Context, key string, a ...string) {
w := m.Data["response"].(http.ResponseWriter)
if _, e := os.Stat(arg[2]); e == nil {
template.Must(template.ParseGlob(arg[2])).Execute(w, m)
} else {
template.Must(template.New("temp").Parse(arg[2])).Execute(w, m)
"client": &ctx.Command{
Name: "client address [output [editor]]",
Help: "添加请求配置, address: 默认地址, output: 输出路径, editor: 编辑器",
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if web, e := m.Target().Server.(*WEB); m.Assert(e) { // {{{
if len(arg) == 0 {
return
}
})
case "script":
cli := m.Find("cli")
lex := m.Find("lex")
mux.Trans(m, arg[1], func(m *ctx.Message, c *ctx.Context, key string, a ...string) {
f, e := os.Open(arg[2])
line, bio := "", bufio.NewReader(f)
if e != nil {
line = arg[2]
}
uri, e := url.Parse(arg[0])
m.Assert(e)
web.Configs["method"] = &ctx.Config{Name: "method", Value: "GET", Help: "请求方法"}
web.Configs["protocol"] = &ctx.Config{Name: "protocol", Value: uri.Scheme, Help: "服务协议"}
web.Configs["hostname"] = &ctx.Config{Name: "hostname", Value: uri.Hostname(), Help: "服务主机"}
web.Configs["port"] = &ctx.Config{Name: "port", Value: uri.Port(), Help: "服务端口"}
for {
if line = strings.TrimSpace(line); line != "" {
lex.Cmd("split", line, "void")
cli.Wait = make(chan bool)
cli.Cmd(lex.Meta["result"])
m.Meta["result"] = cli.Meta["result"]
dir, file := path.Split(uri.EscapedPath())
web.Configs["path"] = &ctx.Config{Name: "path", Value: dir, Help: "服务路由"}
web.Configs["file"] = &ctx.Config{Name: "file", Value: file, Help: "服务文件"}
web.Configs["query"] = &ctx.Config{Name: "query", Value: uri.RawQuery, Help: "服务参数"}
web.Configs["output"] = &ctx.Config{Name: "output", Value: "stdout", Help: "文件缓存"}
if len(arg) > 1 {
m.Conf("output", arg[1])
}
web.Configs["editor"] = &ctx.Config{Name: "editor", Value: "vim", Help: "文件编辑器"}
if len(arg) > 2 {
m.Conf("editor", arg[2])
}
} // }}}
}},
"cookie": &ctx.Command{
Name: "cookie [name [value]]",
Help: "读写请求的Cookie, name: 变量名, value: 变量值",
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if web, ok := m.Target().Server.(*WEB); m.Assert(ok) { // {{{
switch len(arg) {
case 0:
for k, v := range web.cookie {
m.Echo("%s: %v\n", k, v.Value)
}
if line, e = bio.ReadString('\n'); e != nil {
break
case 1:
if v, ok := web.cookie[arg[0]]; ok {
m.Echo("%s", v.Value)
}
default:
if web.cookie == nil {
web.cookie = make(map[string]*http.Cookie)
}
if v, ok := web.cookie[arg[0]]; ok {
v.Value = arg[1]
} else {
web.cookie[arg[0]] = &http.Cookie{Name: arg[0], Value: arg[1]}
}
}
})
} // }}}
}},
"cookie": &ctx.Command{Name: "cookie add|del arg...", Help: "访问URL", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
web, ok := m.Target().Server.(*WEB) // {{{
m.Assert(ok)
switch len(arg) {
case 0:
for k, v := range web.cookie {
m.Echo("%s: %v\n", k, v.Value)
}
case 1:
if v, ok := web.cookie[arg[0]]; ok {
m.Echo("%s", v.Value)
}
default:
if web.cookie == nil {
web.cookie = make(map[string]*http.Cookie)
}
if v, ok := web.cookie[arg[0]]; ok {
v.Value = arg[1]
} else {
web.cookie[arg[0]] = &http.Cookie{Name: arg[0], Value: arg[1]}
}
}
// }}}
}},
"get": &ctx.Command{Name: "get [method GET|POST] [file filename] url arg...", Help: "访问URL",
} // }}}
}},
"get": &ctx.Command{
Name: "get [method GET|POST] [file name filename] url arg...",
Help: "访问服务, method: 请求方法, file: 发送文件, url: 请求地址, arg: 请求参数",
Form: map[string]int{"method": 1, "file": 2},
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
web, ok := m.Target().Server.(*WEB) // {{{
m.Assert(ok)
if web.client == nil {
web.client = &http.Client{}
}
method := "GET"
if m.Options("method") {
method = m.Option("method")
}
uri := web.generate(m, arg[0], arg[1:]...)
m.Log("info", nil, "GET %s", uri)
m.Echo("%s: %s\n", method, uri)
var body io.Reader
index := strings.Index(uri, "?")
contenttype := ""
switch method {
case "POST":
if m.Options("file") {
file, e := os.Open(m.Meta["file"][1])
m.Assert(e)
defer file.Close()
buf := &bytes.Buffer{}
writer := multipart.NewWriter(buf)
part, e := writer.CreateFormFile(m.Option("file"), filepath.Base(m.Meta["file"][1]))
m.Assert(e)
io.Copy(part, file)
for i := 0; i < len(arg)-1; i += 2 {
value := arg[i+1]
if len(arg[i+1]) > 1 {
switch arg[i+1][0] {
case '$':
value = m.Cap(arg[i+1][1:])
case '@':
value = m.Conf(arg[i+1][1:])
}
}
writer.WriteField(arg[i], value)
}
contenttype = writer.FormDataContentType()
body = buf
writer.Close()
} else if index > 0 {
contenttype = "application/x-www-form-urlencoded"
body = strings.NewReader(uri[index+1:])
uri = uri[:index]
if web, ok := m.Target().Server.(*WEB); m.Assert(ok) { // {{{
if web.client == nil {
web.client = &http.Client{}
}
}
req, e := http.NewRequest(method, uri, body)
m.Assert(e)
method := m.Confx("method")
uri := web.generate(m, arg[0], arg[1:]...)
m.Log("info", nil, "GET %s", uri)
m.Echo("%s: %s\n", method, uri)
if len(contenttype) > 0 {
req.Header.Set("Content-Type", contenttype)
}
var body io.Reader
index := strings.Index(uri, "?")
contenttype := ""
for _, v := range web.cookie {
req.AddCookie(v)
}
switch method {
case "POST":
if m.Options("file") {
file, e := os.Open(m.Meta["file"][1])
m.Assert(e)
defer file.Close()
res, e := web.client.Do(req)
m.Assert(e)
buf := &bytes.Buffer{}
writer := multipart.NewWriter(buf)
if web.cookie == nil {
web.cookie = make(map[string]*http.Cookie)
}
for _, v := range res.Cookies() {
web.cookie[v.Name] = v
}
part, e := writer.CreateFormFile(m.Option("file"), filepath.Base(m.Meta["file"][1]))
m.Assert(e)
io.Copy(part, file)
for k, v := range res.Header {
m.Log("info", nil, "%s: %v", k, v)
}
for i := 0; i < len(arg)-1; i += 2 {
value := arg[i+1]
if len(arg[i+1]) > 1 {
switch arg[i+1][0] {
case '$':
value = m.Cap(arg[i+1][1:])
case '@':
value = m.Conf(arg[i+1][1:])
}
}
writer.WriteField(arg[i], value)
}
if m.Confs("output") {
if _, e := os.Stat(m.Conf("output")); e == nil {
name := path.Join(m.Conf("output"), fmt.Sprintf("%d", time.Now().Unix()))
f, e := os.Create(name)
m.Assert(e)
io.Copy(f, res.Body)
if m.Confs("editor") {
cmd := exec.Command(m.Conf("editor"), name)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Run()
} else {
m.Echo("write to %s\n", name)
contenttype = writer.FormDataContentType()
body = buf
writer.Close()
} else if index > 0 {
contenttype = "application/x-www-form-urlencoded"
body = strings.NewReader(uri[index+1:])
uri = uri[:index]
}
}
req, e := http.NewRequest(method, uri, body)
m.Assert(e)
if len(contenttype) > 0 {
req.Header.Set("Content-Type", contenttype)
}
for _, v := range web.cookie {
req.AddCookie(v)
}
res, e := web.client.Do(req)
m.Assert(e)
if web.cookie == nil {
web.cookie = make(map[string]*http.Cookie)
}
for _, v := range res.Cookies() {
web.cookie[v.Name] = v
}
for k, v := range res.Header {
m.Log("info", nil, "%s: %v", k, v)
}
if m.Confs("output") {
if _, e := os.Stat(m.Conf("output")); e == nil {
name := path.Join(m.Conf("output"), fmt.Sprintf("%d", time.Now().Unix()))
f, e := os.Create(name)
m.Assert(e)
io.Copy(f, res.Body)
if m.Confs("editor") {
cmd := exec.Command(m.Conf("editor"), name)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Run()
} else {
m.Echo("write to %s\n", name)
}
return
}
}
buf, e := ioutil.ReadAll(res.Body)
m.Assert(e)
if res.Header.Get("Content-Type") == "application/json" {
result := map[string]interface{}{}
json.Unmarshal(buf, &result)
for k, v := range result {
switch value := v.(type) {
case string:
m.Append(k, value)
case float64:
m.Append(k, fmt.Sprintf("%d", int(value)))
default:
m.Put("append", k, value)
}
}
}
result := string(buf)
m.Echo(result)
m.Append("response", result)
} // }}}
}},
"serve": &ctx.Command{
Name: "serve [directory [address [protocol]]]",
Help: "启动服务, directory: 服务路径, address: 服务地址, protocol: 服务协议(https/http)",
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
m.Set("detail", arg...).Target().Start(m)
}},
"route": &ctx.Command{
Name: "route directory|template|script route content",
Help: "添加响应, directory: 目录响应, template: 模板响应, script: 脚本响应, route: 请求路由, content: 响应内容",
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
if mux, ok := m.Target().Server.(MUX); m.Assert(ok) { // {{{
if len(arg) < 3 {
for k, v := range m.Target().Commands {
if k[0] == '/' {
m.Echo("%s: %s\n", k, v.Name)
}
}
return
}
}
switch arg[0] {
case "directory":
mux.Handle(arg[1]+"/", http.StripPrefix(arg[1], http.FileServer(http.Dir(arg[2]))))
case "template":
mux.Trans(m, arg[1], func(m *ctx.Message, c *ctx.Context, key string, a ...string) {
w := m.Optionv("response").(http.ResponseWriter)
if _, e := os.Stat(arg[2]); e == nil {
template.Must(template.ParseGlob(arg[2])).Execute(w, m)
} else {
template.Must(template.New("temp").Parse(arg[2])).Execute(w, m)
}
})
case "script":
cli := m.Find("cli")
lex := m.Find("lex")
mux.Trans(m, arg[1], func(m *ctx.Message, c *ctx.Context, key string, a ...string) {
f, e := os.Open(arg[2])
line, bio := "", bufio.NewReader(f)
if e != nil {
line = arg[2]
}
buf, e := ioutil.ReadAll(res.Body)
m.Assert(e)
for {
if line = strings.TrimSpace(line); line != "" {
lex.Cmd("split", line, "void")
cli.Wait = make(chan bool)
cli.Cmd(lex.Meta["result"])
m.Meta["result"] = cli.Meta["result"]
}
if res.Header.Get("Content-Type") == "application/json" {
result := map[string]interface{}{}
json.Unmarshal(buf, &result)
for k, v := range result {
switch value := v.(type) {
case string:
m.Append(k, value)
case float64:
m.Append(k, fmt.Sprintf("%d", int(value)))
default:
m.Put("append", k, value)
}
if line, e = bio.ReadString('\n'); e != nil {
break
}
}
})
}
}
result := string(buf)
m.Echo(result)
m.Append("response", result)
// }}}
} // }}}
}},
"list": &ctx.Command{Name: "list [set|add|del [url]]", Help: "查看、访问、添加url", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
web, ok := m.Target().Server.(*WEB) // {{{
m.Assert(ok)
switch len(arg) {
case 0:
for _, k := range web.list_key {
if v, ok := web.list[k]; ok {
m.Echo("%s: %s\n", k, v)
}
}
case 1:
msg := m.Spawn(m.Target()).Cmd("get", web.list[arg[0]])
m.Copy(msg, "result")
default:
switch arg[0] {
case "add":
web.list[m.Cap("count")] = arg[1:]
web.list_key = append(web.list_key, m.Cap("count"))
m.Capi("count", 1)
case "del":
delete(web.list, arg[1])
case "set":
web.list[arg[1]] = arg[2:]
default:
list := []string{}
j := 1
for _, v := range web.list[arg[0]] {
if v == "_" && j < len(arg) {
list = append(list, arg[j])
j++
} else {
list = append(list, v)
}
}
for ; j < len(arg); j++ {
list = append(list, arg[j])
}
msg := m.Spawn(m.Target()).Cmd("get", list)
m.Copy(msg, "result")
}
} // }}}
}},
"upload": &ctx.Command{Name: "upload file", Help: "上传文件", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) {
msg := m.Spawn(m.Target()) // {{{
msg.Cmd("get", "/upload", "method", "POST", "file", "file", arg[0])