mirror of
https://gitee.com/johng/gf
synced 2026-06-11 03:41:44 +08:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f9515d7126 | |||
| b56679a97c | |||
| d1b123964a | |||
| 991f7c4958 | |||
| 770619c39e | |||
| 4ad5450b80 | |||
| 49ce7fe885 | |||
| e66f63262b |
@ -4,16 +4,11 @@
|
||||
[](https://godoc.org/github.com/gogf/gf)
|
||||
[](https://travis-ci.org/gogf/gf)
|
||||
[](https://goreportcard.com/report/github.com/gogf/gf)
|
||||
[](https://goframe.org)
|
||||
[](https://codecov.io/gh/gogf/gf/branch/master)
|
||||
[](https://github.com/gogf/gf)
|
||||
[](https://github.com/gogf/gf)
|
||||
[](https://github.com/gogf/gf/releases)
|
||||
|
||||
<!--
|
||||
[](https://codecov.io/gh/gogf/gf)
|
||||
[](https://www.codetriage.com/gogf/gf)
|
||||
-->
|
||||
|
||||
`GF(Go Frame)`是一款模块化、松耦合、生产级Go应用开发框架。提供了常用的核心开发组件,如:缓存、日志、文件、时间、队列、数组、集合、字符串、定时器、命令行、文件锁、内存锁、对象池、连接池、数据校验、数据编码、文件监控、定时任务、数据库ORM、TCP/UDP组件、进程管理/通信、
|
||||
并发安全容器等等。并提供了Web服务开发的系列核心组件,如:Router、Cookie、Session、服务注册、配置管理、模板引擎等等,支持热重启、热更新、多域名、多端口、多服务、HTTPS、Rewrite等特性。
|
||||
|
||||
|
||||
@ -15,9 +15,8 @@
|
||||
package gqueue
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
"github.com/gogf/gf/g/container/glist"
|
||||
"math"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// 1、这是一个先进先出的队列(chan <-- list);
|
||||
@ -28,9 +27,8 @@ import (
|
||||
//
|
||||
// 4、由于功能主体是chan,那么操作仍然像chan那样具有阻塞效果;
|
||||
type Queue struct {
|
||||
mu sync.Mutex // 底层链表写锁
|
||||
limit int // 队列限制大小
|
||||
list *list.List // 底层数据链表
|
||||
list *glist.List // 底层数据链表
|
||||
events chan struct{} // 写入事件通知
|
||||
closed chan struct{} // 队列关闭通知
|
||||
C chan interface{} // 队列数据读取
|
||||
@ -50,7 +48,7 @@ func New(limit...int) *Queue {
|
||||
q.limit = limit[0]
|
||||
q.C = make(chan interface{}, limit[0])
|
||||
} else {
|
||||
q.list = list.New()
|
||||
q.list = glist.New()
|
||||
q.events = make(chan struct{}, math.MaxInt32)
|
||||
q.C = make(chan interface{}, gDEFAULT_QUEUE_SIZE)
|
||||
go q.startAsyncLoop()
|
||||
@ -68,7 +66,6 @@ func (q *Queue) startAsyncLoop() {
|
||||
for {
|
||||
if length := q.list.Len(); length > 0 {
|
||||
array := make([]interface{}, length)
|
||||
q.mu.Lock()
|
||||
for i := 0; i < length; i++ {
|
||||
if e := q.list.Front(); e != nil {
|
||||
array[i] = q.list.Remove(e)
|
||||
@ -76,7 +73,6 @@ func (q *Queue) startAsyncLoop() {
|
||||
break
|
||||
}
|
||||
}
|
||||
q.mu.Unlock()
|
||||
for _, v := range array {
|
||||
q.C <- v
|
||||
}
|
||||
@ -93,9 +89,7 @@ func (q *Queue) Push(v interface{}) {
|
||||
if q.limit > 0 {
|
||||
q.C <- v
|
||||
} else {
|
||||
q.mu.Lock()
|
||||
q.list.PushBack(v)
|
||||
q.mu.Unlock()
|
||||
q.events <- struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
3
g/g.go
3
g/g.go
@ -16,7 +16,8 @@ type Var = gvar.Var
|
||||
// Frequently-used map type alias.
|
||||
//
|
||||
// 常用map数据结构(使用别名)
|
||||
type Map = map[interface{}]interface{}
|
||||
type Map = map[string]interface{}
|
||||
type MapAnyAny = map[interface{}]interface{}
|
||||
type MapAnyStr = map[interface{}]string
|
||||
type MapAnyInt = map[interface{}]int
|
||||
type MapStrAny = map[string]interface{}
|
||||
|
||||
@ -45,13 +45,10 @@ func (r *Response) Write(content ... interface{}) {
|
||||
return
|
||||
}
|
||||
for _, v := range content {
|
||||
switch v.(type) {
|
||||
case []byte:
|
||||
// 如果是二进制数据,那么返回二进制数据
|
||||
r.buffer.Write(gconv.Bytes(v))
|
||||
|
||||
switch value := v.(type) {
|
||||
case []byte: r.buffer.Write(value)
|
||||
case string: r.buffer.WriteString(value)
|
||||
default:
|
||||
// 否则一律按照可显示的字符串进行转换
|
||||
r.buffer.WriteString(gconv.String(v))
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,10 +13,10 @@ import (
|
||||
)
|
||||
|
||||
// 展示模板,可以给定模板参数,及临时的自定义模板函数
|
||||
func (r *Response) WriteTpl(tpl string, params map[string]interface{}, funcmap...map[string]interface{}) error {
|
||||
func (r *Response) WriteTpl(tpl string, params map[string]interface{}, funcMap...map[string]interface{}) error {
|
||||
fmap := make(gview.FuncMap)
|
||||
if len(funcmap) > 0 {
|
||||
fmap = funcmap[0]
|
||||
if len(funcMap) > 0 {
|
||||
fmap = funcMap[0]
|
||||
}
|
||||
if b, err := r.ParseTpl(tpl, params, fmap); err != nil {
|
||||
r.Write("Tpl Parsing Error: " + err.Error())
|
||||
@ -28,10 +28,10 @@ func (r *Response) WriteTpl(tpl string, params map[string]interface{}, funcmap..
|
||||
}
|
||||
|
||||
// 展示模板内容,可以给定模板参数,及临时的自定义模板函数
|
||||
func (r *Response) WriteTplContent(content string, params map[string]interface{}, funcmap...map[string]interface{}) error {
|
||||
func (r *Response) WriteTplContent(content string, params map[string]interface{}, funcMap...map[string]interface{}) error {
|
||||
fmap := make(gview.FuncMap)
|
||||
if len(funcmap) > 0 {
|
||||
fmap = funcmap[0]
|
||||
if len(funcMap) > 0 {
|
||||
fmap = funcMap[0]
|
||||
}
|
||||
if b, err := r.ParseTplContent(content, params, fmap); err != nil {
|
||||
r.Write("Tpl Parsing Error: " + err.Error())
|
||||
@ -43,19 +43,19 @@ func (r *Response) WriteTplContent(content string, params map[string]interface{}
|
||||
}
|
||||
|
||||
// 解析模板文件,并返回模板内容
|
||||
func (r *Response) ParseTpl(tpl string, params gview.Params, funcmap...map[string]interface{}) ([]byte, error) {
|
||||
func (r *Response) ParseTpl(tpl string, params gview.Params, funcMap...map[string]interface{}) ([]byte, error) {
|
||||
fmap := make(gview.FuncMap)
|
||||
if len(funcmap) > 0 {
|
||||
fmap = funcmap[0]
|
||||
if len(funcMap) > 0 {
|
||||
fmap = funcMap[0]
|
||||
}
|
||||
return gins.View().Parse(tpl, r.buildInVars(params), r.buildInFuncs(fmap))
|
||||
}
|
||||
|
||||
// 解析并返回模板内容
|
||||
func (r *Response) ParseTplContent(content string, params gview.Params, funcmap...map[string]interface{}) ([]byte, error) {
|
||||
func (r *Response) ParseTplContent(content string, params gview.Params, funcMap...map[string]interface{}) ([]byte, error) {
|
||||
fmap := make(gview.FuncMap)
|
||||
if len(funcmap) > 0 {
|
||||
fmap = funcmap[0]
|
||||
if len(funcMap) > 0 {
|
||||
fmap = funcMap[0]
|
||||
}
|
||||
return gins.View().ParseContent(content, r.buildInVars(params), r.buildInFuncs(fmap))
|
||||
}
|
||||
@ -77,14 +77,14 @@ func (r *Response) buildInVars(params map[string]interface{}) map[string]interfa
|
||||
}
|
||||
|
||||
// 内置函数
|
||||
func (r *Response) buildInFuncs(funcmap map[string]interface{}) map[string]interface{} {
|
||||
if funcmap == nil {
|
||||
funcmap = make(map[string]interface{})
|
||||
func (r *Response) buildInFuncs(funcMap map[string]interface{}) map[string]interface{} {
|
||||
if funcMap == nil {
|
||||
funcMap = make(map[string]interface{})
|
||||
}
|
||||
funcmap["get"] = r.funcGet
|
||||
funcmap["post"] = r.funcPost
|
||||
funcmap["request"] = r.funcRequest
|
||||
return funcmap
|
||||
funcMap["get"] = r.funcGet
|
||||
funcMap["post"] = r.funcPost
|
||||
funcMap["request"] = r.funcRequest
|
||||
return funcMap
|
||||
}
|
||||
|
||||
// 模板内置函数: get
|
||||
|
||||
@ -75,6 +75,10 @@ func (s *Server) setHandler(pattern string, handler *handlerItem, hook ... strin
|
||||
glog.Error("invalid pattern:", pattern)
|
||||
return
|
||||
}
|
||||
if len(uri) == 0 || uri[0] != '/' {
|
||||
glog.Error("invalid pattern:", pattern)
|
||||
return
|
||||
}
|
||||
// 注册地址记录及重复注册判断
|
||||
regkey := s.handlerKey(hookName, method, uri, domain)
|
||||
caller := s.getHandlerRegisterCallerLine(handler)
|
||||
|
||||
@ -17,7 +17,7 @@ var (
|
||||
)
|
||||
|
||||
func init() {
|
||||
for i := 8000; i <= 8100; i++ {
|
||||
for i := 8000; i <= 9000; i++ {
|
||||
ports.Append(i)
|
||||
}
|
||||
}
|
||||
|
||||
126
g/net/ghttp/ghttp_unit_router_exit_test.go
Normal file
126
g/net/ghttp/ghttp_unit_router_exit_test.go
Normal file
@ -0,0 +1,126 @@
|
||||
// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package ghttp_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Test_Router_Exit(t *testing.T) {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
s.BindHookHandlerByMap("/*", map[string]ghttp.HandlerFunc{
|
||||
"BeforeServe" : func(r *ghttp.Request){ r.Response.Write("1") },
|
||||
"AfterServe" : func(r *ghttp.Request){ r.Response.Write("2") },
|
||||
"BeforeOutput" : func(r *ghttp.Request){ r.Response.Write("3") },
|
||||
"AfterOutput" : func(r *ghttp.Request){ r.Response.Write("4") },
|
||||
"BeforeClose" : func(r *ghttp.Request){ r.Response.Write("5") },
|
||||
"AfterClose" : func(r *ghttp.Request){ r.Response.Write("6") },
|
||||
})
|
||||
s.BindHandler("/test/test", func(r *ghttp.Request) {
|
||||
r.Response.Write("test-start")
|
||||
r.Exit()
|
||||
r.Response.Write("test-end")
|
||||
})
|
||||
s.SetPort(p)
|
||||
s.SetDumpRouteMap(false)
|
||||
s.Start()
|
||||
defer s.Shutdown()
|
||||
|
||||
// 等待启动完成
|
||||
time.Sleep(time.Second)
|
||||
gtest.Case(t, func() {
|
||||
client := ghttp.NewClient()
|
||||
client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p))
|
||||
|
||||
gtest.Assert(client.GetContent("/"), "123")
|
||||
gtest.Assert(client.GetContent("/test/test"), "1test-start23")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Router_ExitHook(t *testing.T) {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
s.BindHandler("/priority/show", func(r *ghttp.Request) {
|
||||
r.Response.Write("show")
|
||||
})
|
||||
|
||||
s.BindHookHandlerByMap("/priority/:name", map[string]ghttp.HandlerFunc {
|
||||
"BeforeServe" : func(r *ghttp.Request) {
|
||||
r.Response.Write("1")
|
||||
},
|
||||
})
|
||||
s.BindHookHandlerByMap("/priority/*any", map[string]ghttp.HandlerFunc {
|
||||
"BeforeServe" : func(r *ghttp.Request) {
|
||||
r.Response.Write("2")
|
||||
},
|
||||
})
|
||||
s.BindHookHandlerByMap("/priority/show", map[string]ghttp.HandlerFunc {
|
||||
"BeforeServe" : func(r *ghttp.Request) {
|
||||
r.Response.Write("3")
|
||||
r.ExitHook()
|
||||
},
|
||||
})
|
||||
s.SetPort(p)
|
||||
s.SetDumpRouteMap(false)
|
||||
s.Start()
|
||||
defer s.Shutdown()
|
||||
|
||||
// 等待启动完成
|
||||
time.Sleep(time.Second)
|
||||
gtest.Case(t, func() {
|
||||
client := ghttp.NewClient()
|
||||
client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p))
|
||||
|
||||
gtest.Assert(client.GetContent("/"), "Not Found")
|
||||
gtest.Assert(client.GetContent("/priority/show"), "3show")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Router_ExitAll(t *testing.T) {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
s.BindHandler("/priority/show", func(r *ghttp.Request) {
|
||||
r.Response.Write("show")
|
||||
})
|
||||
|
||||
s.BindHookHandlerByMap("/priority/:name", map[string]ghttp.HandlerFunc {
|
||||
"BeforeServe" : func(r *ghttp.Request) {
|
||||
r.Response.Write("1")
|
||||
},
|
||||
})
|
||||
s.BindHookHandlerByMap("/priority/*any", map[string]ghttp.HandlerFunc {
|
||||
"BeforeServe" : func(r *ghttp.Request) {
|
||||
r.Response.Write("2")
|
||||
},
|
||||
})
|
||||
s.BindHookHandlerByMap("/priority/show", map[string]ghttp.HandlerFunc {
|
||||
"BeforeServe" : func(r *ghttp.Request) {
|
||||
r.Response.Write("3")
|
||||
r.ExitAll()
|
||||
},
|
||||
})
|
||||
s.SetPort(p)
|
||||
s.SetDumpRouteMap(false)
|
||||
s.Start()
|
||||
defer s.Shutdown()
|
||||
|
||||
// 等待启动完成
|
||||
time.Sleep(time.Second)
|
||||
gtest.Case(t, func() {
|
||||
client := ghttp.NewClient()
|
||||
client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p))
|
||||
|
||||
gtest.Assert(client.GetContent("/"), "Not Found")
|
||||
gtest.Assert(client.GetContent("/priority/show"), "3")
|
||||
})
|
||||
}
|
||||
87
g/net/ghttp/ghttp_unit_router_hook_test.go
Normal file
87
g/net/ghttp/ghttp_unit_router_hook_test.go
Normal file
@ -0,0 +1,87 @@
|
||||
// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package ghttp_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Test_Router_Hook_Basic(t *testing.T) {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
s.BindHookHandlerByMap("/*", map[string]ghttp.HandlerFunc{
|
||||
"BeforeServe" : func(r *ghttp.Request){ r.Response.Write("1") },
|
||||
"AfterServe" : func(r *ghttp.Request){ r.Response.Write("2") },
|
||||
"BeforeOutput" : func(r *ghttp.Request){ r.Response.Write("3") },
|
||||
"AfterOutput" : func(r *ghttp.Request){ r.Response.Write("4") },
|
||||
"BeforeClose" : func(r *ghttp.Request){ r.Response.Write("5") },
|
||||
"AfterClose" : func(r *ghttp.Request){ r.Response.Write("6") },
|
||||
})
|
||||
s.BindHandler("/test/test", func(r *ghttp.Request) {
|
||||
r.Response.Write("test")
|
||||
})
|
||||
s.SetPort(p)
|
||||
s.SetDumpRouteMap(false)
|
||||
s.Start()
|
||||
defer s.Shutdown()
|
||||
|
||||
// 等待启动完成
|
||||
time.Sleep(time.Second)
|
||||
gtest.Case(t, func() {
|
||||
client := ghttp.NewClient()
|
||||
client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p))
|
||||
|
||||
gtest.Assert(client.GetContent("/"), "123")
|
||||
gtest.Assert(client.GetContent("/test/test"), "1test23")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Router_Hook_Priority(t *testing.T) {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
s.BindHandler("/priority/show", func(r *ghttp.Request) {
|
||||
r.Response.Write("show")
|
||||
})
|
||||
|
||||
s.BindHookHandlerByMap("/priority/:name", map[string]ghttp.HandlerFunc {
|
||||
"BeforeServe" : func(r *ghttp.Request) {
|
||||
r.Response.Write("1")
|
||||
},
|
||||
})
|
||||
s.BindHookHandlerByMap("/priority/*any", map[string]ghttp.HandlerFunc {
|
||||
"BeforeServe" : func(r *ghttp.Request) {
|
||||
r.Response.Write("2")
|
||||
},
|
||||
})
|
||||
s.BindHookHandlerByMap("/priority/show", map[string]ghttp.HandlerFunc {
|
||||
"BeforeServe" : func(r *ghttp.Request) {
|
||||
r.Response.Write("3")
|
||||
},
|
||||
})
|
||||
s.SetPort(p)
|
||||
s.SetDumpRouteMap(false)
|
||||
s.Start()
|
||||
defer s.Shutdown()
|
||||
|
||||
// 等待启动完成
|
||||
time.Sleep(time.Second)
|
||||
gtest.Case(t, func() {
|
||||
client := ghttp.NewClient()
|
||||
client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p))
|
||||
|
||||
gtest.Assert(client.GetContent("/"), "Not Found")
|
||||
gtest.Assert(client.GetContent("/priority/show"), "312show")
|
||||
gtest.Assert(client.GetContent("/priority/any/any"), "2")
|
||||
gtest.Assert(client.GetContent("/priority/name"), "12")
|
||||
})
|
||||
}
|
||||
|
||||
@ -6,3 +6,107 @@
|
||||
|
||||
package ghttp_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
type NamesObject struct {}
|
||||
|
||||
func (o *NamesObject) ShowName(r *ghttp.Request) {
|
||||
r.Response.Write("Object Show Name")
|
||||
}
|
||||
|
||||
func Test_NameToUri_FullName(t *testing.T) {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
s.SetNameToUriType(ghttp.NAME_TO_URI_TYPE_FULLNAME)
|
||||
s.BindObject("/{.struct}/{.method}", new(NamesObject))
|
||||
s.SetPort(p)
|
||||
s.SetDumpRouteMap(false)
|
||||
s.Start()
|
||||
defer s.Shutdown()
|
||||
|
||||
// 等待启动完成
|
||||
time.Sleep(time.Second)
|
||||
gtest.Case(t, func() {
|
||||
client := ghttp.NewClient()
|
||||
client.SetBrowserMode(true)
|
||||
client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p))
|
||||
gtest.Assert(client.GetContent("/"), "Not Found")
|
||||
gtest.Assert(client.GetContent("/NamesObject"), "Not Found")
|
||||
gtest.Assert(client.GetContent("/NamesObject/ShowName"), "Object Show Name")
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
func Test_NameToUri_AllLower(t *testing.T) {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
s.SetNameToUriType(ghttp.NAME_TO_URI_TYPE_ALLLOWER)
|
||||
s.BindObject("/{.struct}/{.method}", new(NamesObject))
|
||||
s.SetPort(p)
|
||||
s.SetDumpRouteMap(false)
|
||||
s.Start()
|
||||
defer s.Shutdown()
|
||||
|
||||
// 等待启动完成
|
||||
time.Sleep(time.Second)
|
||||
gtest.Case(t, func() {
|
||||
client := ghttp.NewClient()
|
||||
client.SetBrowserMode(true)
|
||||
client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p))
|
||||
gtest.Assert(client.GetContent("/"), "Not Found")
|
||||
gtest.Assert(client.GetContent("/NamesObject"), "Not Found")
|
||||
gtest.Assert(client.GetContent("/namesobject/showname"), "Object Show Name")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_NameToUri_Camel(t *testing.T) {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
s.SetNameToUriType(ghttp.NAME_TO_URI_TYPE_CAMEL)
|
||||
s.BindObject("/{.struct}/{.method}", new(NamesObject))
|
||||
s.SetPort(p)
|
||||
s.SetDumpRouteMap(false)
|
||||
s.Start()
|
||||
defer s.Shutdown()
|
||||
|
||||
// 等待启动完成
|
||||
time.Sleep(time.Second)
|
||||
gtest.Case(t, func() {
|
||||
client := ghttp.NewClient()
|
||||
client.SetBrowserMode(true)
|
||||
client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p))
|
||||
gtest.Assert(client.GetContent("/"), "Not Found")
|
||||
gtest.Assert(client.GetContent("/NamesObject"), "Not Found")
|
||||
gtest.Assert(client.GetContent("/namesObject/showName"), "Object Show Name")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_NameToUri_Default(t *testing.T) {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
s.SetNameToUriType(ghttp.NAME_TO_URI_TYPE_DEFAULT)
|
||||
s.BindObject("/{.struct}/{.method}", new(NamesObject))
|
||||
s.SetPort(p)
|
||||
s.SetDumpRouteMap(false)
|
||||
s.Start()
|
||||
defer s.Shutdown()
|
||||
|
||||
// 等待启动完成
|
||||
time.Sleep(time.Second)
|
||||
gtest.Case(t, func() {
|
||||
client := ghttp.NewClient()
|
||||
client.SetBrowserMode(true)
|
||||
client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p))
|
||||
gtest.Assert(client.GetContent("/"), "Not Found")
|
||||
gtest.Assert(client.GetContent("/NamesObject"), "Not Found")
|
||||
gtest.Assert(client.GetContent("/names-object/show-name"), "Object Show Name")
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
232
g/net/ghttp/ghttp_unit_static_test.go
Normal file
232
g/net/ghttp/ghttp_unit_static_test.go
Normal file
@ -0,0 +1,232 @@
|
||||
// Copyright 2018 gf Author(https://github.com/gogf/gf). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
// 静态文件服务测试
|
||||
package ghttp_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/g"
|
||||
"github.com/gogf/gf/g/net/ghttp"
|
||||
"github.com/gogf/gf/g/os/gfile"
|
||||
"github.com/gogf/gf/g/test/gtest"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func Test_Static_Folder_Forbidden(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
path := fmt.Sprintf(`%s/ghttp/static/test/%d`, gfile.TempDir(), p)
|
||||
defer gfile.Remove(path)
|
||||
gfile.PutContents(path + "/test.html", "test")
|
||||
s.SetServerRoot(path)
|
||||
s.SetPort(p)
|
||||
s.Start()
|
||||
defer s.Shutdown()
|
||||
time.Sleep(time.Second)
|
||||
client := ghttp.NewClient()
|
||||
client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p))
|
||||
|
||||
gtest.Assert(client.GetContent("/"), "Forbidden")
|
||||
gtest.Assert(client.GetContent("/index.html"), "Not Found")
|
||||
gtest.Assert(client.GetContent("/test.html"), "test")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Static_IndexFolder(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
path := fmt.Sprintf(`%s/ghttp/static/test/%d`, gfile.TempDir(), p)
|
||||
defer gfile.Remove(path)
|
||||
gfile.PutContents(path + "/test.html", "test")
|
||||
s.SetIndexFolder(true)
|
||||
s.SetServerRoot(path)
|
||||
s.SetPort(p)
|
||||
s.Start()
|
||||
defer s.Shutdown()
|
||||
time.Sleep(time.Second)
|
||||
client := ghttp.NewClient()
|
||||
client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p))
|
||||
|
||||
gtest.AssertNE(client.GetContent("/"), "Forbidden")
|
||||
gtest.Assert(client.GetContent("/index.html"), "Not Found")
|
||||
gtest.Assert(client.GetContent("/test.html"), "test")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Static_IndexFiles1(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
path := fmt.Sprintf(`%s/ghttp/static/test/%d`, gfile.TempDir(), p)
|
||||
defer gfile.Remove(path)
|
||||
gfile.PutContents(path + "/index.html", "index")
|
||||
gfile.PutContents(path + "/test.html", "test")
|
||||
s.SetServerRoot(path)
|
||||
s.SetPort(p)
|
||||
s.Start()
|
||||
defer s.Shutdown()
|
||||
time.Sleep(time.Second)
|
||||
client := ghttp.NewClient()
|
||||
client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p))
|
||||
|
||||
gtest.Assert(client.GetContent("/"), "index")
|
||||
gtest.Assert(client.GetContent("/index.html"), "index")
|
||||
gtest.Assert(client.GetContent("/test.html"), "test")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Static_IndexFiles2(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
path := fmt.Sprintf(`%s/ghttp/static/test/%d`, gfile.TempDir(), p)
|
||||
defer gfile.Remove(path)
|
||||
gfile.PutContents(path + "/test.html", "test")
|
||||
s.SetIndexFiles([]string{"index.html", "test.html"})
|
||||
s.SetServerRoot(path)
|
||||
s.SetPort(p)
|
||||
s.Start()
|
||||
defer s.Shutdown()
|
||||
time.Sleep(time.Second)
|
||||
client := ghttp.NewClient()
|
||||
client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p))
|
||||
|
||||
gtest.Assert(client.GetContent("/"), "test")
|
||||
gtest.Assert(client.GetContent("/index.html"), "Not Found")
|
||||
gtest.Assert(client.GetContent("/test.html"), "test")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Static_AddSearchPath1(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
path1 := fmt.Sprintf(`%s/ghttp/static/test/%d`, gfile.TempDir(), p)
|
||||
path2 := fmt.Sprintf(`%s/ghttp/static/test/%d/%d`, gfile.TempDir(), p, p)
|
||||
defer gfile.Remove(path1)
|
||||
defer gfile.Remove(path2)
|
||||
gfile.PutContents(path2 + "/test.html", "test")
|
||||
s.SetServerRoot(path1)
|
||||
s.AddSearchPath(path2)
|
||||
s.SetPort(p)
|
||||
s.Start()
|
||||
defer s.Shutdown()
|
||||
time.Sleep(time.Second)
|
||||
client := ghttp.NewClient()
|
||||
client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p))
|
||||
|
||||
gtest.Assert(client.GetContent("/"), "Forbidden")
|
||||
gtest.Assert(client.GetContent("/test.html"), "test")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Static_AddSearchPath2(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
path1 := fmt.Sprintf(`%s/ghttp/static/test/%d`, gfile.TempDir(), p)
|
||||
path2 := fmt.Sprintf(`%s/ghttp/static/test/%d/%d`, gfile.TempDir(), p, p)
|
||||
defer gfile.Remove(path1)
|
||||
defer gfile.Remove(path2)
|
||||
gfile.PutContents(path1 + "/test.html", "test1")
|
||||
gfile.PutContents(path2 + "/test.html", "test2")
|
||||
s.SetServerRoot(path1)
|
||||
s.AddSearchPath(path2)
|
||||
s.SetPort(p)
|
||||
s.Start()
|
||||
defer s.Shutdown()
|
||||
time.Sleep(time.Second)
|
||||
client := ghttp.NewClient()
|
||||
client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p))
|
||||
|
||||
gtest.Assert(client.GetContent("/"), "Forbidden")
|
||||
gtest.Assert(client.GetContent("/test.html"), "test1")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Static_AddStaticPath(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
path1 := fmt.Sprintf(`%s/ghttp/static/test/%d`, gfile.TempDir(), p)
|
||||
path2 := fmt.Sprintf(`%s/ghttp/static/test/%d/%d`, gfile.TempDir(), p, p)
|
||||
defer gfile.Remove(path1)
|
||||
defer gfile.Remove(path2)
|
||||
gfile.PutContents(path1 + "/test.html", "test1")
|
||||
gfile.PutContents(path2 + "/test.html", "test2")
|
||||
s.SetServerRoot(path1)
|
||||
s.AddStaticPath("/my-test", path2)
|
||||
s.SetPort(p)
|
||||
s.Start()
|
||||
defer s.Shutdown()
|
||||
time.Sleep(time.Second)
|
||||
client := ghttp.NewClient()
|
||||
client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p))
|
||||
|
||||
gtest.Assert(client.GetContent("/"), "Forbidden")
|
||||
gtest.Assert(client.GetContent("/test.html"), "test1")
|
||||
gtest.Assert(client.GetContent("/my-test/test.html"), "test2")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Static_AddStaticPath_Priority(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
path1 := fmt.Sprintf(`%s/ghttp/static/test/%d/test`, gfile.TempDir(), p)
|
||||
path2 := fmt.Sprintf(`%s/ghttp/static/test/%d/%d/test`, gfile.TempDir(), p, p)
|
||||
defer gfile.Remove(path1)
|
||||
defer gfile.Remove(path2)
|
||||
gfile.PutContents(path1 + "/test.html", "test1")
|
||||
gfile.PutContents(path2 + "/test.html", "test2")
|
||||
s.SetServerRoot(path1)
|
||||
s.AddStaticPath("/test", path2)
|
||||
s.SetPort(p)
|
||||
s.Start()
|
||||
defer s.Shutdown()
|
||||
time.Sleep(time.Second)
|
||||
client := ghttp.NewClient()
|
||||
client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p))
|
||||
|
||||
gtest.Assert(client.GetContent("/"), "Forbidden")
|
||||
gtest.Assert(client.GetContent("/test.html"), "test1")
|
||||
gtest.Assert(client.GetContent("/test/test.html"), "test2")
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Static_Rewrite(t *testing.T) {
|
||||
gtest.Case(t, func() {
|
||||
p := ports.PopRand()
|
||||
s := g.Server(p)
|
||||
path := fmt.Sprintf(`%s/ghttp/static/test/%d`, gfile.TempDir(), p)
|
||||
defer gfile.Remove(path)
|
||||
gfile.PutContents(path + "/test1.html", "test1")
|
||||
gfile.PutContents(path + "/test2.html", "test2")
|
||||
s.SetServerRoot(path)
|
||||
s.SetRewrite("/test.html", "/test1.html")
|
||||
s.SetRewriteMap(g.MapStrStr{
|
||||
"/my-test1" : "/test1.html",
|
||||
"/my-test2" : "/test2.html",
|
||||
})
|
||||
s.SetPort(p)
|
||||
s.Start()
|
||||
defer s.Shutdown()
|
||||
time.Sleep(time.Second)
|
||||
client := ghttp.NewClient()
|
||||
client.SetPrefix(fmt.Sprintf("http://127.0.0.1:%d", p))
|
||||
|
||||
gtest.Assert(client.GetContent("/"), "Forbidden")
|
||||
gtest.Assert(client.GetContent("/test.html"), "test1")
|
||||
gtest.Assert(client.GetContent("/test1.html"), "test1")
|
||||
gtest.Assert(client.GetContent("/test2.html"), "test2")
|
||||
gtest.Assert(client.GetContent("/my-test1"), "test1")
|
||||
gtest.Assert(client.GetContent("/my-test2"), "test2")
|
||||
})
|
||||
}
|
||||
@ -39,14 +39,14 @@ func TestCron_Add_Close(t *testing.T) {
|
||||
gtest.AssertNE(err3, nil)
|
||||
gtest.Assert(err4, nil)
|
||||
gtest.Assert(cron.Size(), 3)
|
||||
time.Sleep(1100*time.Millisecond)
|
||||
time.Sleep(1200*time.Millisecond)
|
||||
gtest.Assert(array.Len(), 2)
|
||||
time.Sleep(1100*time.Millisecond)
|
||||
time.Sleep(1200*time.Millisecond)
|
||||
gtest.Assert(array.Len(), 5)
|
||||
cron.Close()
|
||||
time.Sleep(1100*time.Millisecond)
|
||||
time.Sleep(1200*time.Millisecond)
|
||||
fixedLength := array.Len()
|
||||
time.Sleep(1100*time.Millisecond)
|
||||
time.Sleep(1200*time.Millisecond)
|
||||
gtest.Assert(array.Len(), fixedLength)
|
||||
})
|
||||
}
|
||||
|
||||
@ -18,7 +18,7 @@ func (w *Watcher) startWatchLoop() {
|
||||
// 关闭事件
|
||||
case <- w.closeChan: return
|
||||
|
||||
// 监听事件
|
||||
// 监听事件
|
||||
case ev := <- w.watcher.Events:
|
||||
//fmt.Println("ev:", ev.String())
|
||||
w.cache.SetIfNotExist(ev.String(), func() interface{} {
|
||||
|
||||
@ -232,7 +232,7 @@ func AssertNI(value, expect interface{}) {
|
||||
|
||||
// 提示错误不退出进程执行
|
||||
func Error(message...interface{}) {
|
||||
fmt.Fprintf(os.Stderr, "[ERROR] %s\n%s", fmt.Sprint(message...), getBacktrace())
|
||||
panic(fmt.Sprintf("[ERROR] %s", fmt.Sprint(message...)))
|
||||
}
|
||||
|
||||
// 提示错误并退出进程执行
|
||||
|
||||
@ -109,11 +109,8 @@ func Test_Struct_Attr_Slice(t *testing.T) {
|
||||
type User struct {
|
||||
Scores []int
|
||||
}
|
||||
|
||||
user := new(User)
|
||||
scores := []interface{}{99, 100, 60, 140}
|
||||
|
||||
// 通过map映射转换
|
||||
user := new(User)
|
||||
if err := gconv.Struct(g.Map{"Scores" : scores}, user); err != nil {
|
||||
gtest.Error(err)
|
||||
} else {
|
||||
@ -121,15 +118,6 @@ func Test_Struct_Attr_Slice(t *testing.T) {
|
||||
Scores : []int{99, 100, 60, 140},
|
||||
})
|
||||
}
|
||||
|
||||
// 通过变量映射转换,直接slice赋值
|
||||
if err := gconv.Struct(scores, user); err != nil {
|
||||
gtest.Error(err)
|
||||
} else {
|
||||
gtest.Assert(user, &User{
|
||||
Scores : []int{99, 100, 60, 140},
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
package gf
|
||||
|
||||
const VERSION = "v1.5.12"
|
||||
const VERSION = "v1.5.13"
|
||||
const AUTHORS = "john<john@goframe.org>"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user