diff --git a/CHANGELOG.md b/CHANGELOG.md index f25b7dd5..7e803c99 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ Note: now we force the web admin service serving HTTP only. - [Feat 4999: add get all tasks function](https://github.com/beego/beego/pull/4999) - [Fix 5012: fix some bug, pass []any as any in variadic function](https://github.com/beego/beego/pull/5012) - [Fix 5022: Miss assigning listener to graceful Server](https://github.com/beego/beego/pull/5028) +- [Fix 4955: Make commands and Docker compose for ORM unit tests](https://github.com/beego/beego/pull/5031) # v2.0.4 diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..d2a2e169 --- /dev/null +++ b/Makefile @@ -0,0 +1,64 @@ +# Copyright 2020 +# +# 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. + + +##@ General + +# The help target prints out all targets with their descriptions organized +# beneath their categories. The categories are represented by '##@' and the +# target descriptions by '##'. The awk commands is responsible for reading the +# entire set of makefiles included in this invocation, looking for lines of the +# file as xyz: ## something, and then pretty-format the target and help. Then, +# if there's a line with ##@ something, that gets pretty-printed as a category. +# More info on the usage of ANSI control characters for terminal formatting: +# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters +# More info on the awk command: +# http://linuxcommand.org/lc3_adv_awk.php + +help: ## Display this help. + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) + + +##@ Test + +test-orm-mysql5: ## Run ORM unit tests on mysql5. + docker-compose -f scripts/orm_docker_compose.yaml up -d + export ORM_DRIVER=mysql + export ORM_SOURCE="beego:test@tcp(localhost:13306)/orm_test?charset=utf8" + go test -v github.com/beego/beego/v2/client/orm + docker-compose -f scripts/orm_docker_compose.yaml down + +test-orm-mysql8: ## Run ORM unit tests on mysql8. + docker-compose -f scripts/orm_docker_compose.yaml up -d + export ORM_DRIVER=mysql + export ORM_SOURCE="beego:test@tcp(localhost:23306)/orm_test?charset=utf8" + go test -v github.com/beego/beego/v2/client/orm + docker-compose -f scripts/orm_docker_compose.yaml down + +test-orm-pgsql: ## Run ORM unit tests on postgresql. + docker-compose -f scripts/orm_docker_compose.yaml up -d + export ORM_DRIVER=postgres + export ORM_SOURCE="user=postgres password=postgres dbname=orm_test sslmode=disable" + go test -v github.com/beego/beego/v2/client/orm + docker-compose -f scripts/orm_docker_compose.yaml down + +test-orm-tidb: ## Run ORM unit tests on tidb. + docker-compose -f scripts/orm_docker_compose.yaml up -d + export ORM_DRIVER=tidb + export ORM_SOURCE="memory://test/test" + go test -v github.com/beego/beego/v2/client/orm + docker-compose -f scripts/orm_docker_compose.yaml down + +.PHONY: test-orm-all +test-orm-all: test-orm-mysql5 test-orm-mysql8 test-orm-pgsql test-orm-tidb diff --git a/adapter/context/input.go b/adapter/context/input.go index ac3e0c72..def81bf8 100644 --- a/adapter/context/input.go +++ b/adapter/context/input.go @@ -94,7 +94,7 @@ func (input *BeegoInput) IsHead() bool { return (*context.BeegoInput)(input).IsHead() } -// IsOptions Is this a OPTIONS method request? +// IsOptions Is this an OPTIONS method request? func (input *BeegoInput) IsOptions() bool { return (*context.BeegoInput)(input).IsOptions() } diff --git a/adapter/orm/orm_conds.go b/adapter/orm/orm_conds.go index 387caac2..4a713fcd 100644 --- a/adapter/orm/orm_conds.go +++ b/adapter/orm/orm_conds.go @@ -52,7 +52,7 @@ func (c *Condition) AndCond(cond *Condition) *Condition { return (*Condition)((*orm.Condition)(c).AndCond((*orm.Condition)(cond))) } -// AndNotCond combine a AND NOT condition to current condition +// AndNotCond combine an AND NOT condition to current condition func (c *Condition) AndNotCond(cond *Condition) *Condition { return (*Condition)((*orm.Condition)(c).AndNotCond((*orm.Condition)(cond))) } @@ -67,12 +67,12 @@ func (c Condition) OrNot(expr string, args ...interface{}) *Condition { return (*Condition)((orm.Condition)(c).OrNot(expr, args...)) } -// OrCond combine a OR condition to current condition +// OrCond combine an OR condition to current condition func (c *Condition) OrCond(cond *Condition) *Condition { return (*Condition)((*orm.Condition)(c).OrCond((*orm.Condition)(cond))) } -// OrNotCond combine a OR NOT condition to current condition +// OrNotCond combine an OR NOT condition to current condition func (c *Condition) OrNotCond(cond *Condition) *Condition { return (*Condition)((*orm.Condition)(c).OrNotCond((*orm.Condition)(cond))) } diff --git a/client/httplib/error_code.go b/client/httplib/error_code.go index f87041e4..43a68186 100644 --- a/client/httplib/error_code.go +++ b/client/httplib/error_code.go @@ -19,17 +19,17 @@ import ( ) var InvalidUrl = berror.DefineCode(4001001, moduleName, "InvalidUrl", ` -You pass a invalid url to httplib module. Please check your url, be careful about special character. +You pass an invalid url to httplib module. Please check your url, be careful about special character. `) var InvalidUrlProtocolVersion = berror.DefineCode(4001002, moduleName, "InvalidUrlProtocolVersion", ` -You pass a invalid protocol version. In practice, we use HTTP/1.0, HTTP/1.1, HTTP/1.2 +You pass an invalid protocol version. In practice, we use HTTP/1.0, HTTP/1.1, HTTP/1.2 But something like HTTP/3.2 is valid for client, and the major version is 3, minor version is 2. but you must confirm that server support those abnormal protocol version. `) var UnsupportedBodyType = berror.DefineCode(4001003, moduleName, "UnsupportedBodyType", ` -You use a invalid data as request body. +You use an invalid data as request body. For now, we only support type string and byte[]. `) diff --git a/client/httplib/httplib.go b/client/httplib/httplib.go index 147f595b..a9347395 100644 --- a/client/httplib/httplib.go +++ b/client/httplib/httplib.go @@ -112,7 +112,7 @@ func Head(url string) *BeegoHTTPRequest { return NewBeegoRequest(url, "HEAD") } -// BeegoHTTPRequest provides more useful methods than http.Request for requesting a url. +// BeegoHTTPRequest provides more useful methods than http.Request for requesting an url. type BeegoHTTPRequest struct { url string req *http.Request diff --git a/client/orm/db.go b/client/orm/db.go index 08047a04..cbaa81ad 100644 --- a/client/orm/db.go +++ b/client/orm/db.go @@ -1111,7 +1111,7 @@ func (d *dbBase) ReadBatch(ctx context.Context, q dbQuerier, qs *querySet, mi *m ind.Set(mind) } else { if cnt == 0 { - // you can use a empty & caped container list + // you can use an empty & caped container list // orm will not replace it if ind.Len() != 0 { // if container is not empty @@ -1135,7 +1135,7 @@ func (d *dbBase) ReadBatch(ctx context.Context, q dbQuerier, qs *querySet, mi *m ind.Set(slice) } else { // when a result is empty and container is nil - // to set a empty container + // to set an empty container if ind.IsNil() { ind.Set(reflect.MakeSlice(ind.Type(), 0, 0)) } diff --git a/client/orm/db_mysql.go b/client/orm/db_mysql.go index 5b3333e0..75d24b2a 100644 --- a/client/orm/db_mysql.go +++ b/client/orm/db_mysql.go @@ -155,7 +155,7 @@ func (d *dbBaseMysql) InsertOrUpdate(ctx context.Context, q dbQuerier, mi *model if isMulti { qmarks = strings.Repeat(qmarks+"), (", multi-1) + qmarks } - // conflitValue maybe is a int,can`t use fmt.Sprintf + // conflitValue maybe is an int,can`t use fmt.Sprintf query := fmt.Sprintf("INSERT INTO %s%s%s (%s%s%s) VALUES (%s) %s "+qupdates, Q, mi.table, Q, Q, columns, Q, qmarks, iouStr) d.ins.ReplaceMarks(&query) diff --git a/client/orm/orm_conds.go b/client/orm/orm_conds.go index 7d6eabe2..9946e595 100644 --- a/client/orm/orm_conds.go +++ b/client/orm/orm_conds.go @@ -90,7 +90,7 @@ func (c *Condition) AndCond(cond *Condition) *Condition { return c } -// AndNotCond combine a AND NOT condition to current condition +// AndNotCond combine an AND NOT condition to current condition func (c *Condition) AndNotCond(cond *Condition) *Condition { c = c.clone() if c == cond { @@ -121,7 +121,7 @@ func (c Condition) OrNot(expr string, args ...interface{}) *Condition { return &c } -// OrCond combine a OR condition to current condition +// OrCond combine an OR condition to current condition func (c *Condition) OrCond(cond *Condition) *Condition { c = c.clone() if c == cond { @@ -133,7 +133,7 @@ func (c *Condition) OrCond(cond *Condition) *Condition { return c } -// OrNotCond combine a OR NOT condition to current condition +// OrNotCond combine an OR NOT condition to current condition func (c *Condition) OrNotCond(cond *Condition) *Condition { c = c.clone() if c == cond { diff --git a/client/orm/orm_queryset.go b/client/orm/orm_queryset.go index 9f7b8441..82325899 100644 --- a/client/orm/orm_queryset.go +++ b/client/orm/orm_queryset.go @@ -257,7 +257,7 @@ func (o *querySet) DeleteWithCtx(ctx context.Context) (int64, error) { return o.orm.alias.DbBaser.DeleteBatch(ctx, o.orm.db, o, o.mi, o.cond, o.orm.alias.TZ) } -// return a insert queryer. +// return an insert queryer. // it can be used in times. // example: // i,err := sq.PrepareInsert() diff --git a/client/orm/types.go b/client/orm/types.go index 145f2897..df50a500 100644 --- a/client/orm/types.go +++ b/client/orm/types.go @@ -405,7 +405,7 @@ type QuerySeter interface { // //delete two user who's name is testing1 or testing2 Delete() (int64, error) DeleteWithCtx(context.Context) (int64, error) - // return a insert queryer. + // return an insert queryer. // it can be used in times. // example: // i,err := sq.PrepareInsert() diff --git a/core/config/ini.go b/core/config/ini.go index e3a395e5..d4dea2e3 100644 --- a/core/config/ini.go +++ b/core/config/ini.go @@ -98,7 +98,7 @@ func (ini *IniConfig) parseData(dir string, data []byte) (*IniConfigContainer, e break } - // It might be a good idea to throw a error on all unknonw errors? + // It might be a good idea to throw an error on all unknonw errors? if _, ok := err.(*os.PathError); ok { return nil, err } diff --git a/core/logs/es/es.go b/core/logs/es/es.go index 2073ab3d..a07ee83c 100644 --- a/core/logs/es/es.go +++ b/core/logs/es/es.go @@ -105,11 +105,11 @@ func (el *esLogger) WriteMsg(lm *logs.LogMsg) error { return err } -// Destroy is a empty method +// Destroy is an empty method func (el *esLogger) Destroy() { } -// Flush is a empty method +// Flush is an empty method func (el *esLogger) Flush() { } diff --git a/scripts/orm_docker_compose.yaml b/scripts/orm_docker_compose.yaml new file mode 100644 index 00000000..0ccf93d0 --- /dev/null +++ b/scripts/orm_docker_compose.yaml @@ -0,0 +1,124 @@ +# Copyright 2022 +# +# 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. + +version: "3.8" +services: + # mysql5.7 + mysql5: + container_name: "beego-mysql5" + image: mysql:5.7.30 + ports: + - "13306:3306" + environment: + - MYSQL_ROOT_PASSWORD=1q2w3e + - MYSQL_DATABASE=orm_test + - MYSQL_USER=beego + - MYSQL_PASSWORD=test + + # mysql8.0 + mysql8: + container_name: "beego-mysql8" + image: mysql:8.0 + ports: + - "23306:3306" + environment: + - MYSQL_ROOT_PASSWORD=1q2w3e + - MYSQL_DATABASE=orm_test + - MYSQL_USER=beego + - MYSQL_PASSWORD=test + + # postgresql + postgresql: + container_name: "beego-postgresql" + image: bitnami/postgresql:latest + ports: + - "5432:5432" + environment: + - POSTGRES_USER=postgres + - POSTGRES_PASSWORD=postgres + - POSTGRES_DB=orm_test + + # tidb + pd0: + image: pingcap/pd:latest + ports: + - "2379:2379" + volumes: + - ./config/pd.toml:/pd.toml:ro + - ./data:/data + - ./logs:/logs + command: + - --name=pd0 + - --client-urls=http://0.0.0.0:2379 + - --peer-urls=http://0.0.0.0:2380 + - --advertise-client-urls=http://pd0:2379 + - --advertise-peer-urls=http://pd0:2380 + - --initial-cluster=pd0=http://pd0:2380 + - --data-dir=/data/pd0 + - --config=/pd.toml + - --log-file=/logs/pd0.log + restart: on-failure + + tikv0: + image: pingcap/tikv:latest + volumes: + - ./config/tikv.toml:/tikv.toml:ro + - ./data:/data + - ./logs:/logs + command: + - --addr=0.0.0.0:20160 + - --advertise-addr=tikv0:20160 + - --data-dir=/data/tikv0 + - --pd=pd0:2379 + - --config=/tikv.toml + - --log-file=/logs/tikv0.log + depends_on: + - "pd0" + restart: on-failure + + tikv1: + image: pingcap/tikv:latest + volumes: + - ./config/tikv.toml:/tikv.toml:ro + - ./data:/data + - ./logs:/logs + command: + - --addr=0.0.0.0:20160 + - --advertise-addr=tikv1:20160 + - --data-dir=/data/tikv1 + - --pd=pd0:2379 + - --config=/tikv.toml + - --log-file=/logs/tikv1.log + depends_on: + - "pd0" + restart: on-failure + + tidb: + image: pingcap/tidb:latest + ports: + - "4000:4000" + - "10080:10080" + volumes: + - ./config/tidb.toml:/tidb.toml:ro + - ./logs:/logs + command: + - --store=tikv + - --path=pd0:2379 + - --config=/tidb.toml + - --log-file=/logs/tidb.log + - --advertise-address=tidb + depends_on: + - "tikv0" + - "tikv1" + restart: on-failure diff --git a/server/web/captcha/siprng.go b/server/web/captcha/siprng.go index 5e256cf9..4fdf3143 100644 --- a/server/web/captcha/siprng.go +++ b/server/web/captcha/siprng.go @@ -27,7 +27,7 @@ type siprng struct { k0, k1, ctr uint64 } -// siphash implements SipHash-2-4, accepting a uint64 as a message. +// siphash implements SipHash-2-4, accepting an uint64 as a message. func siphash(k0, k1, m uint64) uint64 { // Initialization. v0 := k0 ^ 0x736f6d6570736575 diff --git a/server/web/context/input.go b/server/web/context/input.go index 241ef8bc..dfb14dfb 100644 --- a/server/web/context/input.go +++ b/server/web/context/input.go @@ -153,7 +153,7 @@ func (input *BeegoInput) IsHead() bool { return input.Is("HEAD") } -// IsOptions Is this a OPTIONS method request? +// IsOptions Is this an OPTIONS method request? func (input *BeegoInput) IsOptions() bool { return input.Is("OPTIONS") } diff --git a/server/web/router.go b/server/web/router.go index e37da0b7..1536bae4 100644 --- a/server/web/router.go +++ b/server/web/router.go @@ -15,8 +15,10 @@ package web import ( + "bytes" "errors" "fmt" + "io" "net/http" "path" "reflect" @@ -211,6 +213,7 @@ func (p *ControllerRegister) Init() { // Add controller handler and pattern rules to ControllerRegister. // usage: +// // default methods is the same name as method // Add("/user",&UserController{}) // Add("/api/list",&RestController{},"*:ListFood") @@ -348,9 +351,10 @@ func (p *ControllerRegister) Include(cList ...ControllerInterface) { // GetContext returns a context from pool, so usually you should remember to call Reset function to clean the context // And don't forget to give back context to pool // example: -// ctx := p.GetContext() -// ctx.Reset(w, q) -// defer p.GiveBackContext(ctx) +// +// ctx := p.GetContext() +// ctx.Reset(w, q) +// defer p.GiveBackContext(ctx) func (p *ControllerRegister) GetContext() *beecontext.Context { return p.pool.Get().(*beecontext.Context) } @@ -362,14 +366,16 @@ func (p *ControllerRegister) GiveBackContext(ctx *beecontext.Context) { // CtrlGet add get method // usage: -// type MyController struct { -// web.Controller -// } -// func (m MyController) Ping() { -// m.Ctx.Output.Body([]byte("hello world")) -// } // -// CtrlGet("/api/:id", MyController.Ping) +// type MyController struct { +// web.Controller +// } +// func (m MyController) Ping() { +// m.Ctx.Output.Body([]byte("hello world")) +// } +// +// CtrlGet("/api/:id", MyController.Ping) +// // If the receiver of function Ping is pointer, you should use CtrlGet("/api/:id", (*MyController).Ping) func (p *ControllerRegister) CtrlGet(pattern string, f interface{}) { p.AddRouterMethod(http.MethodGet, pattern, f) @@ -377,14 +383,16 @@ func (p *ControllerRegister) CtrlGet(pattern string, f interface{}) { // CtrlPost add post method // usage: -// type MyController struct { -// web.Controller -// } -// func (m MyController) Ping() { -// m.Ctx.Output.Body([]byte("hello world")) -// } // -// CtrlPost("/api/:id", MyController.Ping) +// type MyController struct { +// web.Controller +// } +// func (m MyController) Ping() { +// m.Ctx.Output.Body([]byte("hello world")) +// } +// +// CtrlPost("/api/:id", MyController.Ping) +// // If the receiver of function Ping is pointer, you should use CtrlPost("/api/:id", (*MyController).Ping) func (p *ControllerRegister) CtrlPost(pattern string, f interface{}) { p.AddRouterMethod(http.MethodPost, pattern, f) @@ -392,14 +400,16 @@ func (p *ControllerRegister) CtrlPost(pattern string, f interface{}) { // CtrlHead add head method // usage: -// type MyController struct { -// web.Controller -// } -// func (m MyController) Ping() { -// m.Ctx.Output.Body([]byte("hello world")) -// } // -// CtrlHead("/api/:id", MyController.Ping) +// type MyController struct { +// web.Controller +// } +// func (m MyController) Ping() { +// m.Ctx.Output.Body([]byte("hello world")) +// } +// +// CtrlHead("/api/:id", MyController.Ping) +// // If the receiver of function Ping is pointer, you should use CtrlHead("/api/:id", (*MyController).Ping) func (p *ControllerRegister) CtrlHead(pattern string, f interface{}) { p.AddRouterMethod(http.MethodHead, pattern, f) @@ -422,70 +432,75 @@ func (p *ControllerRegister) CtrlPut(pattern string, f interface{}) { // CtrlPatch add patch method // usage: -// type MyController struct { -// web.Controller -// } -// func (m MyController) Ping() { -// m.Ctx.Output.Body([]byte("hello world")) -// } // -// CtrlPatch("/api/:id", MyController.Ping) +// type MyController struct { +// web.Controller +// } +// func (m MyController) Ping() { +// m.Ctx.Output.Body([]byte("hello world")) +// } +// +// CtrlPatch("/api/:id", MyController.Ping) func (p *ControllerRegister) CtrlPatch(pattern string, f interface{}) { p.AddRouterMethod(http.MethodPatch, pattern, f) } // CtrlDelete add delete method // usage: -// type MyController struct { -// web.Controller -// } -// func (m MyController) Ping() { -// m.Ctx.Output.Body([]byte("hello world")) -// } // -// CtrlDelete("/api/:id", MyController.Ping) +// type MyController struct { +// web.Controller +// } +// func (m MyController) Ping() { +// m.Ctx.Output.Body([]byte("hello world")) +// } +// +// CtrlDelete("/api/:id", MyController.Ping) func (p *ControllerRegister) CtrlDelete(pattern string, f interface{}) { p.AddRouterMethod(http.MethodDelete, pattern, f) } // CtrlOptions add options method // usage: -// type MyController struct { -// web.Controller -// } -// func (m MyController) Ping() { -// m.Ctx.Output.Body([]byte("hello world")) -// } // -// CtrlOptions("/api/:id", MyController.Ping) +// type MyController struct { +// web.Controller +// } +// func (m MyController) Ping() { +// m.Ctx.Output.Body([]byte("hello world")) +// } +// +// CtrlOptions("/api/:id", MyController.Ping) func (p *ControllerRegister) CtrlOptions(pattern string, f interface{}) { p.AddRouterMethod(http.MethodOptions, pattern, f) } // CtrlAny add all method // usage: -// type MyController struct { -// web.Controller -// } -// func (m MyController) Ping() { -// m.Ctx.Output.Body([]byte("hello world")) -// } // -// CtrlAny("/api/:id", MyController.Ping) +// type MyController struct { +// web.Controller +// } +// func (m MyController) Ping() { +// m.Ctx.Output.Body([]byte("hello world")) +// } +// +// CtrlAny("/api/:id", MyController.Ping) func (p *ControllerRegister) CtrlAny(pattern string, f interface{}) { p.AddRouterMethod("*", pattern, f) } // AddRouterMethod add http method router // usage: -// type MyController struct { -// web.Controller -// } -// func (m MyController) Ping() { -// m.Ctx.Output.Body([]byte("hello world")) -// } // -// AddRouterMethod("get","/api/:id", MyController.Ping) +// type MyController struct { +// web.Controller +// } +// func (m MyController) Ping() { +// m.Ctx.Output.Body([]byte("hello world")) +// } +// +// AddRouterMethod("get","/api/:id", MyController.Ping) func (p *ControllerRegister) AddRouterMethod(httpMethod, pattern string, f interface{}) { httpMethod = p.getUpperMethodString(httpMethod) ct, methodName := getReflectTypeAndMethod(f) @@ -624,81 +639,90 @@ type HandleFunc func(ctx *beecontext.Context) // Get add get method // usage: -// Get("/", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) +// +// Get("/", func(ctx *context.Context){ +// ctx.Output.Body("hello world") +// }) func (p *ControllerRegister) Get(pattern string, f HandleFunc) { p.AddMethod("get", pattern, f) } // Post add post method // usage: -// Post("/api", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) +// +// Post("/api", func(ctx *context.Context){ +// ctx.Output.Body("hello world") +// }) func (p *ControllerRegister) Post(pattern string, f HandleFunc) { p.AddMethod("post", pattern, f) } // Put add put method // usage: -// Put("/api/:id", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) +// +// Put("/api/:id", func(ctx *context.Context){ +// ctx.Output.Body("hello world") +// }) func (p *ControllerRegister) Put(pattern string, f HandleFunc) { p.AddMethod("put", pattern, f) } // Delete add delete method // usage: -// Delete("/api/:id", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) +// +// Delete("/api/:id", func(ctx *context.Context){ +// ctx.Output.Body("hello world") +// }) func (p *ControllerRegister) Delete(pattern string, f HandleFunc) { p.AddMethod("delete", pattern, f) } // Head add head method // usage: -// Head("/api/:id", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) +// +// Head("/api/:id", func(ctx *context.Context){ +// ctx.Output.Body("hello world") +// }) func (p *ControllerRegister) Head(pattern string, f HandleFunc) { p.AddMethod("head", pattern, f) } // Patch add patch method // usage: -// Patch("/api/:id", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) +// +// Patch("/api/:id", func(ctx *context.Context){ +// ctx.Output.Body("hello world") +// }) func (p *ControllerRegister) Patch(pattern string, f HandleFunc) { p.AddMethod("patch", pattern, f) } // Options add options method // usage: -// Options("/api/:id", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) +// +// Options("/api/:id", func(ctx *context.Context){ +// ctx.Output.Body("hello world") +// }) func (p *ControllerRegister) Options(pattern string, f HandleFunc) { p.AddMethod("options", pattern, f) } // Any add all method // usage: -// Any("/api/:id", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) +// +// Any("/api/:id", func(ctx *context.Context){ +// ctx.Output.Body("hello world") +// }) func (p *ControllerRegister) Any(pattern string, f HandleFunc) { p.AddMethod("*", pattern, f) } // AddMethod add http method router // usage: -// AddMethod("get","/api/:id", func(ctx *context.Context){ -// ctx.Output.Body("hello world") -// }) +// +// AddMethod("get","/api/:id", func(ctx *context.Context){ +// ctx.Output.Body("hello world") +// }) func (p *ControllerRegister) AddMethod(method, pattern string, f HandleFunc) { method = p.getUpperMethodString(method) @@ -772,8 +796,8 @@ func (p *ControllerRegister) addAutoPrefixMethod(prefix, controllerName, methodN // InsertFilter Add a FilterFunc with pattern rule and action constant. // params is for: -// 1. setting the returnOnOutput value (false allows multiple filters to execute) -// 2. determining whether or not params need to be reset. +// 1. setting the returnOnOutput value (false allows multiple filters to execute) +// 2. determining whether or not params need to be reset. func (p *ControllerRegister) InsertFilter(pattern string, pos int, filter FilterFunc, opts ...FilterOpt) error { opts = append(opts, WithCaseSensitive(p.cfg.RouterCaseSensitive)) mr := newFilterRouter(pattern, filter, opts...) @@ -784,13 +808,14 @@ func (p *ControllerRegister) InsertFilter(pattern string, pos int, filter Filter // but it will using chainRoot.filterFunc as input to build a new filterFunc // for example, assume that chainRoot is funcA // and we add new FilterChain -// fc := func(next) { -// return func(ctx) { -// // do something -// next(ctx) -// // do something -// } -// } +// +// fc := func(next) { +// return func(ctx) { +// // do something +// next(ctx) +// // do something +// } +// } func (p *ControllerRegister) InsertFilterChain(pattern string, chain FilterChain, opts ...FilterOpt) { opts = append([]FilterOpt{WithCaseSensitive(p.cfg.RouterCaseSensitive)}, opts...) p.filterChains = append(p.filterChains, filterChainConfig{ @@ -1025,10 +1050,14 @@ func (p *ControllerRegister) serveHttp(ctx *beecontext.Context) { } if r.Method != http.MethodGet && r.Method != http.MethodHead { + body := ctx.Input.Context.Request.Body + if body == nil { + body = io.NopCloser(bytes.NewReader([]byte{})) + } if ctx.Input.IsUpload() { ctx.Input.Context.Request.Body = http.MaxBytesReader(ctx.Input.Context.ResponseWriter, - ctx.Input.Context.Request.Body, + body, p.cfg.MaxUploadSize) } else if p.cfg.CopyRequestBody { // connection will close if the incoming data are larger (RFC 7231, 6.5.11) @@ -1040,7 +1069,7 @@ func (p *ControllerRegister) serveHttp(ctx *beecontext.Context) { ctx.Input.CopyBody(p.cfg.MaxMemory) } else { ctx.Input.Context.Request.Body = http.MaxBytesReader(ctx.Input.Context.ResponseWriter, - ctx.Input.Context.Request.Body, + body, p.cfg.MaxMemory) } diff --git a/server/web/session/sess_utils.go b/server/web/session/sess_utils.go index 23242d7a..b2649336 100644 --- a/server/web/session/sess_utils.go +++ b/server/web/session/sess_utils.go @@ -98,7 +98,7 @@ func encrypt(block cipher.Block, value []byte) ([]byte, error) { // decrypt decrypts a value using the given block in counter mode. // -// The value to be decrypted must be prepended by a initialization vector +// The value to be decrypted must be prepended by an initialization vector // (http://goo.gl/zF67k) with the length of the block size. func decrypt(block cipher.Block, value []byte) ([]byte, error) { size := block.BlockSize() diff --git a/server/web/template.go b/server/web/template.go index c683c565..715c992d 100644 --- a/server/web/template.go +++ b/server/web/template.go @@ -103,7 +103,7 @@ func init() { beegoTplFuncMap["lt"] = lt // < beegoTplFuncMap["ne"] = ne // != - beegoTplFuncMap["urlfor"] = URLFor // build a URL to match a Controller and it's method + beegoTplFuncMap["urlfor"] = URLFor // build an URL to match a Controller and it's method } // AddFuncMap let user to register a func in the template. diff --git a/task/task.go b/task/task.go index 7001b9ed..91b8d2f8 100644 --- a/task/task.go +++ b/task/task.go @@ -221,7 +221,7 @@ func (f optionFunc) apply(t *Task) { f(t) } -// TimeoutOption return a option to set timeout duration for task +// TimeoutOption return an option to set timeout duration for task func TimeoutOption(timeout time.Duration) Option { return optionFunc(func(t *Task) { t.Timeout = timeout