mirror of
https://github.com/astaxie/beego.git
synced 2025-07-11 18:01:01 +00:00
Compare commits
288 Commits
Author | SHA1 | Date | |
---|---|---|---|
56d89cc55c | |||
e048377594 | |||
34334a52be | |||
7cdf96d21a | |||
fad897346f | |||
650fde66aa | |||
e284b0ddae | |||
20a0de6bd0 | |||
b4396c97bb | |||
471ebba64d | |||
d07a1eaa8e | |||
9524036aab | |||
45260e4119 | |||
02234dc503 | |||
05f4e0c146 | |||
ae108ec826 | |||
7c61eb058f | |||
03ba495b7f | |||
d26683799a | |||
f9075e8274 | |||
022ad862ac | |||
93bdf97068 | |||
3c48719999 | |||
cbb3de741d | |||
c510926cb8 | |||
140a4b90a3 | |||
c07acaebbc | |||
105b874477 | |||
3fc21ae6ec | |||
ccf873fa8b | |||
2572094a8d | |||
568626cd57 | |||
34d6a733e9 | |||
e44f16c672 | |||
d41abdb5e4 | |||
f1358cf78d | |||
14c1b76569 | |||
2708916f96 | |||
034cb3222e | |||
66804324f2 | |||
dc65055cf6 | |||
8cc74652a2 | |||
6aa6c55f07 | |||
ff762b561c | |||
d8e8f41230 | |||
9e6b8fcf34 | |||
48e98482f7 | |||
ff7a8b966b | |||
f9bef68aa9 | |||
484beb8bad | |||
43560dede4 | |||
c435d231ab | |||
b838683731 | |||
70cca5e298 | |||
f1cca45d8d | |||
4dc694411f | |||
3364c609de | |||
c5d43e87fe | |||
b89d9511ab | |||
325a0821c1 | |||
dd3f1ce9be | |||
463e96447a | |||
03498529b9 | |||
9a7c43c404 | |||
44127edefc | |||
089006525e | |||
2846043f2a | |||
e6a257f987 | |||
2473e69417 | |||
d455805a0a | |||
bd1cfefec7 | |||
7effdb0e7d | |||
b027968c0b | |||
961f300c14 | |||
7570abd310 | |||
7c8136710c | |||
a3ece98cec | |||
a31dce6216 | |||
a1782cc22d | |||
67f64afa85 | |||
2539fe3831 | |||
05c125ec2d | |||
6e638ef6c8 | |||
df043f22fc | |||
fbaf3380c6 | |||
b7bc57c4d1 | |||
32cdda96bd | |||
5995b00fa2 | |||
5618df8c76 | |||
c6c9ad46f9 | |||
5973ef107c | |||
b575fa1ebe | |||
6bbca96c6c | |||
63cd8e4e15 | |||
93736a8e66 | |||
654d87b210 | |||
0048b7d158 | |||
00e44952ff | |||
8982f5d702 | |||
6612bc4c2a | |||
f580a714d5 | |||
9ccd58bfff | |||
0f50b07a20 | |||
b86cf22fc4 | |||
6bf01eaeca | |||
8e015deee5 | |||
3acda41bc7 | |||
5b3dd7e50f | |||
f4a43814be | |||
35f1bd2119 | |||
f6c95ad534 | |||
f1950482c2 | |||
1dae2c9eb3 | |||
8ef9965eef | |||
3530457ff9 | |||
cbd51616f1 | |||
bdd8df6751 | |||
8fc4f8847c | |||
3bf5cde38c | |||
7a53baaf9b | |||
7574b91760 | |||
78d91062c9 | |||
23792401b5 | |||
e54dbabf0b | |||
cdc8110ea4 | |||
185d55eb46 | |||
8e879726fe | |||
33b052bc7a | |||
087399c44a | |||
f4f200cf04 | |||
0a58428220 | |||
c0462f75bf | |||
5cf33f2655 | |||
670064686e | |||
0019e0fc1b | |||
03bec05714 | |||
e831b97eb8 | |||
81b9a1382a | |||
0189e6329a | |||
6684924e99 | |||
e0a934af1d | |||
8178f035a0 | |||
2b39ff7837 | |||
c2361170b3 | |||
5b35bf6065 | |||
14c911e9d7 | |||
9472cba6c9 | |||
b83094ac1e | |||
1cb0ff560d | |||
cceecad8c2 | |||
d24f861629 | |||
c2471b22ad | |||
c5970766a3 | |||
48a98ec1a5 | |||
ed1d2c7f6e | |||
7a94996e22 | |||
597c55d547 | |||
026e8bc55a | |||
581e48679e | |||
09afe0ae8e | |||
08e49ca323 | |||
e1da804b2b | |||
705e091593 | |||
6bdedff457 | |||
f3be6dd2e9 | |||
9fe353dd0b | |||
9003ca3eef | |||
ff5ac3adf4 | |||
ca4a217783 | |||
e6ea307549 | |||
2c16c7b917 | |||
77ddc3338f | |||
ac3a549187 | |||
fe56de06b5 | |||
6c002a3124 | |||
cead72c6df | |||
7fe4eaef50 | |||
63599c0032 | |||
4db256c9fb | |||
c548764c8e | |||
b4a85c8f13 | |||
94f476fa39 | |||
8574e30b3a | |||
7442919f5a | |||
f6ec4efc70 | |||
7b899aa9af | |||
f73eee75ff | |||
739b8bab0c | |||
139c393f08 | |||
bdec93986b | |||
7ce0fde171 | |||
d6a2621b3c | |||
813a4df3c5 | |||
7267f5e573 | |||
5bc8d90d7f | |||
2d1c02e1c1 | |||
9ca9535c48 | |||
d1d9df74c7 | |||
d326d74c34 | |||
82178a487b | |||
a1b7fd3c93 | |||
0813471202 | |||
ce698aacf6 | |||
c22af4c611 | |||
f8c0e6fec5 | |||
882f1273c8 | |||
5a1fa4e1ec | |||
d05460237c | |||
75107f735e | |||
2e891152dd | |||
dec98f004c | |||
26b016a3a4 | |||
19aae0b7e1 | |||
2e192e1ed0 | |||
f9a3eae9d5 | |||
7fc1e4de96 | |||
993ccac2bd | |||
2fd65a469c | |||
a2fa073072 | |||
08cec9178f | |||
63b3fc4a99 | |||
1b4bb43df0 | |||
ec55edfbc4 | |||
2fce8f9d1b | |||
15489fa76a | |||
e7d8bab5d9 | |||
2f5683610f | |||
5c8c088684 | |||
009074725e | |||
ce50ca22d7 | |||
3052c64b6c | |||
5f2f6e4f86 | |||
3382a5baa1 | |||
882aa9b967 | |||
02972d8702 | |||
261b704d8b | |||
6c6cf91741 | |||
ae8461f95d | |||
aa3987f816 | |||
3dc5ec1060 | |||
1961c1e441 | |||
787bb60b42 | |||
12b984861d | |||
79ffef90e3 | |||
6f5c5bd3a6 | |||
28e6b3b924 | |||
9e1346ef4d | |||
9f295067b7 | |||
71776e4bef | |||
d4074b5004 | |||
22b8cae73b | |||
aa06a10493 | |||
9b58c2836c | |||
7312197732 | |||
e87de70c6d | |||
4304b40a82 | |||
e8facd28f5 | |||
54ef476600 | |||
756df9385f | |||
21f281655d | |||
2e7fb81348 | |||
ebc0207909 | |||
2386c9c80d | |||
b9f9fcca5f | |||
16d71893cd | |||
cfff0f3b46 | |||
93eb7c6b83 | |||
79c2157ad4 | |||
30eb889a91 | |||
9c51952db4 | |||
16b66509f6 | |||
d5695060c5 | |||
af2143f8fb | |||
a66b9950e7 | |||
44460bc457 | |||
41feb3a711 | |||
b6f7d30f9f | |||
4aad313de7 | |||
aefe21b63a | |||
32da446eb1 | |||
d9c016ed98 | |||
7258ef113a | |||
d6779c4a90 | |||
192a278a2a | |||
9d936c58bf | |||
ffe1d52120 | |||
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"
|
||||||
|
3
cache/redis/redis.go
vendored
3
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 (
|
||||||
|
@ -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
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
|
@ -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"))
|
|
||||||
}
|
}
|
||||||
|
@ -332,15 +332,9 @@ func (input *BeegoInput) Query(key string) string {
|
|||||||
if val := input.Param(key); val != "" {
|
if val := input.Param(key); val != "" {
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
if input.Context.Request.Form == nil {
|
|
||||||
input.dataLock.Lock()
|
|
||||||
if input.Context.Request.Form == nil {
|
if input.Context.Request.Form == nil {
|
||||||
input.Context.Request.ParseForm()
|
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)
|
||||||
|
|
||||||
|
14
error.go
14
error.go
@ -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,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 (
|
||||||
|
10
orm/db.go
10
orm/db.go
@ -38,7 +38,6 @@ 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,
|
||||||
@ -703,13 +702,6 @@ func (d *dbBase) Delete(q dbQuerier, mi *modelInfo, ind reflect.Value, tz *time.
|
|||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
if num > 0 {
|
if num > 0 {
|
||||||
if mi.fields.pk.auto {
|
|
||||||
if mi.fields.pk.fieldType&IsPositiveIntegerField > 0 {
|
|
||||||
ind.FieldByIndex(mi.fields.pk.fieldIndex).SetUint(0)
|
|
||||||
} else {
|
|
||||||
ind.FieldByIndex(mi.fields.pk.fieldIndex).SetInt(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
err := d.deleteRels(q, mi, args, tz)
|
err := d.deleteRels(q, mi, args, tz)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return num, err
|
return num, err
|
||||||
@ -1203,7 +1195,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.
|
||||||
@ -426,6 +425,7 @@ 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
|
||||||
|
@ -24,7 +24,6 @@ import (
|
|||||||
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 ?",
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -242,14 +242,8 @@ func (o *orm) Update(md interface{}, cols ...string) (int64, error) {
|
|||||||
func (o *orm) Delete(md interface{}, cols ...string) (int64, error) {
|
func (o *orm) Delete(md interface{}, cols ...string) (int64, error) {
|
||||||
mi, ind := o.getMiInd(md, true)
|
mi, ind := o.getMiInd(md, true)
|
||||||
num, err := o.alias.DbBaser.Delete(o.db, mi, ind, o.alias.TZ, cols)
|
num, err := o.alias.DbBaser.Delete(o.db, mi, ind, o.alias.TZ, cols)
|
||||||
if err != nil {
|
|
||||||
return num, err
|
return num, err
|
||||||
}
|
}
|
||||||
if num > 0 {
|
|
||||||
o.setPk(mi, ind, 0)
|
|
||||||
}
|
|
||||||
return num, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// create a models to models queryer
|
// create a models to models queryer
|
||||||
func (o *orm) QueryM2M(md interface{}, name string) QueryM2Mer {
|
func (o *orm) QueryM2M(md interface{}, name string) QueryM2Mer {
|
||||||
|
@ -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,17 +368,9 @@ 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 {
|
|
||||||
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)
|
o.setFieldValue(field, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
for i := 0; i < ind.NumField(); i++ {
|
for i := 0; i < ind.NumField(); i++ {
|
||||||
f := ind.Field(i)
|
f := ind.Field(i)
|
||||||
@ -519,17 +509,9 @@ 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 {
|
|
||||||
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)
|
o.setFieldValue(field, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// define recursive function
|
// define recursive function
|
||||||
var recursiveSetField func(rv reflect.Value)
|
var recursiveSetField func(rv reflect.Value)
|
||||||
|
@ -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{}
|
||||||
|
@ -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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -106,7 +106,6 @@ type ManagerConfig struct {
|
|||||||
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)
|
||||||
|
@ -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",
|
||||||
|
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) {
|
||||||
|
@ -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