Merge branch 'develop' of https://github.com/astaxie/beego into fix-issue-4176

This commit is contained in:
AllenX2018
2020-12-26 16:33:09 +08:00
33 changed files with 483 additions and 683 deletions

View File

@@ -24,7 +24,7 @@ import (
"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/astaxie/beego/core/governor"
"github.com/astaxie/beego/core/admin"
)
type adminController struct {
@@ -51,7 +51,7 @@ func (a *adminController) ProfIndex() {
data = make(map[interface{}]interface{})
result bytes.Buffer
)
governor.ProcessInput(command, &result)
admin.ProcessInput(command, &result)
data["Content"] = template.HTMLEscapeString(result.String())
if format == "json" && command == "gc summary" {
@@ -88,7 +88,7 @@ func (a *adminController) TaskStatus() {
req.ParseForm()
taskname := req.Form.Get("taskname")
if taskname != "" {
cmd := governor.GetCommand("task", "run")
cmd := admin.GetCommand("task", "run")
res := cmd.Execute(taskname)
if res.IsSuccess() {
@@ -103,7 +103,7 @@ func (a *adminController) TaskStatus() {
// List Tasks
content := make(M)
resultList := governor.GetCommand("task", "list").Execute().Content.([][]string)
resultList := admin.GetCommand("task", "list").Execute().Content.([][]string)
var fields = []string{
"Task Name",
"Task Spec",
@@ -141,7 +141,7 @@ func heathCheck(rw http.ResponseWriter, r *http.Request) {
}
)
for name, h := range governor.AdminCheckList {
for name, h := range admin.AdminCheckList {
if err := h.Check(); err != nil {
result = []string{
"error",

View File

@@ -11,7 +11,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/astaxie/beego/core/governor"
"github.com/astaxie/beego/core/admin"
)
type SampleDatabaseCheck struct {
@@ -126,8 +126,8 @@ func TestWriteJSON(t *testing.T) {
func TestHealthCheckHandlerDefault(t *testing.T) {
endpointPath := "/healthcheck"
governor.AddHealthCheck("database", &SampleDatabaseCheck{})
governor.AddHealthCheck("cache", &SampleCacheCheck{})
admin.AddHealthCheck("database", &SampleDatabaseCheck{})
admin.AddHealthCheck("cache", &SampleCacheCheck{})
req, err := http.NewRequest("GET", endpointPath, nil)
if err != nil {
@@ -187,8 +187,8 @@ func TestBuildHealthCheckResponseList(t *testing.T) {
func TestHealthCheckHandlerReturnsJSON(t *testing.T) {
governor.AddHealthCheck("database", &SampleDatabaseCheck{})
governor.AddHealthCheck("cache", &SampleCacheCheck{})
admin.AddHealthCheck("database", &SampleDatabaseCheck{})
admin.AddHealthCheck("cache", &SampleCacheCheck{})
req, err := http.NewRequest("GET", "/healthcheck?json=true", nil)
if err != nil {

View File

@@ -21,7 +21,7 @@ var indexTpl = `
For detail usage please check our document:
</p>
<p>
<a target="_blank" href="http://beego.me/docs/module/governor.md">Toolbox</a>
<a target="_blank" href="http://beego.me/docs/module/admin.md">Toolbox</a>
</p>
<p>
<a target="_blank" href="http://beego.me/docs/advantage/monitor.md">Live Monitor</a>

View File

@@ -149,7 +149,8 @@ func (ctx *Context) XSRFToken(key string, expire int64) string {
token, ok := ctx.GetSecureCookie(key, "_xsrf")
if !ok {
token = string(utils.RandomCreateBytes(32))
ctx.SetSecureCookie(key, "_xsrf", token, expire, "", "", true, true)
// TODO make it configurable
ctx.SetSecureCookie(key, "_xsrf", token, expire, "", "")
}
ctx._xsrfToken = token
}

View File

@@ -261,15 +261,15 @@ func (output *BeegoOutput) XML(data interface{}, hasIndent bool) error {
}
// ServeFormatted serves YAML, XML or JSON, depending on the value of the Accept header
func (output *BeegoOutput) ServeFormatted(data interface{}, hasIndent bool, hasEncode ...bool) {
func (output *BeegoOutput) ServeFormatted(data interface{}, hasIndent bool, hasEncode ...bool) error {
accept := output.Context.Input.Header("Accept")
switch accept {
case ApplicationYAML:
output.YAML(data)
return output.YAML(data)
case ApplicationXML, TextXML:
output.XML(data, hasIndent)
return output.XML(data, hasIndent)
default:
output.JSON(data, hasIndent, len(hasEncode) > 0 && hasEncode[0])
return output.JSON(data, hasIndent, len(hasEncode) > 0 && hasEncode[0])
}
}

View File

@@ -16,6 +16,7 @@ package web
import (
"bytes"
context2 "context"
"errors"
"fmt"
"html/template"
@@ -250,13 +251,16 @@ func (c *Controller) Render() error {
// RenderString returns the rendered template string. Do not send out response.
func (c *Controller) RenderString() (string, error) {
b, e := c.RenderBytes()
if e != nil {
return "", e
}
return string(b), e
}
// RenderBytes returns the bytes of rendered template string. Do not send out response.
func (c *Controller) RenderBytes() ([]byte, error) {
buf, err := c.renderTemplate()
//if the controller has set layout, then first get the tplName's content set the content to the layout
// if the controller has set layout, then first get the tplName's content set the content to the layout
if err == nil && c.Layout != "" {
c.Data["LayoutContent"] = template.HTML(buf.String())
@@ -276,7 +280,7 @@ func (c *Controller) RenderBytes() ([]byte, error) {
}
buf.Reset()
ExecuteViewPathTemplate(&buf, c.Layout, c.viewPath(), c.Data)
err = ExecuteViewPathTemplate(&buf, c.Layout, c.viewPath(), c.Data)
}
return buf.Bytes(), err
}
@@ -373,50 +377,57 @@ func (c *Controller) URLFor(endpoint string, values ...interface{}) string {
}
// ServeJSON sends a json response with encoding charset.
func (c *Controller) ServeJSON(encoding ...bool) {
func (c *Controller) ServeJSON(encoding ...bool) error {
var (
hasIndent = BConfig.RunMode != PROD
hasEncoding = len(encoding) > 0 && encoding[0]
)
c.Ctx.Output.JSON(c.Data["json"], hasIndent, hasEncoding)
return c.Ctx.Output.JSON(c.Data["json"], hasIndent, hasEncoding)
}
// ServeJSONP sends a jsonp response.
func (c *Controller) ServeJSONP() {
func (c *Controller) ServeJSONP() error {
hasIndent := BConfig.RunMode != PROD
c.Ctx.Output.JSONP(c.Data["jsonp"], hasIndent)
return c.Ctx.Output.JSONP(c.Data["jsonp"], hasIndent)
}
// ServeXML sends xml response.
func (c *Controller) ServeXML() {
func (c *Controller) ServeXML() error {
hasIndent := BConfig.RunMode != PROD
c.Ctx.Output.XML(c.Data["xml"], hasIndent)
return c.Ctx.Output.XML(c.Data["xml"], hasIndent)
}
// ServeYAML sends yaml response.
func (c *Controller) ServeYAML() {
c.Ctx.Output.YAML(c.Data["yaml"])
func (c *Controller) ServeYAML() error {
return c.Ctx.Output.YAML(c.Data["yaml"])
}
// ServeFormatted serve YAML, XML OR JSON, depending on the value of the Accept header
func (c *Controller) ServeFormatted(encoding ...bool) {
func (c *Controller) ServeFormatted(encoding ...bool) error {
hasIndent := BConfig.RunMode != PROD
hasEncoding := len(encoding) > 0 && encoding[0]
c.Ctx.Output.ServeFormatted(c.Data, hasIndent, hasEncoding)
return c.Ctx.Output.ServeFormatted(c.Data, hasIndent, hasEncoding)
}
// Input returns the input data map from POST or PUT request body and query string.
func (c *Controller) Input() url.Values {
func (c *Controller) Input() (url.Values, error) {
if c.Ctx.Request.Form == nil {
c.Ctx.Request.ParseForm()
err := c.Ctx.Request.ParseForm()
if err != nil {
return nil, err
}
}
return c.Ctx.Request.Form
return c.Ctx.Request.Form, nil
}
// ParseForm maps input data map to obj struct.
func (c *Controller) ParseForm(obj interface{}) error {
return ParseForm(c.Input(), obj)
form, err := c.Input()
if err != nil {
return err
}
return ParseForm(form, obj)
}
// GetString returns the input value by key string or the default value while it's present and input is blank
@@ -438,7 +449,7 @@ func (c *Controller) GetStrings(key string, def ...[]string) []string {
defv = def[0]
}
if f := c.Input(); f == nil {
if f, err := c.Input(); f == nil || err != nil {
return defv
} else if vs := f[key]; len(vs) > 0 {
return vs
@@ -618,11 +629,11 @@ func (c *Controller) StartSession() session.Store {
}
// SetSession puts value into session.
func (c *Controller) SetSession(name interface{}, value interface{}) {
func (c *Controller) SetSession(name interface{}, value interface{}) error {
if c.CruSession == nil {
c.StartSession()
}
c.CruSession.Set(nil, name, value)
return c.CruSession.Set(context2.Background(), name, value)
}
// GetSession gets value from session.
@@ -630,32 +641,38 @@ func (c *Controller) GetSession(name interface{}) interface{} {
if c.CruSession == nil {
c.StartSession()
}
return c.CruSession.Get(nil, name)
return c.CruSession.Get(context2.Background(), name)
}
// DelSession removes value from session.
func (c *Controller) DelSession(name interface{}) {
func (c *Controller) DelSession(name interface{}) error {
if c.CruSession == nil {
c.StartSession()
}
c.CruSession.Delete(nil, name)
return c.CruSession.Delete(context2.Background(), name)
}
// SessionRegenerateID regenerates session id for this session.
// the session data have no changes.
func (c *Controller) SessionRegenerateID() {
func (c *Controller) SessionRegenerateID() error {
if c.CruSession != nil {
c.CruSession.SessionRelease(nil, c.Ctx.ResponseWriter)
c.CruSession.SessionRelease(context2.Background(), c.Ctx.ResponseWriter)
}
c.CruSession = GlobalSessions.SessionRegenerateID(c.Ctx.ResponseWriter, c.Ctx.Request)
var err error
c.CruSession, err = GlobalSessions.SessionRegenerateID(c.Ctx.ResponseWriter, c.Ctx.Request)
c.Ctx.Input.CruSession = c.CruSession
return err
}
// DestroySession cleans session data and session cookie.
func (c *Controller) DestroySession() {
c.Ctx.Input.CruSession.Flush(nil)
func (c *Controller) DestroySession() error {
err := c.Ctx.Input.CruSession.Flush(nil)
if err != nil {
return err
}
c.Ctx.Input.CruSession = nil
GlobalSessions.SessionDestroy(c.Ctx.ResponseWriter, c.Ctx.Request)
return nil
}
// IsAjax returns this request is ajax or not.

View File

@@ -298,15 +298,21 @@ func (manager *Manager) GC() {
}
// SessionRegenerateID Regenerate a session id for this SessionStore who's id is saving in http request.
func (manager *Manager) SessionRegenerateID(w http.ResponseWriter, r *http.Request) (session Store) {
func (manager *Manager) SessionRegenerateID(w http.ResponseWriter, r *http.Request) (Store, error) {
sid, err := manager.sessionID()
if err != nil {
return
return nil, err
}
var session Store
cookie, err := r.Cookie(manager.config.CookieName)
if err != nil || cookie.Value == "" {
//delete old cookie
session, _ = manager.provider.SessionRead(nil, sid)
session, err = manager.provider.SessionRead(nil, sid)
if err != nil {
return nil, err
}
cookie = &http.Cookie{Name: manager.config.CookieName,
Value: url.QueryEscape(sid),
Path: "/",
@@ -315,8 +321,16 @@ func (manager *Manager) SessionRegenerateID(w http.ResponseWriter, r *http.Reque
Domain: manager.config.Domain,
}
} else {
oldsid, _ := url.QueryUnescape(cookie.Value)
session, _ = manager.provider.SessionRegenerate(nil, oldsid, sid)
oldsid, err := url.QueryUnescape(cookie.Value)
if err != nil {
return nil, err
}
session, err = manager.provider.SessionRegenerate(nil, oldsid, sid)
if err != nil {
return nil, err
}
cookie.Value = url.QueryEscape(sid)
cookie.HttpOnly = true
cookie.Path = "/"
@@ -335,7 +349,7 @@ func (manager *Manager) SessionRegenerateID(w http.ResponseWriter, r *http.Reque
w.Header().Set(manager.config.SessionNameInHTTPHeader, sid)
}
return
return session, nil
}
// GetActiveSession Get all active sessions count number.

View File

@@ -21,76 +21,109 @@ import (
"github.com/astaxie/beego/server/web/context"
)
type testinfo struct {
url string
requesturl string
params map[string]string
type testInfo struct {
pattern string
requestUrl string
params map[string]string
shouldMatchOrNot bool
}
var routers []testinfo
var routers []testInfo
func matchTestInfo(pattern, url string, params map[string]string) testInfo {
return testInfo{
pattern: pattern,
requestUrl: url,
params: params,
shouldMatchOrNot: true,
}
}
func notMatchTestInfo(pattern, url string) testInfo {
return testInfo{
pattern: pattern,
requestUrl: url,
params: nil,
shouldMatchOrNot: false,
}
}
func init() {
routers = make([]testinfo, 0)
routers = append(routers, testinfo{"/topic/?:auth:int", "/topic", nil})
routers = append(routers, testinfo{"/topic/?:auth:int", "/topic/123", map[string]string{":auth": "123"}})
routers = append(routers, testinfo{"/topic/:id/?:auth", "/topic/1", map[string]string{":id": "1"}})
routers = append(routers, testinfo{"/topic/:id/?:auth", "/topic/1/2", map[string]string{":id": "1", ":auth": "2"}})
routers = append(routers, testinfo{"/topic/:id/?:auth:int", "/topic/1", map[string]string{":id": "1"}})
routers = append(routers, testinfo{"/topic/:id/?:auth:int", "/topic/1/123", map[string]string{":id": "1", ":auth": "123"}})
routers = append(routers, testinfo{"/:id", "/123", map[string]string{":id": "123"}})
routers = append(routers, testinfo{"/hello/?:id", "/hello", map[string]string{":id": ""}})
routers = append(routers, testinfo{"/", "/", nil})
routers = append(routers, testinfo{"/customer/login", "/customer/login", nil})
routers = append(routers, testinfo{"/customer/login", "/customer/login.json", map[string]string{":ext": "json"}})
routers = append(routers, testinfo{"/*", "/http://customer/123/", map[string]string{":splat": "http://customer/123/"}})
routers = append(routers, testinfo{"/*", "/customer/2009/12/11", map[string]string{":splat": "customer/2009/12/11"}})
routers = append(routers, testinfo{"/aa/*/bb", "/aa/2009/bb", map[string]string{":splat": "2009"}})
routers = append(routers, testinfo{"/cc/*/dd", "/cc/2009/11/dd", map[string]string{":splat": "2009/11"}})
routers = append(routers, testinfo{"/cc/:id/*", "/cc/2009/11/dd", map[string]string{":id": "2009", ":splat": "11/dd"}})
routers = append(routers, testinfo{"/ee/:year/*/ff", "/ee/2009/11/ff", map[string]string{":year": "2009", ":splat": "11"}})
routers = append(routers, testinfo{"/thumbnail/:size/uploads/*",
"/thumbnail/100x100/uploads/items/2014/04/20/dPRCdChkUd651t1Hvs18.jpg",
map[string]string{":size": "100x100", ":splat": "items/2014/04/20/dPRCdChkUd651t1Hvs18.jpg"}})
routers = append(routers, testinfo{"/*.*", "/nice/api.json", map[string]string{":path": "nice/api", ":ext": "json"}})
routers = append(routers, testinfo{"/:name/*.*", "/nice/api.json", map[string]string{":name": "nice", ":path": "api", ":ext": "json"}})
routers = append(routers, testinfo{"/:name/test/*.*", "/nice/test/api.json", map[string]string{":name": "nice", ":path": "api", ":ext": "json"}})
routers = append(routers, testinfo{"/dl/:width:int/:height:int/*.*",
"/dl/48/48/05ac66d9bda00a3acf948c43e306fc9a.jpg",
map[string]string{":width": "48", ":height": "48", ":ext": "jpg", ":path": "05ac66d9bda00a3acf948c43e306fc9a"}})
routers = append(routers, testinfo{"/v1/shop/:id:int", "/v1/shop/123", map[string]string{":id": "123"}})
routers = append(routers, testinfo{"/v1/shop/:id\\((a|b|c)\\)", "/v1/shop/123(a)", map[string]string{":id": "123"}})
routers = append(routers, testinfo{"/v1/shop/:id\\((a|b|c)\\)", "/v1/shop/123(b)", map[string]string{":id": "123"}})
routers = append(routers, testinfo{"/v1/shop/:id\\((a|b|c)\\)", "/v1/shop/123(c)", map[string]string{":id": "123"}})
routers = append(routers, testinfo{"/:year:int/:month:int/:id/:endid", "/1111/111/aaa/aaa", map[string]string{":year": "1111", ":month": "111", ":id": "aaa", ":endid": "aaa"}})
routers = append(routers, testinfo{"/v1/shop/:id/:name", "/v1/shop/123/nike", map[string]string{":id": "123", ":name": "nike"}})
routers = append(routers, testinfo{"/v1/shop/:id/account", "/v1/shop/123/account", map[string]string{":id": "123"}})
routers = append(routers, testinfo{"/v1/shop/:name:string", "/v1/shop/nike", map[string]string{":name": "nike"}})
routers = append(routers, testinfo{"/v1/shop/:id([0-9]+)", "/v1/shop//123", map[string]string{":id": "123"}})
routers = append(routers, testinfo{"/v1/shop/:id([0-9]+)_:name", "/v1/shop/123_nike", map[string]string{":id": "123", ":name": "nike"}})
routers = append(routers, testinfo{"/v1/shop/:id(.+)_cms.html", "/v1/shop/123_cms.html", map[string]string{":id": "123"}})
routers = append(routers, testinfo{"/v1/shop/cms_:id(.+)_:page(.+).html", "/v1/shop/cms_123_1.html", map[string]string{":id": "123", ":page": "1"}})
routers = append(routers, testinfo{"/v1/:v/cms/aaa_:id(.+)_:page(.+).html", "/v1/2/cms/aaa_123_1.html", map[string]string{":v": "2", ":id": "123", ":page": "1"}})
routers = append(routers, testinfo{"/v1/:v/cms_:id(.+)_:page(.+).html", "/v1/2/cms_123_1.html", map[string]string{":v": "2", ":id": "123", ":page": "1"}})
routers = append(routers, testinfo{"/v1/:v(.+)_cms/ttt_:id(.+)_:page(.+).html", "/v1/2_cms/ttt_123_1.html", map[string]string{":v": "2", ":id": "123", ":page": "1"}})
routers = append(routers, testinfo{"/api/projects/:pid/members/?:mid", "/api/projects/1/members", map[string]string{":pid": "1"}})
routers = append(routers, testinfo{"/api/projects/:pid/members/?:mid", "/api/projects/1/members/2", map[string]string{":pid": "1", ":mid": "2"}})
routers = make([]testInfo, 0)
//match example
routers = append(routers, matchTestInfo("/topic/?:auth:int", "/topic", nil))
routers = append(routers, matchTestInfo("/topic/?:auth:int", "/topic/123", map[string]string{":auth": "123"}))
routers = append(routers, matchTestInfo("/topic/:id/?:auth", "/topic/1", map[string]string{":id": "1"}))
routers = append(routers, matchTestInfo("/topic/:id/?:auth", "/topic/1/2", map[string]string{":id": "1", ":auth": "2"}))
routers = append(routers, matchTestInfo("/topic/:id/?:auth:int", "/topic/1", map[string]string{":id": "1"}))
routers = append(routers, matchTestInfo("/topic/:id/?:auth:int", "/topic/1/123", map[string]string{":id": "1", ":auth": "123"}))
routers = append(routers, matchTestInfo("/:id", "/123", map[string]string{":id": "123"}))
routers = append(routers, matchTestInfo("/hello/?:id", "/hello", map[string]string{":id": ""}))
routers = append(routers, matchTestInfo("/", "/", nil))
routers = append(routers, matchTestInfo("/customer/login", "/customer/login", nil))
routers = append(routers, matchTestInfo("/customer/login", "/customer/login.json", map[string]string{":ext": "json"}))
routers = append(routers, matchTestInfo("/*", "/http://customer/123/", map[string]string{":splat": "http://customer/123/"}))
routers = append(routers, matchTestInfo("/*", "/customer/2009/12/11", map[string]string{":splat": "customer/2009/12/11"}))
routers = append(routers, matchTestInfo("/aa/*/bb", "/aa/2009/bb", map[string]string{":splat": "2009"}))
routers = append(routers, matchTestInfo("/cc/*/dd", "/cc/2009/11/dd", map[string]string{":splat": "2009/11"}))
routers = append(routers, matchTestInfo("/cc/:id/*", "/cc/2009/11/dd", map[string]string{":id": "2009", ":splat": "11/dd"}))
routers = append(routers, matchTestInfo("/ee/:year/*/ff", "/ee/2009/11/ff", map[string]string{":year": "2009", ":splat": "11"}))
routers = append(routers, matchTestInfo("/thumbnail/:size/uploads/*", "/thumbnail/100x100/uploads/items/2014/04/20/dPRCdChkUd651t1Hvs18.jpg", map[string]string{":size": "100x100", ":splat": "items/2014/04/20/dPRCdChkUd651t1Hvs18.jpg"}))
routers = append(routers, matchTestInfo("/*.*", "/nice/api.json", map[string]string{":path": "nice/api", ":ext": "json"}))
routers = append(routers, matchTestInfo("/:name/*.*", "/nice/api.json", map[string]string{":name": "nice", ":path": "api", ":ext": "json"}))
routers = append(routers, matchTestInfo("/:name/test/*.*", "/nice/test/api.json", map[string]string{":name": "nice", ":path": "api", ":ext": "json"}))
routers = append(routers, matchTestInfo("/dl/:width:int/:height:int/*.*", "/dl/48/48/05ac66d9bda00a3acf948c43e306fc9a.jpg", map[string]string{":width": "48", ":height": "48", ":ext": "jpg", ":path": "05ac66d9bda00a3acf948c43e306fc9a"}))
routers = append(routers, matchTestInfo("/v1/shop/:id:int", "/v1/shop/123", map[string]string{":id": "123"}))
routers = append(routers, matchTestInfo("/v1/shop/:id\\((a|b|c)\\)", "/v1/shop/123(a)", map[string]string{":id": "123"}))
routers = append(routers, matchTestInfo("/v1/shop/:id\\((a|b|c)\\)", "/v1/shop/123(b)", map[string]string{":id": "123"}))
routers = append(routers, matchTestInfo("/v1/shop/:id\\((a|b|c)\\)", "/v1/shop/123(c)", map[string]string{":id": "123"}))
routers = append(routers, matchTestInfo("/:year:int/:month:int/:id/:endid", "/1111/111/aaa/aaa", map[string]string{":year": "1111", ":month": "111", ":id": "aaa", ":endid": "aaa"}))
routers = append(routers, matchTestInfo("/v1/shop/:id/:name", "/v1/shop/123/nike", map[string]string{":id": "123", ":name": "nike"}))
routers = append(routers, matchTestInfo("/v1/shop/:id/account", "/v1/shop/123/account", map[string]string{":id": "123"}))
routers = append(routers, matchTestInfo("/v1/shop/:name:string", "/v1/shop/nike", map[string]string{":name": "nike"}))
routers = append(routers, matchTestInfo("/v1/shop/:id([0-9]+)", "/v1/shop//123", map[string]string{":id": "123"}))
routers = append(routers, matchTestInfo("/v1/shop/:id([0-9]+)_:name", "/v1/shop/123_nike", map[string]string{":id": "123", ":name": "nike"}))
routers = append(routers, matchTestInfo("/v1/shop/:id(.+)_cms.html", "/v1/shop/123_cms.html", map[string]string{":id": "123"}))
routers = append(routers, matchTestInfo("/v1/shop/cms_:id(.+)_:page(.+).html", "/v1/shop/cms_123_1.html", map[string]string{":id": "123", ":page": "1"}))
routers = append(routers, matchTestInfo("/v1/:v/cms/aaa_:id(.+)_:page(.+).html", "/v1/2/cms/aaa_123_1.html", map[string]string{":v": "2", ":id": "123", ":page": "1"}))
routers = append(routers, matchTestInfo("/v1/:v/cms_:id(.+)_:page(.+).html", "/v1/2/cms_123_1.html", map[string]string{":v": "2", ":id": "123", ":page": "1"}))
routers = append(routers, matchTestInfo("/v1/:v(.+)_cms/ttt_:id(.+)_:page(.+).html", "/v1/2_cms/ttt_123_1.html", map[string]string{":v": "2", ":id": "123", ":page": "1"}))
routers = append(routers, matchTestInfo("/api/projects/:pid/members/?:mid", "/api/projects/1/members", map[string]string{":pid": "1"}))
routers = append(routers, matchTestInfo("/api/projects/:pid/members/?:mid", "/api/projects/1/members/2", map[string]string{":pid": "1", ":mid": "2"}))
//not match example
// https://github.com/astaxie/beego/issues/3865
routers = append(routers, notMatchTestInfo("/read_:id:int\\.htm", "/read_222htm"))
routers = append(routers, notMatchTestInfo("/read_:id:int\\.htm", "/read_222_htm"))
routers = append(routers, notMatchTestInfo("/read_:id:int\\.htm", " /read_262shtm"))
}
func TestTreeRouters(t *testing.T) {
for _, r := range routers {
shouldMatch := r.shouldMatchOrNot
tr := NewTree()
tr.AddRouter(r.url, "astaxie")
tr.AddRouter(r.pattern, "astaxie")
ctx := context.NewContext()
obj := tr.Match(r.requesturl, ctx)
obj := tr.Match(r.requestUrl, ctx)
if !shouldMatch {
if obj != nil {
t.Fatal("pattern:", r.pattern, ", should not match", r.requestUrl)
} else {
return
}
}
if obj == nil || obj.(string) != "astaxie" {
t.Fatal(r.url+" can't get obj, Expect ", r.requesturl)
t.Fatal("pattern:", r.pattern+", can't match obj, Expect ", r.requestUrl)
}
if r.params != nil {
for k, v := range r.params {
if vv := ctx.Input.Param(k); vv != v {
t.Fatal("The Rule: " + r.url + "\nThe RequestURL:" + r.requesturl + "\nThe Key is " + k + ", The Value should be: " + v + ", but get: " + vv)
t.Fatal("The Rule: " + r.pattern + "\nThe RequestURL:" + r.requestUrl + "\nThe Key is " + k + ", The Value should be: " + v + ", but get: " + vv)
} else if vv == "" && v != "" {
t.Fatal(r.url + " " + r.requesturl + " get param empty:" + k)
t.Fatal(r.pattern + " " + r.requestUrl + " get param empty:" + k)
}
}
}
@@ -247,7 +280,6 @@ func TestAddTree5(t *testing.T) {
t.Fatal("url /v1/shop/ need match router /v1/shop/ ")
}
}
func TestSplitPath(t *testing.T) {
a := splitPath("")
if len(a) != 0 {
@@ -292,6 +324,7 @@ func TestSplitSegment(t *testing.T) {
":id([0-9]+)": {true, []string{":id"}, `([0-9]+)`},
":id([0-9]+)_:name": {true, []string{":id", ":name"}, `([0-9]+)_(.+)`},
":id(.+)_cms.html": {true, []string{":id"}, `(.+)_cms.html`},
":id(.+)_cms\\.html": {true, []string{":id"}, `(.+)_cms\.html`},
"cms_:id(.+)_:page(.+).html": {true, []string{":id", ":page"}, `cms_(.+)_(.+).html`},
`:app(a|b|c)`: {true, []string{":app"}, `(a|b|c)`},
`:app\((a|b|c)\)`: {true, []string{":app"}, `(.+)\((a|b|c)\)`},
@@ -303,4 +336,4 @@ func TestSplitSegment(t *testing.T) {
t.Fatalf("%s should return %t,%s,%q, got %t,%s,%q", pattern, v.isReg, v.params, v.regStr, b, w, r)
}
}
}
}