mirror of
https://shylinux.com/x/ContextOS
synced 2025-04-26 01:04:06 +08:00
mac pro web
This commit is contained in:
parent
ea2d45692d
commit
723d1824d6
@ -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)
|
||||
}
|
||||
}
|
||||
// }}}
|
||||
|
@ -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
|
||||
// }}}
|
||||
}},
|
||||
},
|
||||
|
@ -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])
|
||||
|
Loading…
x
Reference in New Issue
Block a user