mirror of
https://github.com/astaxie/beego.git
synced 2025-07-11 11:31:02 +00:00
Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
8ef8fd2606 | |||
0cd80525e7 |
@ -8,15 +8,6 @@ It is inspired by Tornado, Sinatra and Flask. beego has some Go-specific feature
|
|||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
#### Create `hello` directory, cd `hello` directory
|
|
||||||
|
|
||||||
mkdir hello
|
|
||||||
cd hello
|
|
||||||
|
|
||||||
#### Init module
|
|
||||||
|
|
||||||
go mod init
|
|
||||||
|
|
||||||
#### Download and install
|
#### Download and install
|
||||||
|
|
||||||
go get github.com/astaxie/beego
|
go get github.com/astaxie/beego
|
||||||
|
62
admin.go
62
admin.go
@ -21,7 +21,6 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
|
||||||
"text/template"
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -72,7 +71,7 @@ func init() {
|
|||||||
// AdminIndex is the default http.Handler for admin module.
|
// AdminIndex is the default http.Handler for admin module.
|
||||||
// it matches url pattern "/".
|
// it matches url pattern "/".
|
||||||
func adminIndex(rw http.ResponseWriter, _ *http.Request) {
|
func adminIndex(rw http.ResponseWriter, _ *http.Request) {
|
||||||
writeTemplate(rw, map[interface{}]interface{}{}, indexTpl, defaultScriptsTpl)
|
execTpl(rw, map[interface{}]interface{}{}, indexTpl, defaultScriptsTpl)
|
||||||
}
|
}
|
||||||
|
|
||||||
// QpsIndex is the http.Handler for writing qps statistics map result info in http.ResponseWriter.
|
// QpsIndex is the http.Handler for writing qps statistics map result info in http.ResponseWriter.
|
||||||
@ -92,7 +91,7 @@ func qpsIndex(rw http.ResponseWriter, _ *http.Request) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
writeTemplate(rw, data, qpsTpl, defaultScriptsTpl)
|
execTpl(rw, data, qpsTpl, defaultScriptsTpl)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListConf is the http.Handler of displaying all beego configuration values as key/value pair.
|
// ListConf is the http.Handler of displaying all beego configuration values as key/value pair.
|
||||||
@ -129,7 +128,7 @@ func listConf(rw http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
data["Content"] = content
|
data["Content"] = content
|
||||||
data["Title"] = "Routers"
|
data["Title"] = "Routers"
|
||||||
writeTemplate(rw, data, routerAndFilterTpl, defaultScriptsTpl)
|
execTpl(rw, data, routerAndFilterTpl, defaultScriptsTpl)
|
||||||
case "filter":
|
case "filter":
|
||||||
var (
|
var (
|
||||||
content = M{
|
content = M{
|
||||||
@ -172,7 +171,7 @@ func listConf(rw http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
data["Content"] = content
|
data["Content"] = content
|
||||||
data["Title"] = "Filters"
|
data["Title"] = "Filters"
|
||||||
writeTemplate(rw, data, routerAndFilterTpl, defaultScriptsTpl)
|
execTpl(rw, data, routerAndFilterTpl, defaultScriptsTpl)
|
||||||
default:
|
default:
|
||||||
rw.Write([]byte("command not support"))
|
rw.Write([]byte("command not support"))
|
||||||
}
|
}
|
||||||
@ -280,7 +279,9 @@ func profIndex(rw http.ResponseWriter, r *http.Request) {
|
|||||||
http.Error(rw, err.Error(), http.StatusInternalServerError)
|
http.Error(rw, err.Error(), http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
writeJSON(rw, dataJSON)
|
|
||||||
|
rw.Header().Set("Content-Type", "application/json")
|
||||||
|
rw.Write(dataJSON)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,12 +290,12 @@ func profIndex(rw http.ResponseWriter, r *http.Request) {
|
|||||||
if command == "gc summary" {
|
if command == "gc summary" {
|
||||||
defaultTpl = gcAjaxTpl
|
defaultTpl = gcAjaxTpl
|
||||||
}
|
}
|
||||||
writeTemplate(rw, data, profillingTpl, defaultTpl)
|
execTpl(rw, data, profillingTpl, defaultTpl)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Healthcheck is a http.Handler calling health checking and showing the result.
|
// Healthcheck is a http.Handler calling health checking and showing the result.
|
||||||
// it's in "/healthcheck" pattern in admin module.
|
// it's in "/healthcheck" pattern in admin module.
|
||||||
func healthcheck(rw http.ResponseWriter, r *http.Request) {
|
func healthcheck(rw http.ResponseWriter, _ *http.Request) {
|
||||||
var (
|
var (
|
||||||
result []string
|
result []string
|
||||||
data = make(map[interface{}]interface{})
|
data = make(map[interface{}]interface{})
|
||||||
@ -321,49 +322,10 @@ func healthcheck(rw http.ResponseWriter, r *http.Request) {
|
|||||||
*resultList = append(*resultList, result)
|
*resultList = append(*resultList, result)
|
||||||
}
|
}
|
||||||
|
|
||||||
queryParams := r.URL.Query()
|
|
||||||
jsonFlag := queryParams.Get("json")
|
|
||||||
shouldReturnJSON, _ := strconv.ParseBool(jsonFlag)
|
|
||||||
|
|
||||||
if shouldReturnJSON {
|
|
||||||
response := buildHealthCheckResponseList(resultList)
|
|
||||||
jsonResponse, err := json.Marshal(response)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
http.Error(rw, err.Error(), http.StatusInternalServerError)
|
|
||||||
} else {
|
|
||||||
writeJSON(rw, jsonResponse)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
content["Data"] = resultList
|
content["Data"] = resultList
|
||||||
data["Content"] = content
|
data["Content"] = content
|
||||||
data["Title"] = "Health Check"
|
data["Title"] = "Health Check"
|
||||||
|
execTpl(rw, data, healthCheckTpl, defaultScriptsTpl)
|
||||||
writeTemplate(rw, data, healthCheckTpl, defaultScriptsTpl)
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildHealthCheckResponseList(healthCheckResults *[][]string) []map[string]interface{} {
|
|
||||||
response := make([]map[string]interface{}, len(*healthCheckResults))
|
|
||||||
|
|
||||||
for i, healthCheckResult := range *healthCheckResults {
|
|
||||||
currentResultMap := make(map[string]interface{})
|
|
||||||
|
|
||||||
currentResultMap["name"] = healthCheckResult[0]
|
|
||||||
currentResultMap["message"] = healthCheckResult[1]
|
|
||||||
currentResultMap["status"] = healthCheckResult[2]
|
|
||||||
|
|
||||||
response[i] = currentResultMap
|
|
||||||
}
|
|
||||||
|
|
||||||
return response
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeJSON(rw http.ResponseWriter, jsonData []byte) {
|
|
||||||
rw.Header().Set("Content-Type", "application/json")
|
|
||||||
rw.Write(jsonData)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TaskStatus is a http.Handler with running task status (task name, status and the last execution).
|
// TaskStatus is a http.Handler with running task status (task name, status and the last execution).
|
||||||
@ -409,10 +371,10 @@ func taskStatus(rw http.ResponseWriter, req *http.Request) {
|
|||||||
content["Data"] = resultList
|
content["Data"] = resultList
|
||||||
data["Content"] = content
|
data["Content"] = content
|
||||||
data["Title"] = "Tasks"
|
data["Title"] = "Tasks"
|
||||||
writeTemplate(rw, data, tasksTpl, defaultScriptsTpl)
|
execTpl(rw, data, tasksTpl, defaultScriptsTpl)
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeTemplate(rw http.ResponseWriter, data map[interface{}]interface{}, tpls ...string) {
|
func execTpl(rw http.ResponseWriter, data map[interface{}]interface{}, tpls ...string) {
|
||||||
tmpl := template.Must(template.New("dashboard").Parse(dashboardTpl))
|
tmpl := template.Must(template.New("dashboard").Parse(dashboardTpl))
|
||||||
for _, tpl := range tpls {
|
for _, tpl := range tpls {
|
||||||
tmpl = template.Must(tmpl.Parse(tpl))
|
tmpl = template.Must(tmpl.Parse(tpl))
|
||||||
|
162
admin_test.go
162
admin_test.go
@ -1,32 +1,10 @@
|
|||||||
package beego
|
package beego
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/astaxie/beego/toolbox"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type SampleDatabaseCheck struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
type SampleCacheCheck struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (dc *SampleDatabaseCheck) Check() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cc *SampleCacheCheck) Check() error {
|
|
||||||
return errors.New("no cache detected")
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestList_01(t *testing.T) {
|
func TestList_01(t *testing.T) {
|
||||||
m := make(M)
|
m := make(M)
|
||||||
list("BConfig", BConfig, m)
|
list("BConfig", BConfig, m)
|
||||||
@ -97,143 +75,3 @@ func oldMap() M {
|
|||||||
m["BConfig.Log.Outputs"] = BConfig.Log.Outputs
|
m["BConfig.Log.Outputs"] = BConfig.Log.Outputs
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWriteJSON(t *testing.T) {
|
|
||||||
t.Log("Testing the adding of JSON to the response")
|
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
originalBody := []int{1, 2, 3}
|
|
||||||
|
|
||||||
res, _ := json.Marshal(originalBody)
|
|
||||||
|
|
||||||
writeJSON(w, res)
|
|
||||||
|
|
||||||
decodedBody := []int{}
|
|
||||||
err := json.NewDecoder(w.Body).Decode(&decodedBody)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("Could not decode response body into slice.")
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := range decodedBody {
|
|
||||||
if decodedBody[i] != originalBody[i] {
|
|
||||||
t.Fatalf("Expected %d but got %d in decoded body slice", originalBody[i], decodedBody[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHealthCheckHandlerDefault(t *testing.T) {
|
|
||||||
endpointPath := "/healthcheck"
|
|
||||||
|
|
||||||
toolbox.AddHealthCheck("database", &SampleDatabaseCheck{})
|
|
||||||
toolbox.AddHealthCheck("cache", &SampleCacheCheck{})
|
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", endpointPath, nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
|
|
||||||
handler := http.HandlerFunc(healthcheck)
|
|
||||||
|
|
||||||
handler.ServeHTTP(w, req)
|
|
||||||
|
|
||||||
if status := w.Code; status != http.StatusOK {
|
|
||||||
t.Errorf("handler returned wrong status code: got %v want %v",
|
|
||||||
status, http.StatusOK)
|
|
||||||
}
|
|
||||||
if !strings.Contains(w.Body.String(), "database") {
|
|
||||||
t.Errorf("Expected 'database' in generated template.")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBuildHealthCheckResponseList(t *testing.T) {
|
|
||||||
healthCheckResults := [][]string{
|
|
||||||
[]string{
|
|
||||||
"error",
|
|
||||||
"Database",
|
|
||||||
"Error occurred while starting the db",
|
|
||||||
},
|
|
||||||
[]string{
|
|
||||||
"success",
|
|
||||||
"Cache",
|
|
||||||
"Cache started successfully",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
responseList := buildHealthCheckResponseList(&healthCheckResults)
|
|
||||||
|
|
||||||
if len(responseList) != len(healthCheckResults) {
|
|
||||||
t.Errorf("invalid response map length: got %d want %d",
|
|
||||||
len(responseList), len(healthCheckResults))
|
|
||||||
}
|
|
||||||
|
|
||||||
responseFields := []string{"name", "message", "status"}
|
|
||||||
|
|
||||||
for _, response := range responseList {
|
|
||||||
for _, field := range responseFields {
|
|
||||||
_, ok := response[field]
|
|
||||||
if !ok {
|
|
||||||
t.Errorf("expected %s to be in the response %v", field, response)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestHealthCheckHandlerReturnsJSON(t *testing.T) {
|
|
||||||
|
|
||||||
toolbox.AddHealthCheck("database", &SampleDatabaseCheck{})
|
|
||||||
toolbox.AddHealthCheck("cache", &SampleCacheCheck{})
|
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", "/healthcheck?json=true", nil)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
|
|
||||||
handler := http.HandlerFunc(healthcheck)
|
|
||||||
|
|
||||||
handler.ServeHTTP(w, req)
|
|
||||||
if status := w.Code; status != http.StatusOK {
|
|
||||||
t.Errorf("handler returned wrong status code: got %v want %v",
|
|
||||||
status, http.StatusOK)
|
|
||||||
}
|
|
||||||
|
|
||||||
decodedResponseBody := []map[string]interface{}{}
|
|
||||||
expectedResponseBody := []map[string]interface{}{}
|
|
||||||
|
|
||||||
expectedJSONString := []byte(`
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"message":"database",
|
|
||||||
"name":"success",
|
|
||||||
"status":"OK"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"message":"cache",
|
|
||||||
"name":"error",
|
|
||||||
"status":"no cache detected"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
`)
|
|
||||||
|
|
||||||
json.Unmarshal(expectedJSONString, &expectedResponseBody)
|
|
||||||
|
|
||||||
json.Unmarshal(w.Body.Bytes(), &decodedResponseBody)
|
|
||||||
|
|
||||||
if len(expectedResponseBody) != len(decodedResponseBody) {
|
|
||||||
t.Errorf("invalid response map length: got %d want %d",
|
|
||||||
len(decodedResponseBody), len(expectedResponseBody))
|
|
||||||
}
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(decodedResponseBody, expectedResponseBody) {
|
|
||||||
t.Errorf("handler returned unexpected body: got %v want %v",
|
|
||||||
decodedResponseBody, expectedResponseBody)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
2
app.go
2
app.go
@ -197,7 +197,7 @@ func (app *App) Run(mws ...MiddleWare) {
|
|||||||
pool.AppendCertsFromPEM(data)
|
pool.AppendCertsFromPEM(data)
|
||||||
app.Server.TLSConfig = &tls.Config{
|
app.Server.TLSConfig = &tls.Config{
|
||||||
ClientCAs: pool,
|
ClientCAs: pool,
|
||||||
ClientAuth: BConfig.Listen.ClientAuth,
|
ClientAuth: tls.RequireAndVerifyClientCert,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := app.Server.ListenAndServeTLS(BConfig.Listen.HTTPSCertFile, BConfig.Listen.HTTPSKeyFile); err != nil {
|
if err := app.Server.ListenAndServeTLS(BConfig.Listen.HTTPSCertFile, BConfig.Listen.HTTPSKeyFile); err != nil {
|
||||||
|
2
beego.go
2
beego.go
@ -23,7 +23,7 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
// VERSION represent beego web framework version.
|
// VERSION represent beego web framework version.
|
||||||
VERSION = "1.12.3"
|
VERSION = "1.12.2"
|
||||||
|
|
||||||
// DEV is for develop
|
// DEV is for develop
|
||||||
DEV = "dev"
|
DEV = "dev"
|
||||||
|
@ -15,11 +15,11 @@
|
|||||||
package beego
|
package beego
|
||||||
|
|
||||||
var (
|
var (
|
||||||
BuildVersion string
|
BuildVersion string
|
||||||
BuildGitRevision string
|
BuildGitRevision string
|
||||||
BuildStatus string
|
BuildStatus string
|
||||||
BuildTag string
|
BuildTag string
|
||||||
BuildTime string
|
BuildTime string
|
||||||
|
|
||||||
GoVersion string
|
GoVersion string
|
||||||
|
|
||||||
|
5
cache/redis/redis.go
vendored
5
cache/redis/redis.go
vendored
@ -38,9 +38,8 @@ import (
|
|||||||
|
|
||||||
"github.com/gomodule/redigo/redis"
|
"github.com/gomodule/redigo/redis"
|
||||||
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/astaxie/beego/cache"
|
"github.com/astaxie/beego/cache"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -58,7 +57,7 @@ type Cache struct {
|
|||||||
maxIdle int
|
maxIdle int
|
||||||
|
|
||||||
//the timeout to a value less than the redis server's timeout.
|
//the timeout to a value less than the redis server's timeout.
|
||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRedisCache create new redis cache with default collection name.
|
// NewRedisCache create new redis cache with default collection name.
|
||||||
|
@ -15,9 +15,7 @@
|
|||||||
package beego
|
package beego
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
@ -67,7 +65,6 @@ type Listen struct {
|
|||||||
HTTPSCertFile string
|
HTTPSCertFile string
|
||||||
HTTPSKeyFile string
|
HTTPSKeyFile string
|
||||||
TrustCaFile string
|
TrustCaFile string
|
||||||
ClientAuth tls.ClientAuthType
|
|
||||||
EnableAdmin bool
|
EnableAdmin bool
|
||||||
AdminAddr string
|
AdminAddr string
|
||||||
AdminPort int
|
AdminPort int
|
||||||
@ -109,7 +106,6 @@ type SessionConfig struct {
|
|||||||
SessionEnableSidInHTTPHeader bool // enable store/get the sessionId into/from http headers
|
SessionEnableSidInHTTPHeader bool // enable store/get the sessionId into/from http headers
|
||||||
SessionNameInHTTPHeader string
|
SessionNameInHTTPHeader string
|
||||||
SessionEnableSidInURLQuery bool // enable get the sessionId from Url Query params
|
SessionEnableSidInURLQuery bool // enable get the sessionId from Url Query params
|
||||||
SessionCookieSameSite http.SameSite
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// LogConfig holds Log related config
|
// LogConfig holds Log related config
|
||||||
@ -154,9 +150,6 @@ func init() {
|
|||||||
filename = os.Getenv("BEEGO_RUNMODE") + ".app.conf"
|
filename = os.Getenv("BEEGO_RUNMODE") + ".app.conf"
|
||||||
}
|
}
|
||||||
appConfigPath = filepath.Join(WorkPath, "conf", filename)
|
appConfigPath = filepath.Join(WorkPath, "conf", filename)
|
||||||
if configPath := os.Getenv("BEEGO_CONFIG_PATH"); configPath != "" {
|
|
||||||
appConfigPath = configPath
|
|
||||||
}
|
|
||||||
if !utils.FileExists(appConfigPath) {
|
if !utils.FileExists(appConfigPath) {
|
||||||
appConfigPath = filepath.Join(AppPath, "conf", filename)
|
appConfigPath = filepath.Join(AppPath, "conf", filename)
|
||||||
if !utils.FileExists(appConfigPath) {
|
if !utils.FileExists(appConfigPath) {
|
||||||
@ -238,7 +231,6 @@ func newBConfig() *Config {
|
|||||||
AdminPort: 8088,
|
AdminPort: 8088,
|
||||||
EnableFcgi: false,
|
EnableFcgi: false,
|
||||||
EnableStdIo: false,
|
EnableStdIo: false,
|
||||||
ClientAuth: tls.RequireAndVerifyClientCert,
|
|
||||||
},
|
},
|
||||||
WebConfig: WebConfig{
|
WebConfig: WebConfig{
|
||||||
AutoRender: true,
|
AutoRender: true,
|
||||||
@ -269,7 +261,6 @@ func newBConfig() *Config {
|
|||||||
SessionEnableSidInHTTPHeader: false, // enable store/get the sessionId into/from http headers
|
SessionEnableSidInHTTPHeader: false, // enable store/get the sessionId into/from http headers
|
||||||
SessionNameInHTTPHeader: "Beegosessionid",
|
SessionNameInHTTPHeader: "Beegosessionid",
|
||||||
SessionEnableSidInURLQuery: false, // enable get the sessionId from Url Query params
|
SessionEnableSidInURLQuery: false, // enable get the sessionId from Url Query params
|
||||||
SessionCookieSameSite: http.SameSiteDefaultMode,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Log: LogConfig{
|
Log: LogConfig{
|
||||||
|
@ -145,7 +145,7 @@ httpport = 8080
|
|||||||
# enable db
|
# enable db
|
||||||
[dbinfo]
|
[dbinfo]
|
||||||
# db type name
|
# db type name
|
||||||
# support mysql,sqlserver
|
# suport mysql,sqlserver
|
||||||
name = mysql
|
name = mysql
|
||||||
`
|
`
|
||||||
|
|
||||||
@ -161,7 +161,7 @@ httpport=8080
|
|||||||
# enable db
|
# enable db
|
||||||
[dbinfo]
|
[dbinfo]
|
||||||
# db type name
|
# db type name
|
||||||
# support mysql,sqlserver
|
# suport mysql,sqlserver
|
||||||
name=mysql
|
name=mysql
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
|
@ -296,7 +296,7 @@ func (c *ConfigContainer) getData(key string) (interface{}, error) {
|
|||||||
case map[string]interface{}:
|
case map[string]interface{}:
|
||||||
{
|
{
|
||||||
tmpData = v.(map[string]interface{})
|
tmpData = v.(map[string]interface{})
|
||||||
if idx == len(keys)-1 {
|
if idx == len(keys) - 1 {
|
||||||
return tmpData, nil
|
return tmpData, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -150,7 +150,7 @@ func (ctx *Context) XSRFToken(key string, expire int64) string {
|
|||||||
token, ok := ctx.GetSecureCookie(key, "_xsrf")
|
token, ok := ctx.GetSecureCookie(key, "_xsrf")
|
||||||
if !ok {
|
if !ok {
|
||||||
token = string(utils.RandomCreateBytes(32))
|
token = string(utils.RandomCreateBytes(32))
|
||||||
ctx.SetSecureCookie(key, "_xsrf", token, expire, "", "", true, true)
|
ctx.SetSecureCookie(key, "_xsrf", token, expire)
|
||||||
}
|
}
|
||||||
ctx._xsrfToken = token
|
ctx._xsrfToken = token
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,7 @@ package context
|
|||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestXsrfReset_01(t *testing.T) {
|
func TestXsrfReset_01(t *testing.T) {
|
||||||
@ -47,8 +44,4 @@ func TestXsrfReset_01(t *testing.T) {
|
|||||||
if token == c._xsrfToken {
|
if token == c._xsrfToken {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
ck := c.ResponseWriter.Header().Get("Set-Cookie")
|
|
||||||
assert.True(t, strings.Contains(ck, "Secure"))
|
|
||||||
assert.True(t, strings.Contains(ck, "HttpOnly"))
|
|
||||||
}
|
}
|
||||||
|
@ -333,14 +333,8 @@ func (input *BeegoInput) Query(key string) string {
|
|||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
if input.Context.Request.Form == nil {
|
if input.Context.Request.Form == nil {
|
||||||
input.dataLock.Lock()
|
input.Context.Request.ParseForm()
|
||||||
if input.Context.Request.Form == nil {
|
|
||||||
input.Context.Request.ParseForm()
|
|
||||||
}
|
|
||||||
input.dataLock.Unlock()
|
|
||||||
}
|
}
|
||||||
input.dataLock.RLock()
|
|
||||||
defer input.dataLock.RUnlock()
|
|
||||||
return input.Context.Request.Form.Get(key)
|
return input.Context.Request.Form.Get(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,13 +205,3 @@ func TestParams(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
func BenchmarkQuery(b *testing.B) {
|
|
||||||
beegoInput := NewInput()
|
|
||||||
beegoInput.Context = NewContext()
|
|
||||||
beegoInput.Context.Request, _ = http.NewRequest("POST", "http://www.example.com/?q=foo", nil)
|
|
||||||
b.RunParallel(func(pb *testing.PB) {
|
|
||||||
for pb.Next() {
|
|
||||||
beegoInput.Query("q")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
package param
|
package param
|
||||||
|
|
||||||
import (
|
import "testing"
|
||||||
"reflect"
|
import "reflect"
|
||||||
"testing"
|
import "time"
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type testDefinition struct {
|
type testDefinition struct {
|
||||||
strValue string
|
strValue string
|
||||||
|
@ -19,10 +19,9 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/astaxie/beego/context"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/astaxie/beego/context"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetInt(t *testing.T) {
|
func TestGetInt(t *testing.T) {
|
||||||
@ -126,8 +125,8 @@ func TestGetUint64(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAdditionalViewPaths(t *testing.T) {
|
func TestAdditionalViewPaths(t *testing.T) {
|
||||||
dir1 := tmpDir("TestAdditionalViewPaths1")
|
dir1 := "_beeTmp"
|
||||||
dir2 := tmpDir("TestAdditionalViewPaths2")
|
dir2 := "_beeTmp2"
|
||||||
defer os.RemoveAll(dir1)
|
defer os.RemoveAll(dir1)
|
||||||
defer os.RemoveAll(dir2)
|
defer os.RemoveAll(dir2)
|
||||||
|
|
||||||
|
16
error.go
16
error.go
@ -28,7 +28,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
errorTypeHandler = iota
|
errorTypeHandler = iota
|
||||||
errorTypeController
|
errorTypeController
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -359,20 +359,6 @@ func gatewayTimeout(rw http.ResponseWriter, r *http.Request) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// show 413 Payload Too Large
|
|
||||||
func payloadTooLarge(rw http.ResponseWriter, r *http.Request) {
|
|
||||||
responseError(rw, r,
|
|
||||||
413,
|
|
||||||
`<br>The page you have requested is unavailable.
|
|
||||||
<br>Perhaps you are here because:<br><br>
|
|
||||||
<ul>
|
|
||||||
<br>The request entity is larger than limits defined by server.
|
|
||||||
<br>Please change the request entity and try again.
|
|
||||||
</ul>
|
|
||||||
`,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func responseError(rw http.ResponseWriter, r *http.Request, errCode int, errContent string) {
|
func responseError(rw http.ResponseWriter, r *http.Request, errCode int, errContent string) {
|
||||||
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
t, _ := template.New("beegoerrortemp").Parse(errtpl)
|
||||||
data := M{
|
data := M{
|
||||||
|
3
go.mod
3
go.mod
@ -22,7 +22,6 @@ require (
|
|||||||
github.com/lib/pq v1.0.0
|
github.com/lib/pq v1.0.0
|
||||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible
|
github.com/mattn/go-sqlite3 v2.0.3+incompatible
|
||||||
github.com/pelletier/go-toml v1.2.0 // indirect
|
github.com/pelletier/go-toml v1.2.0 // indirect
|
||||||
github.com/pkg/errors v0.9.1
|
|
||||||
github.com/prometheus/client_golang v1.7.0
|
github.com/prometheus/client_golang v1.7.0
|
||||||
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644
|
github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644
|
||||||
github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec
|
github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec
|
||||||
@ -30,7 +29,7 @@ require (
|
|||||||
github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c // indirect
|
github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c // indirect
|
||||||
github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b // indirect
|
github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b // indirect
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 // indirect
|
golang.org/x/tools v0.0.0-20200117065230-39095c1d176c
|
||||||
gopkg.in/yaml.v2 v2.2.8
|
gopkg.in/yaml.v2 v2.2.8
|
||||||
)
|
)
|
||||||
|
|
||||||
|
11
go.sum
11
go.sum
@ -53,6 +53,7 @@ github.com/go-redis/redis v6.14.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8w
|
|||||||
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
||||||
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
|
github.com/go-yaml/yaml v0.0.0-20180328195020-5420a8b6744d h1:xy93KVe+KrIIwWDEAfQBdIfsiHJkepbYsDr+VY3g9/o=
|
||||||
github.com/go-yaml/yaml v0.0.0-20180328195020-5420a8b6744d/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
github.com/go-yaml/yaml v0.0.0-20180328195020-5420a8b6744d/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo=
|
github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
@ -113,10 +114,11 @@ github.com/pelletier/go-toml v1.0.1/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9
|
|||||||
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
|
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
|
||||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
github.com/peterh/liner v1.0.1-0.20171122030339-3681c2a91233/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
|
github.com/peterh/liner v1.0.1-0.20171122030339-3681c2a91233/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
|
||||||
|
github.com/pingcap/tidb v2.0.11+incompatible/go.mod h1:I8C6jrPINP2rrVunTRd7C9fRRhQrtR43S1/CL5ix/yQ=
|
||||||
|
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
@ -162,7 +164,9 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf
|
|||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a h1:gOpx8G595UYyvj8UK4+OFyY4rx037g3fmfhe5SasG3U=
|
||||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
@ -171,6 +175,7 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@ -184,6 +189,8 @@ golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM
|
|||||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/tools v0.0.0-20200117065230-39095c1d176c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
|
2
hooks.go
2
hooks.go
@ -34,7 +34,6 @@ func registerDefaultErrorHandler() error {
|
|||||||
"504": gatewayTimeout,
|
"504": gatewayTimeout,
|
||||||
"417": invalidxsrf,
|
"417": invalidxsrf,
|
||||||
"422": missingxsrf,
|
"422": missingxsrf,
|
||||||
"413": payloadTooLarge,
|
|
||||||
}
|
}
|
||||||
for e, h := range m {
|
for e, h := range m {
|
||||||
if _, ok := ErrorMaps[e]; !ok {
|
if _, ok := ErrorMaps[e]; !ok {
|
||||||
@ -61,7 +60,6 @@ func registerSession() error {
|
|||||||
conf.EnableSidInHTTPHeader = BConfig.WebConfig.Session.SessionEnableSidInHTTPHeader
|
conf.EnableSidInHTTPHeader = BConfig.WebConfig.Session.SessionEnableSidInHTTPHeader
|
||||||
conf.SessionNameInHTTPHeader = BConfig.WebConfig.Session.SessionNameInHTTPHeader
|
conf.SessionNameInHTTPHeader = BConfig.WebConfig.Session.SessionNameInHTTPHeader
|
||||||
conf.EnableSidInURLQuery = BConfig.WebConfig.Session.SessionEnableSidInURLQuery
|
conf.EnableSidInURLQuery = BConfig.WebConfig.Session.SessionEnableSidInURLQuery
|
||||||
conf.CookieSameSite = BConfig.WebConfig.Session.SessionCookieSameSite
|
|
||||||
} else {
|
} else {
|
||||||
if err = json.Unmarshal([]byte(sessionConfig), conf); err != nil {
|
if err = json.Unmarshal([]byte(sessionConfig), conf); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -144,7 +144,6 @@ type BeegoHTTPSettings struct {
|
|||||||
Gzip bool
|
Gzip bool
|
||||||
DumpBody bool
|
DumpBody bool
|
||||||
Retries int // if set to -1 means will retry forever
|
Retries int // if set to -1 means will retry forever
|
||||||
RetryDelay time.Duration
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BeegoHTTPRequest provides more useful methods for requesting one url than http.Request.
|
// BeegoHTTPRequest provides more useful methods for requesting one url than http.Request.
|
||||||
@ -203,11 +202,6 @@ func (b *BeegoHTTPRequest) Retries(times int) *BeegoHTTPRequest {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BeegoHTTPRequest) RetryDelay(delay time.Duration) *BeegoHTTPRequest {
|
|
||||||
b.setting.RetryDelay = delay
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// DumpBody setting whether need to Dump the Body.
|
// DumpBody setting whether need to Dump the Body.
|
||||||
func (b *BeegoHTTPRequest) DumpBody(isdump bool) *BeegoHTTPRequest {
|
func (b *BeegoHTTPRequest) DumpBody(isdump bool) *BeegoHTTPRequest {
|
||||||
b.setting.DumpBody = isdump
|
b.setting.DumpBody = isdump
|
||||||
@ -518,13 +512,11 @@ func (b *BeegoHTTPRequest) DoRequest() (resp *http.Response, err error) {
|
|||||||
// retries default value is 0, it will run once.
|
// retries default value is 0, it will run once.
|
||||||
// retries equal to -1, it will run forever until success
|
// retries equal to -1, it will run forever until success
|
||||||
// retries is setted, it will retries fixed times.
|
// retries is setted, it will retries fixed times.
|
||||||
// Sleeps for a 400ms in between calls to reduce spam
|
|
||||||
for i := 0; b.setting.Retries == -1 || i <= b.setting.Retries; i++ {
|
for i := 0; b.setting.Retries == -1 || i <= b.setting.Retries; i++ {
|
||||||
resp, err = client.Do(b.req)
|
resp, err = client.Do(b.req)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
time.Sleep(b.setting.RetryDelay)
|
|
||||||
}
|
}
|
||||||
return resp, err
|
return resp, err
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
package httplib
|
package httplib
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -34,34 +33,6 @@ func TestResponse(t *testing.T) {
|
|||||||
t.Log(resp)
|
t.Log(resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDoRequest(t *testing.T) {
|
|
||||||
req := Get("https://goolnk.com/33BD2j")
|
|
||||||
retryAmount := 1
|
|
||||||
req.Retries(1)
|
|
||||||
req.RetryDelay(1400 * time.Millisecond)
|
|
||||||
retryDelay := 1400 * time.Millisecond
|
|
||||||
|
|
||||||
req.setting.CheckRedirect = func(redirectReq *http.Request, redirectVia []*http.Request) error {
|
|
||||||
return errors.New("Redirect triggered")
|
|
||||||
}
|
|
||||||
|
|
||||||
startTime := time.Now().UnixNano() / int64(time.Millisecond)
|
|
||||||
|
|
||||||
_, err := req.Response()
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("Response should have yielded an error")
|
|
||||||
}
|
|
||||||
|
|
||||||
endTime := time.Now().UnixNano() / int64(time.Millisecond)
|
|
||||||
elapsedTime := endTime - startTime
|
|
||||||
delayedTime := int64(retryAmount) * retryDelay.Milliseconds()
|
|
||||||
|
|
||||||
if elapsedTime < delayedTime {
|
|
||||||
t.Errorf("Not enough retries. Took %dms. Delay was meant to take %dms", elapsedTime, delayedTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGet(t *testing.T) {
|
func TestGet(t *testing.T) {
|
||||||
req := Get("http://httpbin.org/get")
|
req := Get("http://httpbin.org/get")
|
||||||
b, err := req.Bytes()
|
b, err := req.Bytes()
|
||||||
|
@ -16,9 +16,9 @@ package logs
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"strings"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -63,10 +63,7 @@ func (c *connWriter) WriteMsg(when time.Time, msg string, level int) error {
|
|||||||
defer c.innerWriter.Close()
|
defer c.innerWriter.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := c.lg.writeln(when, msg)
|
c.lg.writeln(when, msg)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,6 +101,7 @@ func (c *connWriter) connect() error {
|
|||||||
|
|
||||||
func (c *connWriter) needToConnectOnMsg() bool {
|
func (c *connWriter) needToConnectOnMsg() bool {
|
||||||
if c.Reconnect {
|
if c.Reconnect {
|
||||||
|
c.Reconnect = false
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,65 +15,11 @@
|
|||||||
package logs
|
package logs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ConnTCPListener takes a TCP listener and accepts n TCP connections
|
|
||||||
// Returns connections using connChan
|
|
||||||
func connTCPListener(t *testing.T, n int, ln net.Listener, connChan chan<- net.Conn) {
|
|
||||||
|
|
||||||
// Listen and accept n incoming connections
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
conn, err := ln.Accept()
|
|
||||||
if err != nil {
|
|
||||||
t.Log("Error accepting connection: ", err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send accepted connection to channel
|
|
||||||
connChan <- conn
|
|
||||||
}
|
|
||||||
ln.Close()
|
|
||||||
close(connChan)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestConn(t *testing.T) {
|
func TestConn(t *testing.T) {
|
||||||
log := NewLogger(1000)
|
log := NewLogger(1000)
|
||||||
log.SetLogger("conn", `{"net":"tcp","addr":":7020"}`)
|
log.SetLogger("conn", `{"net":"tcp","addr":":7020"}`)
|
||||||
log.Informational("informational")
|
log.Informational("informational")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestReconnect(t *testing.T) {
|
|
||||||
// Setup connection listener
|
|
||||||
newConns := make(chan net.Conn)
|
|
||||||
connNum := 2
|
|
||||||
ln, err := net.Listen("tcp", ":6002")
|
|
||||||
if err != nil {
|
|
||||||
t.Log("Error listening:", err.Error())
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
go connTCPListener(t, connNum, ln, newConns)
|
|
||||||
|
|
||||||
// Setup logger
|
|
||||||
log := NewLogger(1000)
|
|
||||||
log.SetPrefix("test")
|
|
||||||
log.SetLogger(AdapterConn, `{"net":"tcp","reconnect":true,"level":6,"addr":":6002"}`)
|
|
||||||
log.Informational("informational 1")
|
|
||||||
|
|
||||||
// Refuse first connection
|
|
||||||
first := <-newConns
|
|
||||||
first.Close()
|
|
||||||
|
|
||||||
// Send another log after conn closed
|
|
||||||
log.Informational("informational 2")
|
|
||||||
|
|
||||||
// Check if there was a second connection attempt
|
|
||||||
select {
|
|
||||||
case second := <-newConns:
|
|
||||||
second.Close()
|
|
||||||
default:
|
|
||||||
t.Error("Did not reconnect")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
30
logs/file.go
30
logs/file.go
@ -373,21 +373,21 @@ func (w *fileLogWriter) deleteOldLog() {
|
|||||||
if info == nil {
|
if info == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if w.Hourly {
|
if w.Hourly {
|
||||||
if !info.IsDir() && info.ModTime().Add(1*time.Hour*time.Duration(w.MaxHours)).Before(time.Now()) {
|
if !info.IsDir() && info.ModTime().Add(1 * time.Hour * time.Duration(w.MaxHours)).Before(time.Now()) {
|
||||||
if strings.HasPrefix(filepath.Base(path), filepath.Base(w.fileNameOnly)) &&
|
if strings.HasPrefix(filepath.Base(path), filepath.Base(w.fileNameOnly)) &&
|
||||||
strings.HasSuffix(filepath.Base(path), w.suffix) {
|
strings.HasSuffix(filepath.Base(path), w.suffix) {
|
||||||
os.Remove(path)
|
os.Remove(path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if w.Daily {
|
} else if w.Daily {
|
||||||
if !info.IsDir() && info.ModTime().Add(24*time.Hour*time.Duration(w.MaxDays)).Before(time.Now()) {
|
if !info.IsDir() && info.ModTime().Add(24 * time.Hour * time.Duration(w.MaxDays)).Before(time.Now()) {
|
||||||
if strings.HasPrefix(filepath.Base(path), filepath.Base(w.fileNameOnly)) &&
|
if strings.HasPrefix(filepath.Base(path), filepath.Base(w.fileNameOnly)) &&
|
||||||
strings.HasSuffix(filepath.Base(path), w.suffix) {
|
strings.HasSuffix(filepath.Base(path), w.suffix) {
|
||||||
os.Remove(path)
|
os.Remove(path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -186,7 +186,7 @@ func TestFileDailyRotate_06(t *testing.T) { //test file mode
|
|||||||
|
|
||||||
func TestFileHourlyRotate_01(t *testing.T) {
|
func TestFileHourlyRotate_01(t *testing.T) {
|
||||||
log := NewLogger(10000)
|
log := NewLogger(10000)
|
||||||
log.SetLogger("file", `{"filename":"test3.log","hourly":true,"maxlines":4}`)
|
log.SetLogger("file", `{"filename":"test3.log","hourly":true,"maxlines":4}`)
|
||||||
log.Debug("debug")
|
log.Debug("debug")
|
||||||
log.Info("info")
|
log.Info("info")
|
||||||
log.Notice("notice")
|
log.Notice("notice")
|
||||||
@ -237,7 +237,7 @@ func TestFileHourlyRotate_05(t *testing.T) {
|
|||||||
|
|
||||||
func TestFileHourlyRotate_06(t *testing.T) { //test file mode
|
func TestFileHourlyRotate_06(t *testing.T) { //test file mode
|
||||||
log := NewLogger(10000)
|
log := NewLogger(10000)
|
||||||
log.SetLogger("file", `{"filename":"test3.log", "hourly":true, "maxlines":4}`)
|
log.SetLogger("file", `{"filename":"test3.log", "hourly":true, "maxlines":4}`)
|
||||||
log.Debug("debug")
|
log.Debug("debug")
|
||||||
log.Info("info")
|
log.Info("info")
|
||||||
log.Notice("notice")
|
log.Notice("notice")
|
||||||
@ -269,19 +269,19 @@ func testFileRotate(t *testing.T, fn1, fn2 string, daily, hourly bool) {
|
|||||||
RotatePerm: "0440",
|
RotatePerm: "0440",
|
||||||
}
|
}
|
||||||
|
|
||||||
if daily {
|
if daily {
|
||||||
fw.Init(fmt.Sprintf(`{"filename":"%v","maxdays":1}`, fn1))
|
fw.Init(fmt.Sprintf(`{"filename":"%v","maxdays":1}`, fn1))
|
||||||
fw.dailyOpenTime = time.Now().Add(-24 * time.Hour)
|
fw.dailyOpenTime = time.Now().Add(-24 * time.Hour)
|
||||||
fw.dailyOpenDate = fw.dailyOpenTime.Day()
|
fw.dailyOpenDate = fw.dailyOpenTime.Day()
|
||||||
}
|
}
|
||||||
|
|
||||||
if hourly {
|
if hourly {
|
||||||
fw.Init(fmt.Sprintf(`{"filename":"%v","maxhours":1}`, fn1))
|
fw.Init(fmt.Sprintf(`{"filename":"%v","maxhours":1}`, fn1))
|
||||||
fw.hourlyOpenTime = time.Now().Add(-1 * time.Hour)
|
fw.hourlyOpenTime = time.Now().Add(-1 * time.Hour)
|
||||||
fw.hourlyOpenDate = fw.hourlyOpenTime.Day()
|
fw.hourlyOpenDate = fw.hourlyOpenTime.Day()
|
||||||
}
|
}
|
||||||
|
|
||||||
fw.WriteMsg(time.Now(), "this is a msg for test", LevelDebug)
|
fw.WriteMsg(time.Now(), "this is a msg for test", LevelDebug)
|
||||||
|
|
||||||
for _, file := range []string{fn1, fn2} {
|
for _, file := range []string{fn1, fn2} {
|
||||||
_, err := os.Stat(file)
|
_, err := os.Stat(file)
|
||||||
@ -328,8 +328,8 @@ func testFileDailyRotate(t *testing.T, fn1, fn2 string) {
|
|||||||
|
|
||||||
func testFileHourlyRotate(t *testing.T, fn1, fn2 string) {
|
func testFileHourlyRotate(t *testing.T, fn1, fn2 string) {
|
||||||
fw := &fileLogWriter{
|
fw := &fileLogWriter{
|
||||||
Hourly: true,
|
Hourly: true,
|
||||||
MaxHours: 168,
|
MaxHours: 168,
|
||||||
Rotate: true,
|
Rotate: true,
|
||||||
Level: LevelTrace,
|
Level: LevelTrace,
|
||||||
Perm: "0660",
|
Perm: "0660",
|
||||||
|
@ -30,12 +30,11 @@ func newLogWriter(wr io.Writer) *logWriter {
|
|||||||
return &logWriter{writer: wr}
|
return &logWriter{writer: wr}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lg *logWriter) writeln(when time.Time, msg string) (int, error) {
|
func (lg *logWriter) writeln(when time.Time, msg string) {
|
||||||
lg.Lock()
|
lg.Lock()
|
||||||
h, _, _ := formatTimeHeader(when)
|
h, _, _ := formatTimeHeader(when)
|
||||||
n, err := lg.writer.Write(append(append(h, msg...), '\n'))
|
lg.writer.Write(append(append(h, msg...), '\n'))
|
||||||
lg.Unlock()
|
lg.Unlock()
|
||||||
return n, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -57,15 +57,15 @@ func registerBuildInfo() {
|
|||||||
Subsystem: "build_info",
|
Subsystem: "build_info",
|
||||||
Help: "The building information",
|
Help: "The building information",
|
||||||
ConstLabels: map[string]string{
|
ConstLabels: map[string]string{
|
||||||
"appname": beego.BConfig.AppName,
|
"appname": beego.BConfig.AppName,
|
||||||
"build_version": beego.BuildVersion,
|
"build_version": beego.BuildVersion,
|
||||||
"build_revision": beego.BuildGitRevision,
|
"build_revision": beego.BuildGitRevision,
|
||||||
"build_status": beego.BuildStatus,
|
"build_status": beego.BuildStatus,
|
||||||
"build_tag": beego.BuildTag,
|
"build_tag": beego.BuildTag,
|
||||||
"build_time": strings.Replace(beego.BuildTime, "--", " ", 1),
|
"build_time": strings.Replace(beego.BuildTime, "--", " ", 1),
|
||||||
"go_version": beego.GoVersion,
|
"go_version": beego.GoVersion,
|
||||||
"git_branch": beego.GitBranch,
|
"git_branch": beego.GitBranch,
|
||||||
"start_time": time.Now().Format("2006-01-02 15:04:05"),
|
"start_time": time.Now().Format("2006-01-02 15:04:05"),
|
||||||
},
|
},
|
||||||
}, []string{})
|
}, []string{})
|
||||||
|
|
||||||
|
@ -197,9 +197,9 @@ func getDbCreateSQL(al *alias) (sqls []string, tableIndexes map[string][]dbIndex
|
|||||||
if strings.Contains(column, "%COL%") {
|
if strings.Contains(column, "%COL%") {
|
||||||
column = strings.Replace(column, "%COL%", fi.column, -1)
|
column = strings.Replace(column, "%COL%", fi.column, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if fi.description != "" && al.Driver != DRSqlite {
|
if fi.description != "" && al.Driver!=DRSqlite {
|
||||||
column += " " + fmt.Sprintf("COMMENT '%s'", fi.description)
|
column += " " + fmt.Sprintf("COMMENT '%s'",fi.description)
|
||||||
}
|
}
|
||||||
|
|
||||||
columns = append(columns, column)
|
columns = append(columns, column)
|
||||||
|
11
orm/db.go
11
orm/db.go
@ -36,11 +36,10 @@ var (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
operators = map[string]bool{
|
operators = map[string]bool{
|
||||||
"exact": true,
|
"exact": true,
|
||||||
"iexact": true,
|
"iexact": true,
|
||||||
"strictexact": true,
|
"contains": true,
|
||||||
"contains": true,
|
"icontains": true,
|
||||||
"icontains": true,
|
|
||||||
// "regex": true,
|
// "regex": true,
|
||||||
// "iregex": true,
|
// "iregex": true,
|
||||||
"gt": true,
|
"gt": true,
|
||||||
@ -1203,7 +1202,7 @@ func (d *dbBase) GenerateOperatorSQL(mi *modelInfo, fi *fieldInfo, operator stri
|
|||||||
}
|
}
|
||||||
sql = d.ins.OperatorSQL(operator)
|
sql = d.ins.OperatorSQL(operator)
|
||||||
switch operator {
|
switch operator {
|
||||||
case "exact", "strictexact":
|
case "exact":
|
||||||
if arg == nil {
|
if arg == nil {
|
||||||
params[0] = "IS NULL"
|
params[0] = "IS NULL"
|
||||||
}
|
}
|
||||||
|
@ -18,11 +18,10 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
lru "github.com/hashicorp/golang-lru"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
lru "github.com/hashicorp/golang-lru"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// DriverType database driver constant int.
|
// DriverType database driver constant int.
|
||||||
@ -425,7 +424,8 @@ func GetDB(aliasNames ...string) (*sql.DB, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type stmtDecorator struct {
|
type stmtDecorator struct {
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
lastUse int64
|
||||||
stmt *sql.Stmt
|
stmt *sql.Stmt
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -433,12 +433,9 @@ func (s *stmtDecorator) getStmt() *sql.Stmt {
|
|||||||
return s.stmt
|
return s.stmt
|
||||||
}
|
}
|
||||||
|
|
||||||
// acquire will add one
|
|
||||||
// since this method will be used inside read lock scope,
|
|
||||||
// so we can not do more things here
|
|
||||||
// we should think about refactor this
|
|
||||||
func (s *stmtDecorator) acquire() {
|
func (s *stmtDecorator) acquire() {
|
||||||
s.wg.Add(1)
|
s.wg.Add(1)
|
||||||
|
s.lastUse = time.Now().Unix()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stmtDecorator) release() {
|
func (s *stmtDecorator) release() {
|
||||||
@ -456,13 +453,12 @@ func (s *stmtDecorator) destroy() {
|
|||||||
func newStmtDecorator(sqlStmt *sql.Stmt) *stmtDecorator {
|
func newStmtDecorator(sqlStmt *sql.Stmt) *stmtDecorator {
|
||||||
return &stmtDecorator{
|
return &stmtDecorator{
|
||||||
stmt: sqlStmt,
|
stmt: sqlStmt,
|
||||||
|
lastUse: time.Now().Unix(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newStmtDecoratorLruWithEvict() *lru.Cache {
|
func newStmtDecoratorLruWithEvict() *lru.Cache {
|
||||||
// temporarily solution
|
cache, _ := lru.NewWithEvict(1000, func(key interface{}, value interface{}) {
|
||||||
// we fixed this problem in v2.x
|
|
||||||
cache, _ := lru.NewWithEvict(50, func(key interface{}, value interface{}) {
|
|
||||||
value.(*stmtDecorator).destroy()
|
value.(*stmtDecorator).destroy()
|
||||||
})
|
})
|
||||||
return cache
|
return cache
|
||||||
|
@ -22,11 +22,10 @@ import (
|
|||||||
|
|
||||||
// mysql operators.
|
// mysql operators.
|
||||||
var mysqlOperators = map[string]string{
|
var mysqlOperators = map[string]string{
|
||||||
"exact": "= ?",
|
"exact": "= ?",
|
||||||
"iexact": "LIKE ?",
|
"iexact": "LIKE ?",
|
||||||
"strictexact": "= BINARY ?",
|
"contains": "LIKE BINARY ?",
|
||||||
"contains": "LIKE BINARY ?",
|
"icontains": "LIKE ?",
|
||||||
"icontains": "LIKE ?",
|
|
||||||
// "regex": "REGEXP BINARY ?",
|
// "regex": "REGEXP BINARY ?",
|
||||||
// "iregex": "REGEXP ?",
|
// "iregex": "REGEXP ?",
|
||||||
"gt": "> ?",
|
"gt": "> ?",
|
||||||
|
@ -53,24 +53,18 @@ func (e *SliceStringField) FieldType() int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (e *SliceStringField) SetRaw(value interface{}) error {
|
func (e *SliceStringField) SetRaw(value interface{}) error {
|
||||||
f := func(str string) {
|
switch d := value.(type) {
|
||||||
if len(str) > 0 {
|
case []string:
|
||||||
parts := strings.Split(str, ",")
|
e.Set(d)
|
||||||
|
case string:
|
||||||
|
if len(d) > 0 {
|
||||||
|
parts := strings.Split(d, ",")
|
||||||
v := make([]string, 0, len(parts))
|
v := make([]string, 0, len(parts))
|
||||||
for _, p := range parts {
|
for _, p := range parts {
|
||||||
v = append(v, strings.TrimSpace(p))
|
v = append(v, strings.TrimSpace(p))
|
||||||
}
|
}
|
||||||
e.Set(v)
|
e.Set(v)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
switch d := value.(type) {
|
|
||||||
case []string:
|
|
||||||
e.Set(d)
|
|
||||||
case string:
|
|
||||||
f(d)
|
|
||||||
case []byte:
|
|
||||||
f(string(d))
|
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("<SliceStringField.SetRaw> unknown value `%v`", value)
|
return fmt.Errorf("<SliceStringField.SetRaw> unknown value `%v`", value)
|
||||||
}
|
}
|
||||||
@ -102,8 +96,6 @@ func (e *JSONFieldTest) SetRaw(value interface{}) error {
|
|||||||
switch d := value.(type) {
|
switch d := value.(type) {
|
||||||
case string:
|
case string:
|
||||||
return json.Unmarshal([]byte(d), e)
|
return json.Unmarshal([]byte(d), e)
|
||||||
case []byte:
|
|
||||||
return json.Unmarshal(d, e)
|
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("<JSONField.SetRaw> unknown value `%v`", value)
|
return fmt.Errorf("<JSONField.SetRaw> unknown value `%v`", value)
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ func debugLogQueies(alias *alias, operaton, query string, t time.Time, err error
|
|||||||
con += " - " + err.Error()
|
con += " - " + err.Error()
|
||||||
}
|
}
|
||||||
logMap["sql"] = fmt.Sprintf("%s-`%s`", query, strings.Join(cons, "`, `"))
|
logMap["sql"] = fmt.Sprintf("%s-`%s`", query, strings.Join(cons, "`, `"))
|
||||||
if LogFunc != nil {
|
if LogFunc != nil{
|
||||||
LogFunc(logMap)
|
LogFunc(logMap)
|
||||||
}
|
}
|
||||||
DebugLog.Println(con)
|
DebugLog.Println(con)
|
||||||
|
@ -19,8 +19,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// raw sql string prepared statement
|
// raw sql string prepared statement
|
||||||
@ -370,15 +368,7 @@ func (o *rawSet) QueryRow(containers ...interface{}) error {
|
|||||||
field.Set(mf)
|
field.Set(mf)
|
||||||
field = mf.Elem().FieldByIndex(fi.relModelInfo.fields.pk.fieldIndex)
|
field = mf.Elem().FieldByIndex(fi.relModelInfo.fields.pk.fieldIndex)
|
||||||
}
|
}
|
||||||
if fi.isFielder {
|
o.setFieldValue(field, value)
|
||||||
fd := field.Addr().Interface().(Fielder)
|
|
||||||
err := fd.SetRaw(value)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Errorf("set raw error:%s", err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
o.setFieldValue(field, value)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -519,15 +509,7 @@ func (o *rawSet) QueryRows(containers ...interface{}) (int64, error) {
|
|||||||
field.Set(mf)
|
field.Set(mf)
|
||||||
field = mf.Elem().FieldByIndex(fi.relModelInfo.fields.pk.fieldIndex)
|
field = mf.Elem().FieldByIndex(fi.relModelInfo.fields.pk.fieldIndex)
|
||||||
}
|
}
|
||||||
if fi.isFielder {
|
o.setFieldValue(field, value)
|
||||||
fd := field.Addr().Interface().(Fielder)
|
|
||||||
err := fd.SetRaw(value)
|
|
||||||
if err != nil {
|
|
||||||
return 0, errors.Errorf("set raw error:%s", err)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
o.setFieldValue(field, value)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -769,20 +769,6 @@ func TestCustomField(t *testing.T) {
|
|||||||
|
|
||||||
throwFailNow(t, AssertIs(user.Extra.Name, "beego"))
|
throwFailNow(t, AssertIs(user.Extra.Name, "beego"))
|
||||||
throwFailNow(t, AssertIs(user.Extra.Data, "orm"))
|
throwFailNow(t, AssertIs(user.Extra.Data, "orm"))
|
||||||
|
|
||||||
var users []User
|
|
||||||
Q := dDbBaser.TableQuote()
|
|
||||||
n, err := dORM.Raw(fmt.Sprintf("SELECT * FROM %suser%s where id=?", Q, Q), 2).QueryRows(&users)
|
|
||||||
throwFailNow(t, err)
|
|
||||||
throwFailNow(t, AssertIs(n, 1))
|
|
||||||
throwFailNow(t, AssertIs(users[0].Extra.Name, "beego"))
|
|
||||||
throwFailNow(t, AssertIs(users[0].Extra.Data, "orm"))
|
|
||||||
|
|
||||||
user = User{}
|
|
||||||
err = dORM.Raw(fmt.Sprintf("SELECT * FROM %suser%s where id=?", Q, Q), 2).QueryRow(&user)
|
|
||||||
throwFailNow(t, err)
|
|
||||||
throwFailNow(t, AssertIs(user.Extra.Name, "beego"))
|
|
||||||
throwFailNow(t, AssertIs(user.Extra.Data, "orm"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestExpr(t *testing.T) {
|
func TestExpr(t *testing.T) {
|
||||||
@ -822,17 +808,6 @@ func TestOperators(t *testing.T) {
|
|||||||
throwFail(t, err)
|
throwFail(t, err)
|
||||||
throwFail(t, AssertIs(num, 1))
|
throwFail(t, AssertIs(num, 1))
|
||||||
|
|
||||||
if IsMysql {
|
|
||||||
// Now only mysql support `strictexact`
|
|
||||||
num, err = qs.Filter("user_name__strictexact", "Slene").Count()
|
|
||||||
throwFail(t, err)
|
|
||||||
throwFail(t, AssertIs(num, 0))
|
|
||||||
|
|
||||||
num, err = qs.Filter("user_name__strictexact", "slene").Count()
|
|
||||||
throwFail(t, err)
|
|
||||||
throwFail(t, AssertIs(num, 1))
|
|
||||||
}
|
|
||||||
|
|
||||||
num, err = qs.Filter("user_name__contains", "e").Count()
|
num, err = qs.Filter("user_name__contains", "e").Count()
|
||||||
throwFail(t, err)
|
throwFail(t, err)
|
||||||
throwFail(t, AssertIs(num, 2))
|
throwFail(t, AssertIs(num, 2))
|
||||||
|
@ -40,11 +40,10 @@
|
|||||||
package authz
|
package authz
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/astaxie/beego"
|
"github.com/astaxie/beego"
|
||||||
"github.com/astaxie/beego/context"
|
"github.com/astaxie/beego/context"
|
||||||
"github.com/casbin/casbin"
|
"github.com/casbin/casbin"
|
||||||
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewAuthorizer returns the authorizer.
|
// NewAuthorizer returns the authorizer.
|
||||||
|
@ -15,14 +15,13 @@
|
|||||||
package authz
|
package authz
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
|
||||||
"net/http/httptest"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/astaxie/beego"
|
"github.com/astaxie/beego"
|
||||||
"github.com/astaxie/beego/context"
|
"github.com/astaxie/beego/context"
|
||||||
"github.com/astaxie/beego/plugins/auth"
|
"github.com/astaxie/beego/plugins/auth"
|
||||||
"github.com/casbin/casbin"
|
"github.com/casbin/casbin"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func testRequest(t *testing.T, handler *beego.ControllerRegister, user string, path string, method string, code int) {
|
func testRequest(t *testing.T, handler *beego.ControllerRegister, user string, path string, method string, code int) {
|
||||||
|
@ -742,12 +742,6 @@ func (p *ControllerRegister) ServeHTTP(rw http.ResponseWriter, r *http.Request)
|
|||||||
|
|
||||||
if r.Method != http.MethodGet && r.Method != http.MethodHead {
|
if r.Method != http.MethodGet && r.Method != http.MethodHead {
|
||||||
if BConfig.CopyRequestBody && !context.Input.IsUpload() {
|
if BConfig.CopyRequestBody && !context.Input.IsUpload() {
|
||||||
// connection will close if the incoming data are larger (RFC 7231, 6.5.11)
|
|
||||||
if r.ContentLength > BConfig.MaxMemory {
|
|
||||||
logs.Error(errors.New("payload too large"))
|
|
||||||
exception("413", context)
|
|
||||||
goto Admin
|
|
||||||
}
|
|
||||||
context.Input.CopyBody(BConfig.MaxMemory)
|
context.Input.CopyBody(BConfig.MaxMemory)
|
||||||
}
|
}
|
||||||
context.Input.ParseFormOrMulitForm(BConfig.MaxMemory)
|
context.Input.ParseFormOrMulitForm(BConfig.MaxMemory)
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
package beego
|
package beego
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"strings"
|
"strings"
|
||||||
@ -72,6 +71,7 @@ func (tc *TestController) GetEmptyBody() {
|
|||||||
tc.Ctx.Output.Body(res)
|
tc.Ctx.Output.Body(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type JSONController struct {
|
type JSONController struct {
|
||||||
Controller
|
Controller
|
||||||
}
|
}
|
||||||
@ -656,14 +656,17 @@ func beegoBeforeRouter1(ctx *context.Context) {
|
|||||||
ctx.WriteString("|BeforeRouter1")
|
ctx.WriteString("|BeforeRouter1")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func beegoBeforeExec1(ctx *context.Context) {
|
func beegoBeforeExec1(ctx *context.Context) {
|
||||||
ctx.WriteString("|BeforeExec1")
|
ctx.WriteString("|BeforeExec1")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func beegoAfterExec1(ctx *context.Context) {
|
func beegoAfterExec1(ctx *context.Context) {
|
||||||
ctx.WriteString("|AfterExec1")
|
ctx.WriteString("|AfterExec1")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func beegoFinishRouter1(ctx *context.Context) {
|
func beegoFinishRouter1(ctx *context.Context) {
|
||||||
ctx.WriteString("|FinishRouter1")
|
ctx.WriteString("|FinishRouter1")
|
||||||
}
|
}
|
||||||
@ -706,27 +709,3 @@ func TestYAMLPrepare(t *testing.T) {
|
|||||||
t.Errorf(w.Body.String())
|
t.Errorf(w.Body.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRouterEntityTooLargeCopyBody(t *testing.T) {
|
|
||||||
_MaxMemory := BConfig.MaxMemory
|
|
||||||
_CopyRequestBody := BConfig.CopyRequestBody
|
|
||||||
BConfig.CopyRequestBody = true
|
|
||||||
BConfig.MaxMemory = 20
|
|
||||||
|
|
||||||
b := bytes.NewBuffer([]byte("barbarbarbarbarbarbarbarbarbar"))
|
|
||||||
r, _ := http.NewRequest("POST", "/user/123", b)
|
|
||||||
w := httptest.NewRecorder()
|
|
||||||
|
|
||||||
handler := NewControllerRegister()
|
|
||||||
handler.Post("/user/:id", func(ctx *context.Context) {
|
|
||||||
ctx.Output.Body([]byte(ctx.Input.Param(":id")))
|
|
||||||
})
|
|
||||||
handler.ServeHTTP(w, r)
|
|
||||||
|
|
||||||
BConfig.CopyRequestBody = _CopyRequestBody
|
|
||||||
BConfig.MaxMemory = _MaxMemory
|
|
||||||
|
|
||||||
if w.Code != http.StatusRequestEntityTooLarge {
|
|
||||||
t.Errorf("TestRouterRequestEntityTooLarge can't run")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -31,16 +31,14 @@
|
|||||||
//
|
//
|
||||||
// more docs: http://beego.me/docs/module/session.md
|
// more docs: http://beego.me/docs/module/session.md
|
||||||
package redis_cluster
|
package redis_cluster
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/astaxie/beego/session"
|
"github.com/astaxie/beego/session"
|
||||||
rediss "github.com/go-redis/redis"
|
rediss "github.com/go-redis/redis"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var redispder = &Provider{}
|
var redispder = &Provider{}
|
||||||
@ -103,7 +101,7 @@ func (rs *SessionStore) SessionRelease(w http.ResponseWriter) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
c := rs.p
|
c := rs.p
|
||||||
c.Set(rs.sid, string(b), time.Duration(rs.maxlifetime)*time.Second)
|
c.Set(rs.sid, string(b), time.Duration(rs.maxlifetime) * time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Provider redis_cluster session provider
|
// Provider redis_cluster session provider
|
||||||
@ -148,10 +146,10 @@ func (rp *Provider) SessionInit(maxlifetime int64, savePath string) error {
|
|||||||
} else {
|
} else {
|
||||||
rp.dbNum = 0
|
rp.dbNum = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
rp.poollist = rediss.NewClusterClient(&rediss.ClusterOptions{
|
rp.poollist = rediss.NewClusterClient(&rediss.ClusterOptions{
|
||||||
Addrs: strings.Split(rp.savePath, ";"),
|
Addrs: strings.Split(rp.savePath, ";"),
|
||||||
Password: rp.password,
|
Password: rp.password,
|
||||||
PoolSize: rp.poolsize,
|
PoolSize: rp.poolsize,
|
||||||
})
|
})
|
||||||
return rp.poollist.Ping().Err()
|
return rp.poollist.Ping().Err()
|
||||||
@ -188,15 +186,15 @@ func (rp *Provider) SessionExist(sid string) bool {
|
|||||||
// SessionRegenerate generate new sid for redis_cluster session
|
// SessionRegenerate generate new sid for redis_cluster session
|
||||||
func (rp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) {
|
func (rp *Provider) SessionRegenerate(oldsid, sid string) (session.Store, error) {
|
||||||
c := rp.poollist
|
c := rp.poollist
|
||||||
|
|
||||||
if existed, err := c.Exists(oldsid).Result(); err != nil || existed == 0 {
|
if existed, err := c.Exists(oldsid).Result(); err != nil || existed == 0 {
|
||||||
// oldsid doesn't exists, set the new sid directly
|
// oldsid doesn't exists, set the new sid directly
|
||||||
// ignore error here, since if it return error
|
// ignore error here, since if it return error
|
||||||
// the existed value will be 0
|
// the existed value will be 0
|
||||||
c.Set(sid, "", time.Duration(rp.maxlifetime)*time.Second)
|
c.Set(sid, "", time.Duration(rp.maxlifetime) * time.Second)
|
||||||
} else {
|
} else {
|
||||||
c.Rename(oldsid, sid)
|
c.Rename(oldsid, sid)
|
||||||
c.Expire(sid, time.Duration(rp.maxlifetime)*time.Second)
|
c.Expire(sid, time.Duration(rp.maxlifetime) * time.Second)
|
||||||
}
|
}
|
||||||
return rp.SessionRead(sid)
|
return rp.SessionRead(sid)
|
||||||
}
|
}
|
||||||
|
@ -33,14 +33,13 @@
|
|||||||
package redis_sentinel
|
package redis_sentinel
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/astaxie/beego/session"
|
||||||
|
"github.com/go-redis/redis"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/astaxie/beego/session"
|
|
||||||
"github.com/go-redis/redis"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var redispder = &Provider{}
|
var redispder = &Provider{}
|
||||||
|
@ -15,11 +15,11 @@
|
|||||||
package session
|
package session
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"errors"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
@ -180,11 +180,6 @@ func (fp *FileProvider) SessionExist(sid string) bool {
|
|||||||
filepder.lock.Lock()
|
filepder.lock.Lock()
|
||||||
defer filepder.lock.Unlock()
|
defer filepder.lock.Unlock()
|
||||||
|
|
||||||
if len(sid) < 2 {
|
|
||||||
SLogger.Println("min length of session id is 2", sid)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := os.Stat(path.Join(fp.savePath, string(sid[0]), string(sid[1]), sid))
|
_, err := os.Stat(path.Join(fp.savePath, string(sid[0]), string(sid[1]), sid))
|
||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
@ -1,386 +0,0 @@
|
|||||||
// Copyright 2014 beego Author. All Rights Reserved.
|
|
||||||
//
|
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
// you may not use this file except in compliance with the License.
|
|
||||||
// You may obtain a copy of the License at
|
|
||||||
//
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
//
|
|
||||||
// Unless required by applicable law or agreed to in writing, software
|
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
// See the License for the specific language governing permissions and
|
|
||||||
// limitations under the License.
|
|
||||||
|
|
||||||
package session
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"sync"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const sid = "Session_id"
|
|
||||||
const sidNew = "Session_id_new"
|
|
||||||
const sessionPath = "./_session_runtime"
|
|
||||||
|
|
||||||
var (
|
|
||||||
mutex sync.Mutex
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestFileProvider_SessionInit(t *testing.T) {
|
|
||||||
mutex.Lock()
|
|
||||||
defer mutex.Unlock()
|
|
||||||
os.RemoveAll(sessionPath)
|
|
||||||
defer os.RemoveAll(sessionPath)
|
|
||||||
fp := &FileProvider{}
|
|
||||||
|
|
||||||
_ = fp.SessionInit(180, sessionPath)
|
|
||||||
if fp.maxlifetime != 180 {
|
|
||||||
t.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
if fp.savePath != sessionPath {
|
|
||||||
t.Error()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFileProvider_SessionExist(t *testing.T) {
|
|
||||||
mutex.Lock()
|
|
||||||
defer mutex.Unlock()
|
|
||||||
os.RemoveAll(sessionPath)
|
|
||||||
defer os.RemoveAll(sessionPath)
|
|
||||||
fp := &FileProvider{}
|
|
||||||
|
|
||||||
_ = fp.SessionInit(180, sessionPath)
|
|
||||||
|
|
||||||
if fp.SessionExist(sid) {
|
|
||||||
t.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := fp.SessionRead(sid)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !fp.SessionExist(sid) {
|
|
||||||
t.Error()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFileProvider_SessionExist2(t *testing.T) {
|
|
||||||
mutex.Lock()
|
|
||||||
defer mutex.Unlock()
|
|
||||||
os.RemoveAll(sessionPath)
|
|
||||||
defer os.RemoveAll(sessionPath)
|
|
||||||
fp := &FileProvider{}
|
|
||||||
|
|
||||||
_ = fp.SessionInit(180, sessionPath)
|
|
||||||
|
|
||||||
if fp.SessionExist(sid) {
|
|
||||||
t.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
if fp.SessionExist("") {
|
|
||||||
t.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
if fp.SessionExist("1") {
|
|
||||||
t.Error()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFileProvider_SessionRead(t *testing.T) {
|
|
||||||
mutex.Lock()
|
|
||||||
defer mutex.Unlock()
|
|
||||||
os.RemoveAll(sessionPath)
|
|
||||||
defer os.RemoveAll(sessionPath)
|
|
||||||
fp := &FileProvider{}
|
|
||||||
|
|
||||||
_ = fp.SessionInit(180, sessionPath)
|
|
||||||
|
|
||||||
s, err := fp.SessionRead(sid)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = s.Set("sessionValue", 18975)
|
|
||||||
v := s.Get("sessionValue")
|
|
||||||
|
|
||||||
if v.(int) != 18975 {
|
|
||||||
t.Error()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFileProvider_SessionRead1(t *testing.T) {
|
|
||||||
mutex.Lock()
|
|
||||||
defer mutex.Unlock()
|
|
||||||
os.RemoveAll(sessionPath)
|
|
||||||
defer os.RemoveAll(sessionPath)
|
|
||||||
fp := &FileProvider{}
|
|
||||||
|
|
||||||
_ = fp.SessionInit(180, sessionPath)
|
|
||||||
|
|
||||||
_, err := fp.SessionRead("")
|
|
||||||
if err == nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = fp.SessionRead("1")
|
|
||||||
if err == nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFileProvider_SessionAll(t *testing.T) {
|
|
||||||
mutex.Lock()
|
|
||||||
defer mutex.Unlock()
|
|
||||||
os.RemoveAll(sessionPath)
|
|
||||||
defer os.RemoveAll(sessionPath)
|
|
||||||
fp := &FileProvider{}
|
|
||||||
|
|
||||||
_ = fp.SessionInit(180, sessionPath)
|
|
||||||
|
|
||||||
sessionCount := 546
|
|
||||||
|
|
||||||
for i := 1; i <= sessionCount; i++ {
|
|
||||||
_, err := fp.SessionRead(fmt.Sprintf("%s_%d", sid, i))
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if fp.SessionAll() != sessionCount {
|
|
||||||
t.Error()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFileProvider_SessionRegenerate(t *testing.T) {
|
|
||||||
mutex.Lock()
|
|
||||||
defer mutex.Unlock()
|
|
||||||
os.RemoveAll(sessionPath)
|
|
||||||
defer os.RemoveAll(sessionPath)
|
|
||||||
fp := &FileProvider{}
|
|
||||||
|
|
||||||
_ = fp.SessionInit(180, sessionPath)
|
|
||||||
|
|
||||||
_, err := fp.SessionRead(sid)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !fp.SessionExist(sid) {
|
|
||||||
t.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = fp.SessionRegenerate(sid, sidNew)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if fp.SessionExist(sid) {
|
|
||||||
t.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
if !fp.SessionExist(sidNew) {
|
|
||||||
t.Error()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFileProvider_SessionDestroy(t *testing.T) {
|
|
||||||
mutex.Lock()
|
|
||||||
defer mutex.Unlock()
|
|
||||||
os.RemoveAll(sessionPath)
|
|
||||||
defer os.RemoveAll(sessionPath)
|
|
||||||
fp := &FileProvider{}
|
|
||||||
|
|
||||||
_ = fp.SessionInit(180, sessionPath)
|
|
||||||
|
|
||||||
_, err := fp.SessionRead(sid)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !fp.SessionExist(sid) {
|
|
||||||
t.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
err = fp.SessionDestroy(sid)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if fp.SessionExist(sid) {
|
|
||||||
t.Error()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFileProvider_SessionGC(t *testing.T) {
|
|
||||||
mutex.Lock()
|
|
||||||
defer mutex.Unlock()
|
|
||||||
os.RemoveAll(sessionPath)
|
|
||||||
defer os.RemoveAll(sessionPath)
|
|
||||||
fp := &FileProvider{}
|
|
||||||
|
|
||||||
_ = fp.SessionInit(1, sessionPath)
|
|
||||||
|
|
||||||
sessionCount := 412
|
|
||||||
|
|
||||||
for i := 1; i <= sessionCount; i++ {
|
|
||||||
_, err := fp.SessionRead(fmt.Sprintf("%s_%d", sid, i))
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
time.Sleep(2 * time.Second)
|
|
||||||
|
|
||||||
fp.SessionGC()
|
|
||||||
if fp.SessionAll() != 0 {
|
|
||||||
t.Error()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFileSessionStore_Set(t *testing.T) {
|
|
||||||
mutex.Lock()
|
|
||||||
defer mutex.Unlock()
|
|
||||||
os.RemoveAll(sessionPath)
|
|
||||||
defer os.RemoveAll(sessionPath)
|
|
||||||
fp := &FileProvider{}
|
|
||||||
|
|
||||||
_ = fp.SessionInit(180, sessionPath)
|
|
||||||
|
|
||||||
sessionCount := 100
|
|
||||||
s, _ := fp.SessionRead(sid)
|
|
||||||
for i := 1; i <= sessionCount; i++ {
|
|
||||||
err := s.Set(i, i)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFileSessionStore_Get(t *testing.T) {
|
|
||||||
mutex.Lock()
|
|
||||||
defer mutex.Unlock()
|
|
||||||
os.RemoveAll(sessionPath)
|
|
||||||
defer os.RemoveAll(sessionPath)
|
|
||||||
fp := &FileProvider{}
|
|
||||||
|
|
||||||
_ = fp.SessionInit(180, sessionPath)
|
|
||||||
|
|
||||||
sessionCount := 100
|
|
||||||
s, _ := fp.SessionRead(sid)
|
|
||||||
for i := 1; i <= sessionCount; i++ {
|
|
||||||
_ = s.Set(i, i)
|
|
||||||
|
|
||||||
v := s.Get(i)
|
|
||||||
if v.(int) != i {
|
|
||||||
t.Error()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFileSessionStore_Delete(t *testing.T) {
|
|
||||||
mutex.Lock()
|
|
||||||
defer mutex.Unlock()
|
|
||||||
os.RemoveAll(sessionPath)
|
|
||||||
defer os.RemoveAll(sessionPath)
|
|
||||||
fp := &FileProvider{}
|
|
||||||
|
|
||||||
_ = fp.SessionInit(180, sessionPath)
|
|
||||||
|
|
||||||
s, _ := fp.SessionRead(sid)
|
|
||||||
s.Set("1", 1)
|
|
||||||
|
|
||||||
if s.Get("1") == nil {
|
|
||||||
t.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
s.Delete("1")
|
|
||||||
|
|
||||||
if s.Get("1") != nil {
|
|
||||||
t.Error()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFileSessionStore_Flush(t *testing.T) {
|
|
||||||
mutex.Lock()
|
|
||||||
defer mutex.Unlock()
|
|
||||||
os.RemoveAll(sessionPath)
|
|
||||||
defer os.RemoveAll(sessionPath)
|
|
||||||
fp := &FileProvider{}
|
|
||||||
|
|
||||||
_ = fp.SessionInit(180, sessionPath)
|
|
||||||
|
|
||||||
sessionCount := 100
|
|
||||||
s, _ := fp.SessionRead(sid)
|
|
||||||
for i := 1; i <= sessionCount; i++ {
|
|
||||||
_ = s.Set(i, i)
|
|
||||||
}
|
|
||||||
|
|
||||||
_ = s.Flush()
|
|
||||||
|
|
||||||
for i := 1; i <= sessionCount; i++ {
|
|
||||||
if s.Get(i) != nil {
|
|
||||||
t.Error()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFileSessionStore_SessionID(t *testing.T) {
|
|
||||||
mutex.Lock()
|
|
||||||
defer mutex.Unlock()
|
|
||||||
os.RemoveAll(sessionPath)
|
|
||||||
defer os.RemoveAll(sessionPath)
|
|
||||||
fp := &FileProvider{}
|
|
||||||
|
|
||||||
_ = fp.SessionInit(180, sessionPath)
|
|
||||||
|
|
||||||
sessionCount := 85
|
|
||||||
|
|
||||||
for i := 1; i <= sessionCount; i++ {
|
|
||||||
s, err := fp.SessionRead(fmt.Sprintf("%s_%d", sid, i))
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
if s.SessionID() != fmt.Sprintf("%s_%d", sid, i) {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestFileSessionStore_SessionRelease(t *testing.T) {
|
|
||||||
mutex.Lock()
|
|
||||||
defer mutex.Unlock()
|
|
||||||
os.RemoveAll(sessionPath)
|
|
||||||
defer os.RemoveAll(sessionPath)
|
|
||||||
fp := &FileProvider{}
|
|
||||||
|
|
||||||
_ = fp.SessionInit(180, sessionPath)
|
|
||||||
filepder.savePath = sessionPath
|
|
||||||
sessionCount := 85
|
|
||||||
|
|
||||||
for i := 1; i <= sessionCount; i++ {
|
|
||||||
s, err := fp.SessionRead(fmt.Sprintf("%s_%d", sid, i))
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
s.Set(i, i)
|
|
||||||
s.SessionRelease(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 1; i <= sessionCount; i++ {
|
|
||||||
s, err := fp.SessionRead(fmt.Sprintf("%s_%d", sid, i))
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if s.Get(i).(int) != i {
|
|
||||||
t.Error()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -92,21 +92,20 @@ func GetProvider(name string) (Provider, error) {
|
|||||||
|
|
||||||
// ManagerConfig define the session config
|
// ManagerConfig define the session config
|
||||||
type ManagerConfig struct {
|
type ManagerConfig struct {
|
||||||
CookieName string `json:"cookieName"`
|
CookieName string `json:"cookieName"`
|
||||||
EnableSetCookie bool `json:"enableSetCookie,omitempty"`
|
EnableSetCookie bool `json:"enableSetCookie,omitempty"`
|
||||||
Gclifetime int64 `json:"gclifetime"`
|
Gclifetime int64 `json:"gclifetime"`
|
||||||
Maxlifetime int64 `json:"maxLifetime"`
|
Maxlifetime int64 `json:"maxLifetime"`
|
||||||
DisableHTTPOnly bool `json:"disableHTTPOnly"`
|
DisableHTTPOnly bool `json:"disableHTTPOnly"`
|
||||||
Secure bool `json:"secure"`
|
Secure bool `json:"secure"`
|
||||||
CookieLifeTime int `json:"cookieLifeTime"`
|
CookieLifeTime int `json:"cookieLifeTime"`
|
||||||
ProviderConfig string `json:"providerConfig"`
|
ProviderConfig string `json:"providerConfig"`
|
||||||
Domain string `json:"domain"`
|
Domain string `json:"domain"`
|
||||||
SessionIDLength int64 `json:"sessionIDLength"`
|
SessionIDLength int64 `json:"sessionIDLength"`
|
||||||
EnableSidInHTTPHeader bool `json:"EnableSidInHTTPHeader"`
|
EnableSidInHTTPHeader bool `json:"EnableSidInHTTPHeader"`
|
||||||
SessionNameInHTTPHeader string `json:"SessionNameInHTTPHeader"`
|
SessionNameInHTTPHeader string `json:"SessionNameInHTTPHeader"`
|
||||||
EnableSidInURLQuery bool `json:"EnableSidInURLQuery"`
|
EnableSidInURLQuery bool `json:"EnableSidInURLQuery"`
|
||||||
SessionIDPrefix string `json:"sessionIDPrefix"`
|
SessionIDPrefix string `json:"sessionIDPrefix"`
|
||||||
CookieSameSite http.SameSite `json:"cookieSameSite"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manager contains Provider and its configuration.
|
// Manager contains Provider and its configuration.
|
||||||
@ -233,7 +232,6 @@ func (manager *Manager) SessionStart(w http.ResponseWriter, r *http.Request) (se
|
|||||||
HttpOnly: !manager.config.DisableHTTPOnly,
|
HttpOnly: !manager.config.DisableHTTPOnly,
|
||||||
Secure: manager.isSecure(r),
|
Secure: manager.isSecure(r),
|
||||||
Domain: manager.config.Domain,
|
Domain: manager.config.Domain,
|
||||||
SameSite: manager.config.CookieSameSite,
|
|
||||||
}
|
}
|
||||||
if manager.config.CookieLifeTime > 0 {
|
if manager.config.CookieLifeTime > 0 {
|
||||||
cookie.MaxAge = manager.config.CookieLifeTime
|
cookie.MaxAge = manager.config.CookieLifeTime
|
||||||
@ -273,9 +271,7 @@ func (manager *Manager) SessionDestroy(w http.ResponseWriter, r *http.Request) {
|
|||||||
HttpOnly: !manager.config.DisableHTTPOnly,
|
HttpOnly: !manager.config.DisableHTTPOnly,
|
||||||
Expires: expiration,
|
Expires: expiration,
|
||||||
MaxAge: -1,
|
MaxAge: -1,
|
||||||
Domain: manager.config.Domain,
|
Domain: manager.config.Domain}
|
||||||
SameSite: manager.config.CookieSameSite,
|
|
||||||
}
|
|
||||||
|
|
||||||
http.SetCookie(w, cookie)
|
http.SetCookie(w, cookie)
|
||||||
}
|
}
|
||||||
@ -310,7 +306,6 @@ func (manager *Manager) SessionRegenerateID(w http.ResponseWriter, r *http.Reque
|
|||||||
HttpOnly: !manager.config.DisableHTTPOnly,
|
HttpOnly: !manager.config.DisableHTTPOnly,
|
||||||
Secure: manager.isSecure(r),
|
Secure: manager.isSecure(r),
|
||||||
Domain: manager.config.Domain,
|
Domain: manager.config.Domain,
|
||||||
SameSite: manager.config.CookieSameSite,
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
oldsid, _ := url.QueryUnescape(cookie.Value)
|
oldsid, _ := url.QueryUnescape(cookie.Value)
|
||||||
|
@ -202,7 +202,7 @@ func searchFile(ctx *context.Context) (string, os.FileInfo, error) {
|
|||||||
if !strings.Contains(requestPath, prefix) {
|
if !strings.Contains(requestPath, prefix) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if prefix != "/" && len(requestPath) > len(prefix) && requestPath[len(prefix)] != '/' {
|
if prefix != "/" && len(requestPath) > len(prefix) && requestPath[len(prefix)] != '/' {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
filePath := path.Join(staticDir, requestPath[len(prefix):])
|
filePath := path.Join(staticDir, requestPath[len(prefix):])
|
||||||
|
@ -16,13 +16,12 @@ package beego
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"github.com/astaxie/beego/testdata"
|
||||||
|
"github.com/elazarl/go-bindata-assetfs"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/astaxie/beego/testdata"
|
|
||||||
"github.com/elazarl/go-bindata-assetfs"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var header = `{{define "header"}}
|
var header = `{{define "header"}}
|
||||||
@ -46,12 +45,8 @@ var block = `{{define "block"}}
|
|||||||
<h1>Hello, blocks!</h1>
|
<h1>Hello, blocks!</h1>
|
||||||
{{end}}`
|
{{end}}`
|
||||||
|
|
||||||
func tmpDir(s string) string {
|
|
||||||
return filepath.Join(os.TempDir(), s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestTemplate(t *testing.T) {
|
func TestTemplate(t *testing.T) {
|
||||||
dir := tmpDir("TestTemplate")
|
dir := "_beeTmp"
|
||||||
files := []string{
|
files := []string{
|
||||||
"header.tpl",
|
"header.tpl",
|
||||||
"index.tpl",
|
"index.tpl",
|
||||||
@ -112,7 +107,7 @@ var user = `<!DOCTYPE html>
|
|||||||
`
|
`
|
||||||
|
|
||||||
func TestRelativeTemplate(t *testing.T) {
|
func TestRelativeTemplate(t *testing.T) {
|
||||||
dir := tmpDir("TestRelativeTemplate")
|
dir := "_beeTmp"
|
||||||
|
|
||||||
//Just add dir to known viewPaths
|
//Just add dir to known viewPaths
|
||||||
if err := AddViewPath(dir); err != nil {
|
if err := AddViewPath(dir); err != nil {
|
||||||
@ -223,7 +218,7 @@ var output = `<!DOCTYPE html>
|
|||||||
`
|
`
|
||||||
|
|
||||||
func TestTemplateLayout(t *testing.T) {
|
func TestTemplateLayout(t *testing.T) {
|
||||||
dir := tmpDir("TestTemplateLayout")
|
dir := "_beeTmp"
|
||||||
files := []string{
|
files := []string{
|
||||||
"add.tpl",
|
"add.tpl",
|
||||||
"layout_blog.tpl",
|
"layout_blog.tpl",
|
||||||
|
@ -362,7 +362,7 @@ func parseFormToStruct(form url.Values, objT reflect.Type, objV reflect.Value) e
|
|||||||
value = value[:25]
|
value = value[:25]
|
||||||
t, err = time.ParseInLocation(time.RFC3339, value, time.Local)
|
t, err = time.ParseInLocation(time.RFC3339, value, time.Local)
|
||||||
} else if strings.HasSuffix(strings.ToUpper(value), "Z") {
|
} else if strings.HasSuffix(strings.ToUpper(value), "Z") {
|
||||||
t, err = time.ParseInLocation(time.RFC3339, value, time.Local)
|
t, err = time.ParseInLocation(time.RFC3339, value, time.Local)
|
||||||
} else if len(value) >= 19 {
|
} else if len(value) >= 19 {
|
||||||
if strings.Contains(value, "T") {
|
if strings.Contains(value, "T") {
|
||||||
value = value[:19]
|
value = value[:19]
|
||||||
|
14
test.sh
14
test.sh
@ -1,14 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
docker-compose -f test_docker_compose.yaml up -d
|
|
||||||
|
|
||||||
export ORM_DRIVER=mysql
|
|
||||||
export TZ=UTC
|
|
||||||
export ORM_SOURCE="beego:test@tcp(localhost:13306)/orm_test?charset=utf8"
|
|
||||||
|
|
||||||
go test ./...
|
|
||||||
|
|
||||||
# clear all container
|
|
||||||
docker-compose -f test_docker_compose.yaml down
|
|
||||||
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
|||||||
version: "3.8"
|
|
||||||
services:
|
|
||||||
redis:
|
|
||||||
container_name: "beego-redis"
|
|
||||||
image: redis
|
|
||||||
environment:
|
|
||||||
- ALLOW_EMPTY_PASSWORD=yes
|
|
||||||
ports:
|
|
||||||
- "6379:6379"
|
|
||||||
|
|
||||||
mysql:
|
|
||||||
container_name: "beego-mysql"
|
|
||||||
image: mysql:5.7.30
|
|
||||||
ports:
|
|
||||||
- "13306:3306"
|
|
||||||
environment:
|
|
||||||
- MYSQL_ROOT_PASSWORD=1q2w3e
|
|
||||||
- MYSQL_DATABASE=orm_test
|
|
||||||
- MYSQL_USER=beego
|
|
||||||
- MYSQL_PASSWORD=test
|
|
||||||
|
|
||||||
postgresql:
|
|
||||||
container_name: "beego-postgresql"
|
|
||||||
image: bitnami/postgresql:latest
|
|
||||||
ports:
|
|
||||||
- "5432:5432"
|
|
||||||
environment:
|
|
||||||
- ALLOW_EMPTY_PASSWORD=yes
|
|
||||||
ssdb:
|
|
||||||
container_name: "beego-ssdb"
|
|
||||||
image: wendal/ssdb
|
|
||||||
ports:
|
|
||||||
- "8888:8888"
|
|
||||||
memcache:
|
|
||||||
container_name: "beego-memcache"
|
|
||||||
image: memcached
|
|
||||||
ports:
|
|
||||||
- "11211:11211"
|
|
||||||
|
|
3
testdata/bindata.go
vendored
3
testdata/bindata.go
vendored
@ -11,14 +11,13 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/elazarl/go-bindata-assetfs"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/elazarl/go-bindata-assetfs"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func bindataRead(data []byte, name string) ([]byte, error) {
|
func bindataRead(data []byte, name string) ([]byte, error) {
|
||||||
|
@ -213,7 +213,7 @@ func parseFunc(vfunc, key string, label string) (v ValidFunc, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
tParams, err := trim(name, key+"."+name+"."+label, params)
|
tParams, err := trim(name, key+"."+ name + "." + label, params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -16,14 +16,13 @@ package validation
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/astaxie/beego/logs"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
|
|
||||||
"github.com/astaxie/beego/logs"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// CanSkipFuncs will skip valid if RequiredFirst is true and the struct field's value is empty
|
// CanSkipFuncs will skip valid if RequiredFirst is true and the struct field's value is empty
|
||||||
|
Reference in New Issue
Block a user