diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml
index 50e91510..ee981191 100644
--- a/.github/workflows/changelog.yml
+++ b/.github/workflows/changelog.yml
@@ -10,6 +10,9 @@ on:
branches:
- develop
+permissions:
+ contents: read
+
jobs:
changelog:
runs-on: ubuntu-latest
diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml
index 39901ce8..6e5f0122 100644
--- a/.github/workflows/golangci-lint.yml
+++ b/.github/workflows/golangci-lint.yml
@@ -11,8 +11,14 @@ on:
paths:
- "**/*.go"
- ".github/workflows/golangci-lint.yml"
+permissions:
+ contents: read
+
jobs:
lint:
+ permissions:
+ contents: read # for actions/checkout to fetch code
+ pull-requests: read # for golangci/golangci-lint-action to fetch pull requests
runs-on: ubuntu-latest
steps:
- name: Checkout codebase
diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml
index 66c8ce4a..9d19affc 100644
--- a/.github/workflows/stale.yml
+++ b/.github/workflows/stale.yml
@@ -4,13 +4,19 @@ on:
schedule:
- cron: "30 1 * * *"
+permissions:
+ contents: read
+
jobs:
stale:
+ permissions:
+ issues: write # for actions/stale to close stale issues
+ pull-requests: write # for actions/stale to close stale PRs
runs-on: ubuntu-latest
steps:
- - uses: actions/stale@v4
+ - uses: actions/stale@v5
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'This issue is inactive for a long time.'
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 7ebaddd1..c9d4cc70 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -20,12 +20,15 @@ on:
- "go.sum"
- ".github/workflows/test.yml"
+permissions:
+ contents: read
+
jobs:
test:
strategy:
fail-fast: false
matrix:
- go-version: [1.14, 1.15, 1.16]
+ go-version: [1.18]
runs-on: ubuntu-latest
services:
redis:
@@ -52,7 +55,7 @@ jobs:
steps:
- name: Set up Go
- uses: actions/setup-go@v2
+ uses: actions/setup-go@v3
with:
go-version: ${{ matrix.go-version }}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 72eb9904..0075ddcf 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,7 +1,21 @@
# developing
-- [https://github.com/beego/beego/pull/4845](https://github.com/beego/beego/pull/4845)
-# v2.0.2-beta.1
+# v2.0.3
+- [upgrade redisgo to v1.8.8](https://github.com/beego/beego/pull/4872)
+- [fix prometheus CVE-2022-21698](https://github.com/beego/beego/pull/4878)
+- [upgrade to Go 1.18](https://github.com/beego/beego/pull/4896)
+- [make `PatternLogFormatter` handling the arguments](https://github.com/beego/beego/pull/4914/files)
+- [Add httplib OpenTelemetry Filter](https://github.com/beego/beego/pull/4888, https://github.com/beego/beego/pull/4915)
+- [Support NewBeegoRequestWithCtx in httplib](https://github.com/beego/beego/pull/4895)
+- [Support lifecycle callback](https://github.com/beego/beego/pull/4918)
+- [Append column comments to create table sentence when using postgres](https://github.com/beego/beego/pull/4940)
+- [logs: multiFileLogWriter uses incorrect formatter](https://github.com/beego/beego/pull/4943)
+- [fix issue 4946 CVE-2022-31259](https://github.com/beego/beego/pull/4954)
+
+# v2.0.2
+See v2.0.2-beta.1
+- [fix bug: etcd should use etcd as adapter name](https://github.com/beego/beego/pull/4845)
+# v2.0.2-beta.1
- Add a custom option for whether to escape HTML special characters when processing http request parameters. [4701](https://github.com/beego/beego/pull/4701)
- Always set the response status in the CustomAbort function. [4686](https://github.com/beego/beego/pull/4686)
- Add template functions eq,lt to support uint and int compare. [4607](https://github.com/beego/beego/pull/4607)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 83a7eaea..59cc5682 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -53,9 +53,13 @@ export SSDB_ADDR="192.168.0.105:8888"
### Pull requests
-First of all. beego follow the gitflow. So please send you pull request to **develop** branch. We will close the pull
+First, beego follow the gitflow. So please send you pull request to **develop** branch. We will close the pull
request to master branch.
+By the way, please don't forget update the `CHANGELOG.md` before you send pull request.
+You can just add your pull request following 'developing' section in `CHANGELOG.md`.
+We'll release them in the next Beego version.
+
We are always happy to receive pull requests, and do our best to review them as fast as possible. Not sure if that typo
is worth a pull request? Do it! We will appreciate it.
@@ -86,4 +90,4 @@ Please take a moment to check that an issue doesn't already exist documenting yo
If it does, it never hurts to add a quick "+1" or "I have this problem too". This will help prioritize the most common
problems and requests.
-Also, if you don't know how to use it. please make sure you have read through the docs in http://beego.me/docs
+Also, if you don't know how to use it. please make sure you have read through the docs in http://beego.vip/docs
diff --git a/README.md b/README.md
index 0133510f..d361f66e 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,8 @@ Beego is composed of four parts:
## Quick Start
-[Official website](http://beego.me)
+[Official website](http://beego.vip)
+[中文新版文档网站](https://beego.gocn.vip)
[Example](https://github.com/beego/beego-example)
@@ -87,9 +88,9 @@ Congratulations! You've just built your first **beego** app.
## Community
-* [http://beego.me/community](http://beego.me/community)
+* [http://beego.vip/community](http://beego.vip/community)
* Welcome to join us in Slack: [https://beego.slack.com invite](https://join.slack.com/t/beego/shared_invite/zt-fqlfjaxs-_CRmiITCSbEqQG9NeBqXKA),
-* QQ Group Group ID:523992905
+* QQ Group ID:523992905
* [Contribution Guide](https://github.com/beego/beedoc/blob/master/en-US/intro/contributing.md).
## License
diff --git a/adapter/cache/cache.go b/adapter/cache/cache.go
index 1291568c..0465e4c1 100644
--- a/adapter/cache/cache.go
+++ b/adapter/cache/cache.go
@@ -28,7 +28,7 @@
// bm.IsExist("astaxie")
// bm.Delete("astaxie")
//
-// more docs http://beego.me/docs/module/cache.md
+// more docs http://beego.vip/docs/module/cache.md
package cache
import (
diff --git a/adapter/cache/memcache/memcache.go b/adapter/cache/memcache/memcache.go
index 37b4b282..fd4a8bbf 100644
--- a/adapter/cache/memcache/memcache.go
+++ b/adapter/cache/memcache/memcache.go
@@ -26,7 +26,7 @@
//
// bm, err := cache.NewCache("memcache", `{"conn":"127.0.0.1:11211"}`)
//
-// more docs http://beego.me/docs/module/cache.md
+// more docs http://beego.vip/docs/module/cache.md
package memcache
import (
diff --git a/adapter/cache/redis/redis.go b/adapter/cache/redis/redis.go
index a511f53a..d95e10f6 100644
--- a/adapter/cache/redis/redis.go
+++ b/adapter/cache/redis/redis.go
@@ -26,7 +26,7 @@
//
// bm, err := cache.NewCache("redis", `{"conn":"127.0.0.1:11211"}`)
//
-// more docs http://beego.me/docs/module/cache.md
+// more docs http://beego.vip/docs/module/cache.md
package redis
import (
diff --git a/adapter/config/config.go b/adapter/config/config.go
index bf2496fc..93be0961 100644
--- a/adapter/config/config.go
+++ b/adapter/config/config.go
@@ -37,7 +37,7 @@
// cnf.DIY(key string) (interface{}, error)
// cnf.GetSection(section string) (map[string]string, error)
// cnf.SaveConfigFile(filename string) error
-// More docs http://beego.me/docs/module/config.md
+// More docs http://beego.vip/docs/module/config.md
package config
import (
diff --git a/adapter/config/xml/xml.go b/adapter/config/xml/xml.go
index 8c623033..9514624d 100644
--- a/adapter/config/xml/xml.go
+++ b/adapter/config/xml/xml.go
@@ -26,7 +26,7 @@
//
// cnf, err := config.NewConfig("xml", "config.xml")
//
-// More docs http://beego.me/docs/module/config.md
+// More docs http://beego.vip/docs/module/config.md
package xml
import (
diff --git a/adapter/config/yaml/yaml.go b/adapter/config/yaml/yaml.go
index 538f1178..f3e72380 100644
--- a/adapter/config/yaml/yaml.go
+++ b/adapter/config/yaml/yaml.go
@@ -26,7 +26,7 @@
//
// cnf, err := config.NewConfig("yaml", "config.yaml")
//
-// More docs http://beego.me/docs/module/config.md
+// More docs http://beego.vip/docs/module/config.md
package yaml
import (
diff --git a/adapter/context/context.go b/adapter/context/context.go
index bb8f7cd9..c0259139 100644
--- a/adapter/context/context.go
+++ b/adapter/context/context.go
@@ -19,7 +19,7 @@
//
// ctx := context.Context{Request:req,ResponseWriter:rw}
//
-// more docs http://beego.me/docs/module/context.md
+// more docs http://beego.vip/docs/module/context.md
package context
import (
diff --git a/adapter/httplib/httplib.go b/adapter/httplib/httplib.go
index 005eee0f..fecd8f19 100644
--- a/adapter/httplib/httplib.go
+++ b/adapter/httplib/httplib.go
@@ -17,7 +17,7 @@
//
// import "github.com/beego/beego/v2/client/httplib"
//
-// b := httplib.Post("http://beego.me/")
+// b := httplib.Post("http://beego.vip/")
// b.Param("username","astaxie")
// b.Param("password","123456")
// b.PostFile("uploadfile1", "httplib.pdf")
@@ -28,7 +28,7 @@
// }
// fmt.Println(str)
//
-// more docs http://beego.me/docs/module/httplib.md
+// more docs http://beego.vip/docs/module/httplib.md
package httplib
import (
diff --git a/adapter/logs/log.go b/adapter/logs/log.go
index d53cc2ce..fc0fdc62 100644
--- a/adapter/logs/log.go
+++ b/adapter/logs/log.go
@@ -30,7 +30,7 @@
// log.Debug("debug")
// log.Critical("critical")
//
-// more docs http://beego.me/docs/module/logs.md
+// more docs http://beego.vip/docs/module/logs.md
package logs
import (
diff --git a/adapter/namespace.go b/adapter/namespace.go
index 4beda252..9c3dcbb9 100644
--- a/adapter/namespace.go
+++ b/adapter/namespace.go
@@ -51,7 +51,7 @@ func oldToNewLinkNs(params []LinkNamespace) []web.LinkNamespace {
// if cond return true can run this namespace, else can't
// usage:
// ns.Cond(func (ctx *context.Context) bool{
-// if ctx.Input.Domain() == "api.beego.me" {
+// if ctx.Input.Domain() == "api.beego.vip" {
// return true
// }
// return false
diff --git a/adapter/orm/orm.go b/adapter/orm/orm.go
index f3283fd4..fd3c3d25 100644
--- a/adapter/orm/orm.go
+++ b/adapter/orm/orm.go
@@ -50,7 +50,7 @@
// num, err = o.Delete(&u)
// }
//
-// more docs: http://beego.me/docs/mvc/model/overview.md
+// more docs: http://beego.vip/docs/mvc/model/overview.md
package orm
import (
diff --git a/adapter/session/couchbase/sess_couchbase.go b/adapter/session/couchbase/sess_couchbase.go
index 2dc4ce18..61f10af5 100644
--- a/adapter/session/couchbase/sess_couchbase.go
+++ b/adapter/session/couchbase/sess_couchbase.go
@@ -29,7 +29,7 @@
// go globalSessions.GC()
// }
//
-// more docs: http://beego.me/docs/module/session.md
+// more docs: http://beego.vip/docs/module/session.md
package couchbase
import (
diff --git a/adapter/session/memcache/sess_memcache.go b/adapter/session/memcache/sess_memcache.go
index 7cd8d733..12f33a58 100644
--- a/adapter/session/memcache/sess_memcache.go
+++ b/adapter/session/memcache/sess_memcache.go
@@ -29,7 +29,7 @@
// go globalSessions.GC()
// }
//
-// more docs: http://beego.me/docs/module/session.md
+// more docs: http://beego.vip/docs/module/session.md
package memcache
import (
diff --git a/adapter/session/mysql/sess_mysql.go b/adapter/session/mysql/sess_mysql.go
index 71c2d4a7..9355f89a 100644
--- a/adapter/session/mysql/sess_mysql.go
+++ b/adapter/session/mysql/sess_mysql.go
@@ -37,7 +37,7 @@
// go globalSessions.GC()
// }
//
-// more docs: http://beego.me/docs/module/session.md
+// more docs: http://beego.vip/docs/module/session.md
package mysql
import (
diff --git a/adapter/session/postgres/sess_postgresql.go b/adapter/session/postgres/sess_postgresql.go
index 5807d551..4a23ddb0 100644
--- a/adapter/session/postgres/sess_postgresql.go
+++ b/adapter/session/postgres/sess_postgresql.go
@@ -47,7 +47,7 @@
// go globalSessions.GC()
// }
//
-// more docs: http://beego.me/docs/module/session.md
+// more docs: http://beego.vip/docs/module/session.md
package postgres
import (
diff --git a/adapter/session/redis/sess_redis.go b/adapter/session/redis/sess_redis.go
index 220a59cd..ee861a0d 100644
--- a/adapter/session/redis/sess_redis.go
+++ b/adapter/session/redis/sess_redis.go
@@ -29,7 +29,7 @@
// go globalSessions.GC()
// }
//
-// more docs: http://beego.me/docs/module/session.md
+// more docs: http://beego.vip/docs/module/session.md
package redis
import (
diff --git a/adapter/session/redis_cluster/redis_cluster.go b/adapter/session/redis_cluster/redis_cluster.go
index 623d72cc..03df3637 100644
--- a/adapter/session/redis_cluster/redis_cluster.go
+++ b/adapter/session/redis_cluster/redis_cluster.go
@@ -29,7 +29,7 @@
// go globalSessions.GC()
// }
//
-// more docs: http://beego.me/docs/module/session.md
+// more docs: http://beego.vip/docs/module/session.md
package redis_cluster
import (
diff --git a/adapter/session/session.go b/adapter/session/session.go
index 703adbde..d3d16a08 100644
--- a/adapter/session/session.go
+++ b/adapter/session/session.go
@@ -24,7 +24,7 @@
// go globalSessions.GC()
// }
//
-// more docs: http://beego.me/docs/module/session.md
+// more docs: http://beego.vip/docs/module/session.md
package session
import (
diff --git a/adapter/templatefunc.go b/adapter/templatefunc.go
index c5574d32..ddfaaeff 100644
--- a/adapter/templatefunc.go
+++ b/adapter/templatefunc.go
@@ -106,7 +106,7 @@ func Htmlunquote(text string) string {
// /login?next=/
// /user/John%20Doe
//
-// more detail http://beego.me/docs/mvc/controller/urlbuilding.md
+// more detail http://beego.vip/docs/mvc/controller/urlbuilding.md
func URLFor(endpoint string, values ...interface{}) string {
return web.URLFor(endpoint, values...)
}
diff --git a/adapter/toolbox/healthcheck.go b/adapter/toolbox/healthcheck.go
index 9095053f..5a0e8708 100644
--- a/adapter/toolbox/healthcheck.go
+++ b/adapter/toolbox/healthcheck.go
@@ -27,7 +27,7 @@
//
// AddHealthCheck("database",&DatabaseCheck{})
//
-// more docs: http://beego.me/docs/module/toolbox.md
+// more docs: http://beego.vip/docs/module/toolbox.md
package toolbox
import (
diff --git a/adapter/utils/pagination/doc.go b/adapter/utils/pagination/doc.go
index 43ee78b6..bb3cbdd4 100644
--- a/adapter/utils/pagination/doc.go
+++ b/adapter/utils/pagination/doc.go
@@ -52,7 +52,7 @@ In your view templates:
See also
-http://beego.me/docs/mvc/view/page.md
+http://beego.vip/docs/mvc/view/page.md
*/
package pagination
diff --git a/adapter/validation/validation.go b/adapter/validation/validation.go
index eadd4361..e6dfde77 100644
--- a/adapter/validation/validation.go
+++ b/adapter/validation/validation.go
@@ -43,7 +43,7 @@
// }
// }
//
-// more info: http://beego.me/docs/mvc/controller/validation.md
+// more info: http://beego.vip/docs/mvc/controller/validation.md
package validation
import (
diff --git a/client/cache/cache.go b/client/cache/cache.go
index 87f7ba62..2f9dd9bd 100644
--- a/client/cache/cache.go
+++ b/client/cache/cache.go
@@ -28,7 +28,7 @@
// bm.IsExist("astaxie")
// bm.Delete("astaxie")
//
-// more docs http://beego.me/docs/module/cache.md
+// more docs http://beego.vip/docs/module/cache.md
package cache
import (
diff --git a/client/cache/memcache/memcache.go b/client/cache/memcache/memcache.go
index 90242bab..06cc7995 100644
--- a/client/cache/memcache/memcache.go
+++ b/client/cache/memcache/memcache.go
@@ -26,7 +26,7 @@
//
// bm, err := cache.NewCache("memcache", `{"conn":"127.0.0.1:11211"}`)
//
-// more docs http://beego.me/docs/module/cache.md
+// more docs http://beego.vip/docs/module/cache.md
package memcache
import (
diff --git a/client/cache/redis/redis.go b/client/cache/redis/redis.go
index bd244223..9462bcd8 100644
--- a/client/cache/redis/redis.go
+++ b/client/cache/redis/redis.go
@@ -26,7 +26,7 @@
//
// bm, err := cache.NewCache("redis", `{"conn":"127.0.0.1:11211"}`)
//
-// more docs http://beego.me/docs/module/cache.md
+// more docs http://beego.vip/docs/module/cache.md
package redis
import (
diff --git a/client/httplib/README.md b/client/httplib/README.md
index a5723c6d..b1145e7a 100644
--- a/client/httplib/README.md
+++ b/client/httplib/README.md
@@ -10,7 +10,7 @@ you can use Get to crawl data.
import "github.com/beego/beego/v2/client/httplib"
- str, err := httplib.Get("http://beego.me/").String()
+ str, err := httplib.Get("http://beego.vip/").String()
if err != nil {
// error
}
@@ -20,7 +20,7 @@ you can use Get to crawl data.
POST data to remote url
- req := httplib.Post("http://beego.me/")
+ req := httplib.Post("http://beego.vip/")
req.Param("username","astaxie")
req.Param("password","123456")
str, err := req.String()
@@ -38,20 +38,20 @@ The default timeout is `60` seconds, function prototype:
Example:
// GET
- httplib.Get("http://beego.me/").SetTimeout(100 * time.Second, 30 * time.Second)
+ httplib.Get("http://beego.vip/").SetTimeout(100 * time.Second, 30 * time.Second)
// POST
- httplib.Post("http://beego.me/").SetTimeout(100 * time.Second, 30 * time.Second)
+ httplib.Post("http://beego.vip/").SetTimeout(100 * time.Second, 30 * time.Second)
## Debug
If you want to debug the request info, set the debug on
- httplib.Get("http://beego.me/").Debug(true)
+ httplib.Get("http://beego.vip/").Debug(true)
## Set HTTP Basic Auth
- str, err := Get("http://beego.me/").SetBasicAuth("user", "passwd").String()
+ str, err := Get("http://beego.vip/").SetBasicAuth("user", "passwd").String()
if err != nil {
// error
}
@@ -69,7 +69,7 @@ More info about the `tls.Config` please visit http://golang.org/pkg/crypto/tls/#
some servers need to specify the protocol version of HTTP
- httplib.Get("http://beego.me/").SetProtocolVersion("HTTP/1.1")
+ httplib.Get("http://beego.vip/").SetProtocolVersion("HTTP/1.1")
## Set Cookie
@@ -78,13 +78,13 @@ some http request need setcookie. So set it like this:
cookie := &http.Cookie{}
cookie.Name = "username"
cookie.Value = "astaxie"
- httplib.Get("http://beego.me/").SetCookie(cookie)
+ httplib.Get("http://beego.vip/").SetCookie(cookie)
## Upload file
httplib support mutil file upload, use `req.PostFile()`
- req := httplib.Post("http://beego.me/")
+ req := httplib.Post("http://beego.vip/")
req.Param("username","astaxie")
req.PostFile("uploadfile1", "httplib.pdf")
str, err := req.String()
diff --git a/client/httplib/error_code.go b/client/httplib/error_code.go
index 177419ad..f87041e4 100644
--- a/client/httplib/error_code.go
+++ b/client/httplib/error_code.go
@@ -51,6 +51,10 @@ Sometimes you got JSON document and you want to make it as request body. So you
If you do this, you got this code. Instead, you should call Header to set Content-type and call Body to set body data.
`)
+var InvalidURLOrMethod = berror.DefineCode(4001007, moduleName, "InvalidURLOrMethod", `
+You pass invalid url or method to httplib module. Please check the url and method, be careful about special characters.
+`)
+
// start with 5 --------------------------------------------------------------------------
var CreateFormFileFailed = berror.DefineCode(5001001, moduleName, "CreateFormFileFailed", `
diff --git a/client/httplib/filter/opentelemetry/filter.go b/client/httplib/filter/opentelemetry/filter.go
new file mode 100644
index 00000000..cee1458d
--- /dev/null
+++ b/client/httplib/filter/opentelemetry/filter.go
@@ -0,0 +1,86 @@
+// Copyright 2021 beego
+//
+// 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 opentelemetry
+
+import (
+ "context"
+ "net/http"
+
+ "go.opentelemetry.io/otel"
+ "go.opentelemetry.io/otel/attribute"
+ "go.opentelemetry.io/otel/propagation"
+ "go.opentelemetry.io/otel/trace"
+
+ "github.com/beego/beego/v2/client/httplib"
+)
+
+type CustomSpanFunc func(span trace.Span, ctx context.Context, req *httplib.BeegoHTTPRequest, resp *http.Response, err error)
+
+type OtelFilterChainBuilder struct {
+ // TagURL true will tag span with url
+ tagURL bool
+ // CustomSpanFunc users are able to custom their span
+ customSpanFunc CustomSpanFunc
+}
+
+func NewOpenTelemetryFilter(tagURL bool, spanFunc CustomSpanFunc) *OtelFilterChainBuilder {
+ return &OtelFilterChainBuilder{
+ tagURL: tagURL,
+ customSpanFunc: spanFunc,
+ }
+}
+
+func (builder *OtelFilterChainBuilder) FilterChain(next httplib.Filter) httplib.Filter {
+ return func(ctx context.Context, req *httplib.BeegoHTTPRequest) (*http.Response, error) {
+ method := req.GetRequest().Method
+
+ operationName := method + "#" + req.GetRequest().URL.Path
+ spanCtx, span := otel.Tracer("beego").Start(ctx, operationName)
+ defer span.End()
+
+ otel.GetTextMapPropagator().Inject(spanCtx, propagation.HeaderCarrier(req.GetRequest().Header))
+
+ resp, err := next(spanCtx, req)
+
+ if resp != nil {
+ span.SetAttributes(attribute.Int("http.status_code", resp.StatusCode))
+ }
+ span.SetAttributes(attribute.String("http.method", method))
+ span.SetAttributes(attribute.String("peer.hostname", req.GetRequest().URL.Host))
+
+ span.SetAttributes(attribute.String("http.scheme", req.GetRequest().URL.Scheme))
+ span.SetAttributes(attribute.String("span.kind", "client"))
+ span.SetAttributes(attribute.String("component", "beego"))
+
+ if builder.tagURL {
+ span.SetAttributes(attribute.String("http.url", req.GetRequest().URL.String()))
+ }
+
+ if err != nil {
+ span.SetAttributes(attribute.Bool("error", true))
+ span.RecordError(err)
+ } else if resp != nil && !(resp.StatusCode < 300 && resp.StatusCode >= 200) {
+ span.SetAttributes(attribute.Bool("error", true))
+ }
+
+ span.SetAttributes(attribute.String("peer.address", req.GetRequest().RemoteAddr))
+ span.SetAttributes(attribute.String("http.proto", req.GetRequest().Proto))
+
+ if builder.customSpanFunc != nil {
+ builder.customSpanFunc(span, ctx, req, resp, err)
+ }
+ return resp, err
+ }
+}
diff --git a/client/httplib/filter/opentelemetry/filter_test.go b/client/httplib/filter/opentelemetry/filter_test.go
new file mode 100644
index 00000000..4949e375
--- /dev/null
+++ b/client/httplib/filter/opentelemetry/filter_test.go
@@ -0,0 +1,46 @@
+// Copyright 2021 beego
+//
+// 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 opentelemetry
+
+import (
+ "context"
+ "errors"
+ "net/http"
+ "testing"
+ "time"
+
+ "github.com/stretchr/testify/assert"
+
+ "github.com/beego/beego/v2/client/httplib"
+)
+
+func TestFilterChainBuilderFilterChain(t *testing.T) {
+ next := func(ctx context.Context, req *httplib.BeegoHTTPRequest) (*http.Response, error) {
+ time.Sleep(100 * time.Millisecond)
+ return &http.Response{
+ StatusCode: 404,
+ Body: http.NoBody,
+ }, errors.New("hello")
+ }
+ builder := NewOpenTelemetryFilter(true, nil)
+ filter := builder.FilterChain(next)
+ req := httplib.Get("https://github.com/notifications?query=repo%3Aastaxie%2Fbeego")
+ resp, err := filter(context.Background(), req)
+
+ defer resp.Body.Close()
+
+ assert.NotNil(t, resp)
+ assert.NotNil(t, err)
+}
diff --git a/client/httplib/httpclient.go b/client/httplib/httpclient.go
index c2a61fcf..524f8bbb 100644
--- a/client/httplib/httpclient.go
+++ b/client/httplib/httpclient.go
@@ -51,7 +51,7 @@ type HTTPStatusCarrier interface {
SetStatusCode(status int)
}
-// HttpHeaderCarrier If value implement HttpHeaderCarrier. http.Response.Header will pass to SetHeader
+// HTTPHeadersCarrier If value implement HttpHeaderCarrier. http.Response.Header will pass to SetHeader
type HTTPHeadersCarrier interface {
SetHeader(header map[string][]string)
}
diff --git a/client/httplib/httpclient_test.go b/client/httplib/httpclient_test.go
index d1de3828..1ab6d95f 100644
--- a/client/httplib/httpclient_test.go
+++ b/client/httplib/httpclient_test.go
@@ -25,7 +25,7 @@ import (
)
func TestNewClient(t *testing.T) {
- client, err := NewClient("test1", "http://beego.me", WithEnableCookie(true))
+ client, err := NewClient("test1", "http://beego.vip", WithEnableCookie(true))
assert.NoError(t, err)
assert.NotNil(t, client)
assert.Equal(t, true, client.Setting.EnableCookie)
@@ -204,7 +204,7 @@ func TestClientDelete(t *testing.T) {
}
func TestClientHead(t *testing.T) {
- client, err := NewClient("test", "http://beego.me")
+ client, err := NewClient("test", "http://beego.gocn.vip")
if err != nil {
t.Fatal(err)
}
diff --git a/client/httplib/httplib.go b/client/httplib/httplib.go
index 5be4598b..147f595b 100644
--- a/client/httplib/httplib.go
+++ b/client/httplib/httplib.go
@@ -17,7 +17,7 @@
//
// import "github.com/beego/beego/v2/client/httplib"
//
-// b := httplib.Post("http://beego.me/")
+// b := httplib.Post("http://beego.vip/")
// b.Param("username","astaxie")
// b.Param("password","123456")
// b.PostFile("uploadfile1", "httplib.pdf")
@@ -28,7 +28,7 @@
// }
// fmt.Println(str)
//
-// more docs http://beego.me/docs/module/httplib.md
+// more docs http://beego.vip/docs/module/httplib.md
package httplib
import (
@@ -67,26 +67,23 @@ var doRequestFilter = func(ctx context.Context, req *BeegoHTTPRequest) (*http.Re
// I think if we don't return error
// users are hard to check whether we create Beego request successfully
func NewBeegoRequest(rawurl, method string) *BeegoHTTPRequest {
- var resp http.Response
- u, err := url.Parse(rawurl)
+ return NewBeegoRequestWithCtx(context.Background(), rawurl, method)
+}
+
+// NewBeegoRequestWithCtx returns a new BeegoHTTPRequest given a method, URL
+func NewBeegoRequestWithCtx(ctx context.Context, rawurl, method string) *BeegoHTTPRequest {
+ req, err := http.NewRequestWithContext(ctx, method, rawurl, nil)
if err != nil {
- logs.Error("%+v", berror.Wrapf(err, InvalidUrl, "invalid raw url: %s", rawurl))
- }
- req := http.Request{
- URL: u,
- Method: method,
- Header: make(http.Header),
- Proto: "HTTP/1.1",
- ProtoMajor: 1,
- ProtoMinor: 1,
+ logs.Error("%+v", berror.Wrapf(err, InvalidURLOrMethod, "invalid raw url or method: %s %s", rawurl, method))
}
+
return &BeegoHTTPRequest{
url: rawurl,
- req: &req,
+ req: req,
params: map[string][]string{},
files: map[string]string{},
setting: defaultSetting,
- resp: &resp,
+ resp: &http.Response{},
}
}
@@ -409,7 +406,7 @@ func (b *BeegoHTTPRequest) handleFiles() {
b.Header("Transfer-Encoding", "chunked")
}
-func (b *BeegoHTTPRequest) handleFileToBody(bodyWriter *multipart.Writer, formname string, filename string) {
+func (*BeegoHTTPRequest) handleFileToBody(bodyWriter *multipart.Writer, formname string, filename string) {
fileWriter, err := bodyWriter.CreateFormFile(formname, filename)
const errFmt = "Httplib: %+v"
if err != nil {
@@ -445,9 +442,16 @@ func (b *BeegoHTTPRequest) getResponse() (*http.Response, error) {
// DoRequest executes client.Do
func (b *BeegoHTTPRequest) DoRequest() (resp *http.Response, err error) {
- return b.DoRequestWithCtx(context.Background())
+ root := doRequestFilter
+ if len(b.setting.FilterChains) > 0 {
+ for i := len(b.setting.FilterChains) - 1; i >= 0; i-- {
+ root = b.setting.FilterChains[i](root)
+ }
+ }
+ return root(b.req.Context(), b)
}
+// Deprecated: please use NewBeegoRequestWithContext
func (b *BeegoHTTPRequest) DoRequestWithCtx(ctx context.Context) (resp *http.Response, err error) {
root := doRequestFilter
if len(b.setting.FilterChains) > 0 {
@@ -458,7 +462,7 @@ func (b *BeegoHTTPRequest) DoRequestWithCtx(ctx context.Context) (resp *http.Res
return root(ctx, b)
}
-func (b *BeegoHTTPRequest) doRequest(ctx context.Context) (*http.Response, error) {
+func (b *BeegoHTTPRequest) doRequest(_ context.Context) (*http.Response, error) {
paramBody := b.buildParamBody()
b.buildURL(paramBody)
diff --git a/client/httplib/httplib_test.go b/client/httplib/httplib_test.go
index 471be02c..217351b2 100644
--- a/client/httplib/httplib_test.go
+++ b/client/httplib/httplib_test.go
@@ -290,19 +290,19 @@ func TestHeader(t *testing.T) {
// TestAddFilter make sure that AddFilters only work for the specific request
func TestAddFilter(t *testing.T) {
- req := Get("http://beego.me")
+ req := Get("http://beego.vip")
req.AddFilters(func(next Filter) Filter {
return func(ctx context.Context, req *BeegoHTTPRequest) (*http.Response, error) {
return next(ctx, req)
}
})
- r := Get("http://beego.me")
+ r := Get("http://beego.vip")
assert.Equal(t, 1, len(req.setting.FilterChains)-len(r.setting.FilterChains))
}
func TestFilterChainOrder(t *testing.T) {
- req := Get("http://beego.me")
+ req := Get("http://beego.vip")
req.AddFilters(func(next Filter) Filter {
return func(ctx context.Context, req *BeegoHTTPRequest) (*http.Response, error) {
return NewHttpResponseWithJsonBody("first"), nil
@@ -323,39 +323,51 @@ func TestFilterChainOrder(t *testing.T) {
}
func TestHead(t *testing.T) {
- req := Head("http://beego.me")
+ req := Head("http://beego.vip")
assert.NotNil(t, req)
assert.Equal(t, "HEAD", req.req.Method)
}
func TestDelete(t *testing.T) {
- req := Delete("http://beego.me")
+ req := Delete("http://beego.vip")
assert.NotNil(t, req)
assert.Equal(t, "DELETE", req.req.Method)
}
func TestPost(t *testing.T) {
- req := Post("http://beego.me")
+ req := Post("http://beego.vip")
assert.NotNil(t, req)
assert.Equal(t, "POST", req.req.Method)
}
func TestNewBeegoRequest(t *testing.T) {
- req := NewBeegoRequest("http://beego.me", "GET")
+ req := NewBeegoRequest("http://beego.vip", "GET")
assert.NotNil(t, req)
assert.Equal(t, "GET", req.req.Method)
// invalid case but still go request
- req = NewBeegoRequest("httpa\ta://beego.me", "GET")
+ req = NewBeegoRequest("httpa\ta://beego.vip", "GET")
+ assert.NotNil(t, req)
+}
+
+func TestNewBeegoRequestWithCtx(t *testing.T) {
+ req := NewBeegoRequestWithCtx(context.Background(), "http://beego.vip", "GET")
+ assert.NotNil(t, req)
+ assert.Equal(t, "GET", req.req.Method)
+
+ // bad url but still get request
+ req = NewBeegoRequestWithCtx(context.Background(), "httpa\ta://beego.vip", "GET")
+ assert.NotNil(t, req)
+
+ // bad method but still get request
+ req = NewBeegoRequestWithCtx(context.Background(), "http://beego.vip", "G\tET")
assert.NotNil(t, req)
}
func TestBeegoHTTPRequestSetProtocolVersion(t *testing.T) {
- req := NewBeegoRequest("http://beego.me", "GET")
- req.SetProtocolVersion("HTTP/3.10")
- assert.Equal(t, "HTTP/3.10", req.req.Proto)
- assert.Equal(t, 3, req.req.ProtoMajor)
- assert.Equal(t, 10, req.req.ProtoMinor)
+ req := NewBeegoRequest("http://beego.vip", "GET")
+ assert.Equal(t, 1, req.req.ProtoMajor)
+ assert.Equal(t, 1, req.req.ProtoMinor)
req.SetProtocolVersion("")
assert.Equal(t, "HTTP/1.1", req.req.Proto)
@@ -370,27 +382,27 @@ func TestBeegoHTTPRequestSetProtocolVersion(t *testing.T) {
}
func TestPut(t *testing.T) {
- req := Put("http://beego.me")
+ req := Put("http://beego.vip")
assert.NotNil(t, req)
assert.Equal(t, "PUT", req.req.Method)
}
func TestBeegoHTTPRequestHeader(t *testing.T) {
- req := Post("http://beego.me")
+ req := Post("http://beego.vip")
key, value := "test-header", "test-header-value"
req.Header(key, value)
assert.Equal(t, value, req.req.Header.Get(key))
}
func TestBeegoHTTPRequestSetHost(t *testing.T) {
- req := Post("http://beego.me")
+ req := Post("http://beego.vip")
host := "test-hose"
req.SetHost(host)
assert.Equal(t, host, req.req.Host)
}
func TestBeegoHTTPRequestParam(t *testing.T) {
- req := Post("http://beego.me")
+ req := Post("http://beego.vip")
key, value := "test-param", "test-param-value"
req.Param(key, value)
assert.Equal(t, value, req.params[key][0])
@@ -401,7 +413,7 @@ func TestBeegoHTTPRequestParam(t *testing.T) {
}
func TestBeegoHTTPRequestBody(t *testing.T) {
- req := Post("http://beego.me")
+ req := Post("http://beego.vip")
body := `hello, world`
req.Body([]byte(body))
assert.Equal(t, int64(len(body)), req.req.ContentLength)
@@ -423,7 +435,7 @@ type user struct {
}
func TestBeegoHTTPRequestXMLBody(t *testing.T) {
- req := Post("http://beego.me")
+ req := Post("http://beego.vip")
body := &user{
Name: "Tom",
}
@@ -438,7 +450,7 @@ func TestBeegoHTTPRequestResponseForValue(t *testing.T) {
}
func TestBeegoHTTPRequestJSONMarshal(t *testing.T) {
- req := Post("http://beego.me")
+ req := Post("http://beego.vip")
req.SetEscapeHTML(false)
body := map[string]interface{}{
"escape": "left&right",
diff --git a/client/orm/README.md b/client/orm/README.md
index bb11d1c6..15fd1b11 100644
--- a/client/orm/README.md
+++ b/client/orm/README.md
@@ -155,5 +155,5 @@ note: not recommend use this in product env.
more details and examples in docs and test
-[documents](http://beego.me/docs/mvc/model/overview.md)
+[documents](http://beego.vip/docs/mvc/model/overview.md)
diff --git a/client/orm/cmd.go b/client/orm/cmd.go
index 432785d6..9819badb 100644
--- a/client/orm/cmd.go
+++ b/client/orm/cmd.go
@@ -100,7 +100,7 @@ func (d *commandSyncDb) Run() error {
var drops []string
var err error
if d.force {
- drops, err = modelCache.getDbDropSQL(d.al)
+ drops, err = defaultModelCache.getDbDropSQL(d.al)
if err != nil {
return err
}
@@ -109,7 +109,7 @@ func (d *commandSyncDb) Run() error {
db := d.al.DB
if d.force && len(drops) > 0 {
- for i, mi := range modelCache.allOrdered() {
+ for i, mi := range defaultModelCache.allOrdered() {
query := drops[i]
if !d.noInfo {
fmt.Printf("drop table `%s`\n", mi.table)
@@ -127,7 +127,7 @@ func (d *commandSyncDb) Run() error {
}
}
- createQueries, indexes, err := modelCache.getDbCreateSQL(d.al)
+ createQueries, indexes, err := defaultModelCache.getDbCreateSQL(d.al)
if err != nil {
return err
}
@@ -141,7 +141,7 @@ func (d *commandSyncDb) Run() error {
}
ctx := context.Background()
- for i, mi := range modelCache.allOrdered() {
+ for i, mi := range defaultModelCache.allOrdered() {
if !isApplicableTableForDB(mi.addrField, d.al.Name) {
fmt.Printf("table `%s` is not applicable to database '%s'\n", mi.table, d.al.Name)
@@ -258,12 +258,12 @@ func (d *commandSQLAll) Parse(args []string) {
// Run orm line command.
func (d *commandSQLAll) Run() error {
- createQueries, indexes, err := modelCache.getDbCreateSQL(d.al)
+ createQueries, indexes, err := defaultModelCache.getDbCreateSQL(d.al)
if err != nil {
return err
}
var all []string
- for i, mi := range modelCache.allOrdered() {
+ for i, mi := range defaultModelCache.allOrdered() {
queries := []string{createQueries[i]}
for _, idx := range indexes[mi.table] {
queries = append(queries, idx.SQL)
diff --git a/client/orm/db.go b/client/orm/db.go
index 5a9f1b58..5da43d0a 100644
--- a/client/orm/db.go
+++ b/client/orm/db.go
@@ -1038,7 +1038,7 @@ func (d *dbBase) ReadBatch(ctx context.Context, q dbQuerier, qs *querySet, mi *m
slice := ind
if unregister {
- mi, _ = modelCache.get(name)
+ mi, _ = defaultModelCache.get(name)
tCols = mi.fields.dbcols
colsNum = len(tCols)
}
diff --git a/client/orm/db_utils.go b/client/orm/db_utils.go
index f2e1353c..01f5a028 100644
--- a/client/orm/db_utils.go
+++ b/client/orm/db_utils.go
@@ -156,7 +156,7 @@ outFor:
typ := val.Type()
name := getFullName(typ)
var value interface{}
- if mmi, ok := modelCache.getByFullName(name); ok {
+ if mmi, ok := defaultModelCache.getByFullName(name); ok {
if _, vu, exist := getExistPk(mmi, val); exist {
value = vu
}
diff --git a/client/orm/filter_orm_decorator.go b/client/orm/filter_orm_decorator.go
index edeaaade..3b23284d 100644
--- a/client/orm/filter_orm_decorator.go
+++ b/client/orm/filter_orm_decorator.go
@@ -78,7 +78,7 @@ func (f *filterOrmDecorator) Read(md interface{}, cols ...string) error {
}
func (f *filterOrmDecorator) ReadWithCtx(ctx context.Context, md interface{}, cols ...string) error {
- mi, _ := modelCache.getByMd(md)
+ mi, _ := defaultModelCache.getByMd(md)
inv := &Invocation{
Method: "ReadWithCtx",
Args: []interface{}{md, cols},
@@ -100,7 +100,7 @@ func (f *filterOrmDecorator) ReadForUpdate(md interface{}, cols ...string) error
}
func (f *filterOrmDecorator) ReadForUpdateWithCtx(ctx context.Context, md interface{}, cols ...string) error {
- mi, _ := modelCache.getByMd(md)
+ mi, _ := defaultModelCache.getByMd(md)
inv := &Invocation{
Method: "ReadForUpdateWithCtx",
Args: []interface{}{md, cols},
@@ -122,7 +122,7 @@ func (f *filterOrmDecorator) ReadOrCreate(md interface{}, col1 string, cols ...s
}
func (f *filterOrmDecorator) ReadOrCreateWithCtx(ctx context.Context, md interface{}, col1 string, cols ...string) (bool, int64, error) {
- mi, _ := modelCache.getByMd(md)
+ mi, _ := defaultModelCache.getByMd(md)
inv := &Invocation{
Method: "ReadOrCreateWithCtx",
Args: []interface{}{md, col1, cols},
@@ -144,7 +144,7 @@ func (f *filterOrmDecorator) LoadRelated(md interface{}, name string, args ...ut
}
func (f *filterOrmDecorator) LoadRelatedWithCtx(ctx context.Context, md interface{}, name string, args ...utils.KV) (int64, error) {
- mi, _ := modelCache.getByMd(md)
+ mi, _ := defaultModelCache.getByMd(md)
inv := &Invocation{
Method: "LoadRelatedWithCtx",
Args: []interface{}{md, name, args},
@@ -162,7 +162,7 @@ func (f *filterOrmDecorator) LoadRelatedWithCtx(ctx context.Context, md interfac
}
func (f *filterOrmDecorator) QueryM2M(md interface{}, name string) QueryM2Mer {
- mi, _ := modelCache.getByMd(md)
+ mi, _ := defaultModelCache.getByMd(md)
inv := &Invocation{
Method: "QueryM2M",
Args: []interface{}{md, name},
@@ -202,7 +202,7 @@ func (f *filterOrmDecorator) QueryTable(ptrStructOrTableName interface{}) QueryS
md = ptrStructOrTableName
}
- if m, ok := modelCache.getByFullName(name); ok {
+ if m, ok := defaultModelCache.getByFullName(name); ok {
mi = m
}
@@ -256,7 +256,7 @@ func (f *filterOrmDecorator) Insert(md interface{}) (int64, error) {
}
func (f *filterOrmDecorator) InsertWithCtx(ctx context.Context, md interface{}) (int64, error) {
- mi, _ := modelCache.getByMd(md)
+ mi, _ := defaultModelCache.getByMd(md)
inv := &Invocation{
Method: "InsertWithCtx",
Args: []interface{}{md},
@@ -278,7 +278,7 @@ func (f *filterOrmDecorator) InsertOrUpdate(md interface{}, colConflitAndArgs ..
}
func (f *filterOrmDecorator) InsertOrUpdateWithCtx(ctx context.Context, md interface{}, colConflitAndArgs ...string) (int64, error) {
- mi, _ := modelCache.getByMd(md)
+ mi, _ := defaultModelCache.getByMd(md)
inv := &Invocation{
Method: "InsertOrUpdateWithCtx",
Args: []interface{}{md, colConflitAndArgs},
@@ -311,7 +311,7 @@ func (f *filterOrmDecorator) InsertMultiWithCtx(ctx context.Context, bulk int, m
if (sind.Kind() == reflect.Array || sind.Kind() == reflect.Slice) && sind.Len() > 0 {
ind := reflect.Indirect(sind.Index(0))
md = ind.Interface()
- mi, _ = modelCache.getByMd(md)
+ mi, _ = defaultModelCache.getByMd(md)
}
inv := &Invocation{
@@ -335,7 +335,7 @@ func (f *filterOrmDecorator) Update(md interface{}, cols ...string) (int64, erro
}
func (f *filterOrmDecorator) UpdateWithCtx(ctx context.Context, md interface{}, cols ...string) (int64, error) {
- mi, _ := modelCache.getByMd(md)
+ mi, _ := defaultModelCache.getByMd(md)
inv := &Invocation{
Method: "UpdateWithCtx",
Args: []interface{}{md, cols},
@@ -357,7 +357,7 @@ func (f *filterOrmDecorator) Delete(md interface{}, cols ...string) (int64, erro
}
func (f *filterOrmDecorator) DeleteWithCtx(ctx context.Context, md interface{}, cols ...string) (int64, error) {
- mi, _ := modelCache.getByMd(md)
+ mi, _ := defaultModelCache.getByMd(md)
inv := &Invocation{
Method: "DeleteWithCtx",
Args: []interface{}{md, cols},
diff --git a/client/orm/model_test.go b/client/orm/model_test.go
new file mode 100644
index 00000000..8aee8d89
--- /dev/null
+++ b/client/orm/model_test.go
@@ -0,0 +1,78 @@
+// 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.
+
+package orm
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+type ModelWithComments struct {
+ ID int `orm:"column(id);description(user id)"`
+ UserName string `orm:"size(30);unique;description(user name)"`
+ Email string `orm:"size(100);description(email)"`
+ Password string `orm:"size(100);description(password)"`
+}
+
+type ModelWithoutComments struct {
+ ID int `orm:"column(id)"`
+ UserName string `orm:"size(30);unique"`
+ Email string `orm:"size(100)"`
+ Password string `orm:"size(100)"`
+}
+
+type ModelWithEmptyComments struct {
+ ID int `orm:"column(id);description()"`
+ UserName string `orm:"size(30);unique;description()"`
+ Email string `orm:"size(100);description()"`
+ Password string `orm:"size(100);description()"`
+}
+
+func TestGetDbCreateSQLWithComment(t *testing.T) {
+ type TestCase struct {
+ name string
+ model interface{}
+ wantSQL string
+ wantErr error
+ }
+ al := getDbAlias("default")
+ testModelCache := NewModelCacheHandler()
+ var testCases []TestCase
+ switch al.Driver {
+ case DRMySQL:
+ testCases = append(testCases, TestCase{name: "model with comments for MySQL", model: &ModelWithComments{}, wantSQL: "-- --------------------------------------------------\n-- Table Structure for `github.com/beego/beego/v2/client/orm.ModelWithComments`\n-- --------------------------------------------------\nCREATE TABLE IF NOT EXISTS `model_with_comments` (\n `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY COMMENT 'user id',\n `user_name` varchar(30) NOT NULL DEFAULT '' UNIQUE COMMENT 'user name',\n `email` varchar(100) NOT NULL DEFAULT '' COMMENT 'email',\n `password` varchar(100) NOT NULL DEFAULT '' COMMENT 'password'\n) ENGINE=INNODB;", wantErr: nil})
+ testCases = append(testCases, TestCase{name: "model without comments for MySQL", model: &ModelWithoutComments{}, wantSQL: "-- --------------------------------------------------\n-- Table Structure for `github.com/beego/beego/v2/client/orm.ModelWithoutComments`\n-- --------------------------------------------------\nCREATE TABLE IF NOT EXISTS `model_without_comments` (\n `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,\n `user_name` varchar(30) NOT NULL DEFAULT '' UNIQUE,\n `email` varchar(100) NOT NULL DEFAULT '' ,\n `password` varchar(100) NOT NULL DEFAULT '' \n) ENGINE=INNODB;", wantErr: nil})
+ testCases = append(testCases, TestCase{name: "model with empty comments for MySQL", model: &ModelWithEmptyComments{}, wantSQL: "-- --------------------------------------------------\n-- Table Structure for `github.com/beego/beego/v2/client/orm.ModelWithEmptyComments`\n-- --------------------------------------------------\nCREATE TABLE IF NOT EXISTS `model_with_empty_comments` (\n `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,\n `user_name` varchar(30) NOT NULL DEFAULT '' UNIQUE,\n `email` varchar(100) NOT NULL DEFAULT '' ,\n `password` varchar(100) NOT NULL DEFAULT '' \n) ENGINE=INNODB;", wantErr: nil})
+ case DRPostgres:
+ testCases = append(testCases, TestCase{name: "model with comments for Postgres", model: &ModelWithComments{}, wantSQL: "-- --------------------------------------------------\n-- Table Structure for `github.com/beego/beego/v2/client/orm.ModelWithComments`\n-- --------------------------------------------------\nCREATE TABLE IF NOT EXISTS \"model_with_comments\" (\n \"id\" serial NOT NULL PRIMARY KEY,\n \"user_name\" varchar(30) NOT NULL DEFAULT '' UNIQUE,\n \"email\" varchar(100) NOT NULL DEFAULT '' ,\n \"password\" varchar(100) NOT NULL DEFAULT '' \n);\nCOMMENT ON COLUMN \"model_with_comments\".\"id\" is 'user id';\nCOMMENT ON COLUMN \"model_with_comments\".\"user_name\" is 'user name';\nCOMMENT ON COLUMN \"model_with_comments\".\"email\" is 'email';\nCOMMENT ON COLUMN \"model_with_comments\".\"password\" is 'password';", wantErr: nil})
+ testCases = append(testCases, TestCase{name: "model without comments for Postgres", model: &ModelWithoutComments{}, wantSQL: "-- --------------------------------------------------\n-- Table Structure for `github.com/beego/beego/v2/client/orm.ModelWithoutComments`\n-- --------------------------------------------------\nCREATE TABLE IF NOT EXISTS \"model_without_comments\" (\n \"id\" serial NOT NULL PRIMARY KEY,\n \"user_name\" varchar(30) NOT NULL DEFAULT '' UNIQUE,\n \"email\" varchar(100) NOT NULL DEFAULT '' ,\n \"password\" varchar(100) NOT NULL DEFAULT '' \n);", wantErr: nil})
+ testCases = append(testCases, TestCase{name: "model with empty comments for Postgres", model: &ModelWithEmptyComments{}, wantSQL: "-- --------------------------------------------------\n-- Table Structure for `github.com/beego/beego/v2/client/orm.ModelWithEmptyComments`\n-- --------------------------------------------------\nCREATE TABLE IF NOT EXISTS \"model_with_empty_comments\" (\n \"id\" serial NOT NULL PRIMARY KEY,\n \"user_name\" varchar(30) NOT NULL DEFAULT '' UNIQUE,\n \"email\" varchar(100) NOT NULL DEFAULT '' ,\n \"password\" varchar(100) NOT NULL DEFAULT '' \n);", wantErr: nil})
+ case DRSqlite:
+ testCases = append(testCases, TestCase{name: "model with comments for Sqlite", model: &ModelWithComments{}, wantSQL: "-- --------------------------------------------------\n-- Table Structure for `github.com/beego/beego/v2/client/orm.ModelWithComments`\n-- --------------------------------------------------\nCREATE TABLE IF NOT EXISTS `model_with_comments` (\n `id` integer NOT NULL PRIMARY KEY AUTOINCREMENT,\n `user_name` varchar(30) NOT NULL DEFAULT '' UNIQUE,\n `email` varchar(100) NOT NULL DEFAULT '' ,\n `password` varchar(100) NOT NULL DEFAULT '' \n);", wantErr: nil})
+ testCases = append(testCases, TestCase{name: "model without comments for Sqlite", model: &ModelWithoutComments{}, wantSQL: "-- --------------------------------------------------\n-- Table Structure for `github.com/beego/beego/v2/client/orm.ModelWithoutComments`\n-- --------------------------------------------------\nCREATE TABLE IF NOT EXISTS `model_without_comments` (\n `id` integer NOT NULL PRIMARY KEY AUTOINCREMENT,\n `user_name` varchar(30) NOT NULL DEFAULT '' UNIQUE,\n `email` varchar(100) NOT NULL DEFAULT '' ,\n `password` varchar(100) NOT NULL DEFAULT '' \n);", wantErr: nil})
+ testCases = append(testCases, TestCase{name: "model with empty comments for Sqlite", model: &ModelWithEmptyComments{}, wantSQL: "-- --------------------------------------------------\n-- Table Structure for `github.com/beego/beego/v2/client/orm.ModelWithEmptyComments`\n-- --------------------------------------------------\nCREATE TABLE IF NOT EXISTS `model_with_empty_comments` (\n `id` integer NOT NULL PRIMARY KEY AUTOINCREMENT,\n `user_name` varchar(30) NOT NULL DEFAULT '' UNIQUE,\n `email` varchar(100) NOT NULL DEFAULT '' ,\n `password` varchar(100) NOT NULL DEFAULT '' \n);", wantErr: nil})
+ }
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ testModelCache.clean()
+ err := testModelCache.register("", true, tc.model)
+ assert.NoError(t, err)
+ queries, _, err := testModelCache.getDbCreateSQL(al)
+ assert.Equal(t, tc.wantSQL, queries[0])
+ assert.Equal(t, tc.wantErr, err)
+ })
+ }
+}
diff --git a/client/orm/model_utils_test.go b/client/orm/model_utils_test.go
index b65aadcb..be97c58d 100644
--- a/client/orm/model_utils_test.go
+++ b/client/orm/model_utils_test.go
@@ -49,7 +49,7 @@ func (i *Interface) TableEngine() string {
func TestDbBase_GetTables(t *testing.T) {
RegisterModel(&Interface{})
- mi, ok := modelCache.get("INTERFACE_")
+ mi, ok := defaultModelCache.get("INTERFACE_")
assert.True(t, ok)
assert.NotNil(t, mi)
diff --git a/client/orm/models.go b/client/orm/models.go
index c78bcf69..94630ba5 100644
--- a/client/orm/models.go
+++ b/client/orm/models.go
@@ -32,10 +32,10 @@ const (
defaultStructTagDelim = ";"
)
-var modelCache = NewModelCacheHandler()
+var defaultModelCache = NewModelCacheHandler()
// model info collection
-type _modelCache struct {
+type modelCache struct {
sync.RWMutex // only used outsite for bootStrap
orders []string
cache map[string]*modelInfo
@@ -43,16 +43,16 @@ type _modelCache struct {
done bool
}
-// NewModelCacheHandler generator of _modelCache
-func NewModelCacheHandler() *_modelCache {
- return &_modelCache{
+// NewModelCacheHandler generator of modelCache
+func NewModelCacheHandler() *modelCache {
+ return &modelCache{
cache: make(map[string]*modelInfo),
cacheByFullName: make(map[string]*modelInfo),
}
}
// get all model info
-func (mc *_modelCache) all() map[string]*modelInfo {
+func (mc *modelCache) all() map[string]*modelInfo {
m := make(map[string]*modelInfo, len(mc.cache))
for k, v := range mc.cache {
m[k] = v
@@ -61,7 +61,7 @@ func (mc *_modelCache) all() map[string]*modelInfo {
}
// get ordered model info
-func (mc *_modelCache) allOrdered() []*modelInfo {
+func (mc *modelCache) allOrdered() []*modelInfo {
m := make([]*modelInfo, 0, len(mc.orders))
for _, table := range mc.orders {
m = append(m, mc.cache[table])
@@ -70,18 +70,18 @@ func (mc *_modelCache) allOrdered() []*modelInfo {
}
// get model info by table name
-func (mc *_modelCache) get(table string) (mi *modelInfo, ok bool) {
+func (mc *modelCache) get(table string) (mi *modelInfo, ok bool) {
mi, ok = mc.cache[table]
return
}
// get model info by full name
-func (mc *_modelCache) getByFullName(name string) (mi *modelInfo, ok bool) {
+func (mc *modelCache) getByFullName(name string) (mi *modelInfo, ok bool) {
mi, ok = mc.cacheByFullName[name]
return
}
-func (mc *_modelCache) getByMd(md interface{}) (*modelInfo, bool) {
+func (mc *modelCache) getByMd(md interface{}) (*modelInfo, bool) {
val := reflect.ValueOf(md)
ind := reflect.Indirect(val)
typ := ind.Type()
@@ -90,7 +90,7 @@ func (mc *_modelCache) getByMd(md interface{}) (*modelInfo, bool) {
}
// set model info to collection
-func (mc *_modelCache) set(table string, mi *modelInfo) *modelInfo {
+func (mc *modelCache) set(table string, mi *modelInfo) *modelInfo {
mii := mc.cache[table]
mc.cache[table] = mi
mc.cacheByFullName[mi.fullName] = mi
@@ -101,7 +101,7 @@ func (mc *_modelCache) set(table string, mi *modelInfo) *modelInfo {
}
// clean all model info.
-func (mc *_modelCache) clean() {
+func (mc *modelCache) clean() {
mc.Lock()
defer mc.Unlock()
@@ -112,7 +112,7 @@ func (mc *_modelCache) clean() {
}
// bootstrap bootstrap for models
-func (mc *_modelCache) bootstrap() {
+func (mc *modelCache) bootstrap() {
mc.Lock()
defer mc.Unlock()
if mc.done {
@@ -325,11 +325,10 @@ end:
debug.PrintStack()
}
mc.done = true
- return
}
// register register models to model cache
-func (mc *_modelCache) register(prefixOrSuffixStr string, prefixOrSuffix bool, models ...interface{}) (err error) {
+func (mc *modelCache) register(prefixOrSuffixStr string, prefixOrSuffix bool, models ...interface{}) (err error) {
for _, model := range models {
val := reflect.ValueOf(model)
typ := reflect.Indirect(val).Type()
@@ -396,7 +395,7 @@ func (mc *_modelCache) register(prefixOrSuffixStr string, prefixOrSuffix bool, m
}
// getDbDropSQL get database scheme drop sql queries
-func (mc *_modelCache) getDbDropSQL(al *alias) (queries []string, err error) {
+func (mc *modelCache) getDbDropSQL(al *alias) (queries []string, err error) {
if len(mc.cache) == 0 {
err = errors.New("no Model found, need register your model")
return
@@ -411,7 +410,7 @@ func (mc *_modelCache) getDbDropSQL(al *alias) (queries []string, err error) {
}
// getDbCreateSQL get database scheme creation sql queries
-func (mc *_modelCache) getDbCreateSQL(al *alias) (queries []string, tableIndexes map[string][]dbIndex, err error) {
+func (mc *modelCache) getDbCreateSQL(al *alias) (queries []string, tableIndexes map[string][]dbIndex, err error) {
if len(mc.cache) == 0 {
err = errors.New("no Model found, need register your model")
return
@@ -433,9 +432,9 @@ func (mc *_modelCache) getDbCreateSQL(al *alias) (queries []string, tableIndexes
columns := make([]string, 0, len(mi.fields.fieldsDB))
sqlIndexes := [][]string{}
+ var commentIndexes []int // store comment indexes for postgres
- for _, fi := range mi.fields.fieldsDB {
-
+ for i, fi := range mi.fields.fieldsDB {
column := fmt.Sprintf(" %s%s%s ", Q, fi.column, Q)
col := getColumnTyp(al, fi)
@@ -476,7 +475,11 @@ func (mc *_modelCache) getDbCreateSQL(al *alias) (queries []string, tableIndexes
}
if fi.description != "" && al.Driver != DRSqlite {
- column += " " + fmt.Sprintf("COMMENT '%s'", fi.description)
+ if al.Driver == DRPostgres {
+ commentIndexes = append(commentIndexes, i)
+ } else {
+ column += " " + fmt.Sprintf("COMMENT '%s'", fi.description)
+ }
}
columns = append(columns, column)
@@ -516,6 +519,19 @@ func (mc *_modelCache) getDbCreateSQL(al *alias) (queries []string, tableIndexes
}
sql += ";"
+ if al.Driver == DRPostgres && len(commentIndexes) > 0 {
+ // append comments for postgres only
+ for _, index := range commentIndexes {
+ sql += fmt.Sprintf("\nCOMMENT ON COLUMN %s%s%s.%s%s%s is '%s';",
+ Q,
+ mi.table,
+ Q,
+ Q,
+ mi.fields.fieldsDB[index].column,
+ Q,
+ mi.fields.fieldsDB[index].description)
+ }
+ }
queries = append(queries, sql)
if mi.model != nil {
@@ -553,5 +569,5 @@ func (mc *_modelCache) getDbCreateSQL(al *alias) (queries []string, tableIndexes
// ResetModelCache Clean model cache. Then you can re-RegisterModel.
// Common use this api for test case.
func ResetModelCache() {
- modelCache.clean()
+ defaultModelCache.clean()
}
diff --git a/client/orm/models_boot.go b/client/orm/models_boot.go
index 9a0ce893..6916f3ba 100644
--- a/client/orm/models_boot.go
+++ b/client/orm/models_boot.go
@@ -21,14 +21,14 @@ func RegisterModel(models ...interface{}) {
// RegisterModelWithPrefix register models with a prefix
func RegisterModelWithPrefix(prefix string, models ...interface{}) {
- if err := modelCache.register(prefix, true, models...); err != nil {
+ if err := defaultModelCache.register(prefix, true, models...); err != nil {
panic(err)
}
}
// RegisterModelWithSuffix register models with a suffix
func RegisterModelWithSuffix(suffix string, models ...interface{}) {
- if err := modelCache.register(suffix, false, models...); err != nil {
+ if err := defaultModelCache.register(suffix, false, models...); err != nil {
panic(err)
}
}
@@ -36,5 +36,5 @@ func RegisterModelWithSuffix(suffix string, models ...interface{}) {
// BootStrap bootstrap models.
// make all model parsed and can not add more models
func BootStrap() {
- modelCache.bootstrap()
+ defaultModelCache.bootstrap()
}
diff --git a/client/orm/orm.go b/client/orm/orm.go
index 30753acf..05614beb 100644
--- a/client/orm/orm.go
+++ b/client/orm/orm.go
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+//go:build go1.8
// +build go1.8
// Package orm provide ORM for MySQL/PostgreSQL/sqlite
@@ -50,7 +51,7 @@
// num, err = o.Delete(&u)
// }
//
-// more docs: http://beego.me/docs/mvc/model/overview.md
+// more docs: http://beego.vip/docs/mvc/model/overview.md
package orm
import (
@@ -130,7 +131,7 @@ func (*ormBase) getPtrMiInd(md interface{}) (mi *modelInfo, ind reflect.Value) {
func getTypeMi(mdTyp reflect.Type) *modelInfo {
name := getFullName(mdTyp)
- if mi, ok := modelCache.getByFullName(name); ok {
+ if mi, ok := defaultModelCache.getByFullName(name); ok {
return mi
}
panic(fmt.Errorf(" table: `%s` not found, make sure it was registered with `RegisterModel()`", name))
@@ -476,12 +477,12 @@ func (o *ormBase) QueryTable(ptrStructOrTableName interface{}) (qs QuerySeter) {
var name string
if table, ok := ptrStructOrTableName.(string); ok {
name = nameStrategyMap[defaultNameStrategy](table)
- if mi, ok := modelCache.get(name); ok {
+ if mi, ok := defaultModelCache.get(name); ok {
qs = newQuerySet(o, mi)
}
} else {
name = getFullName(indirectType(reflect.TypeOf(ptrStructOrTableName)))
- if mi, ok := modelCache.getByFullName(name); ok {
+ if mi, ok := defaultModelCache.getByFullName(name); ok {
qs = newQuerySet(o, mi)
}
}
diff --git a/client/orm/orm_raw.go b/client/orm/orm_raw.go
index 25452660..f4f3a62e 100644
--- a/client/orm/orm_raw.go
+++ b/client/orm/orm_raw.go
@@ -314,7 +314,7 @@ func (o *rawSet) QueryRow(containers ...interface{}) error {
structMode = true
fn := getFullName(typ)
- if mi, ok := modelCache.getByFullName(fn); ok {
+ if mi, ok := defaultModelCache.getByFullName(fn); ok {
sMi = mi
}
} else {
@@ -475,7 +475,7 @@ func (o *rawSet) QueryRows(containers ...interface{}) (int64, error) {
structMode = true
fn := getFullName(typ)
- if mi, ok := modelCache.getByFullName(fn); ok {
+ if mi, ok := defaultModelCache.getByFullName(fn); ok {
sMi = mi
}
} else {
diff --git a/client/orm/orm_test.go b/client/orm/orm_test.go
index 764e5b6d..55d9ba18 100644
--- a/client/orm/orm_test.go
+++ b/client/orm/orm_test.go
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+//go:build go1.8
// +build go1.8
package orm
@@ -214,7 +215,7 @@ func TestSyncDb(t *testing.T) {
err := RunSyncdb("default", true, Debug)
throwFail(t, err)
- modelCache.clean()
+ defaultModelCache.clean()
}
func TestRegisterModels(_ *testing.T) {
@@ -250,10 +251,10 @@ func TestModelSyntax(t *testing.T) {
user := &User{}
ind := reflect.ValueOf(user).Elem()
fn := getFullName(ind.Type())
- _, ok := modelCache.getByFullName(fn)
+ _, ok := defaultModelCache.getByFullName(fn)
throwFail(t, AssertIs(ok, true))
- mi, ok := modelCache.get("user")
+ mi, ok := defaultModelCache.get("user")
throwFail(t, AssertIs(ok, true))
if ok {
throwFail(t, AssertIs(mi.fields.GetByName("ShouldSkip") == nil, true))
@@ -2628,9 +2629,9 @@ func TestIgnoreCaseTag(t *testing.T) {
Name02 string `orm:"COLUMN(Name)"`
Name03 string `orm:"Column(name)"`
}
- modelCache.clean()
+ defaultModelCache.clean()
RegisterModel(&testTagModel{})
- info, ok := modelCache.get("test_tag_model")
+ info, ok := defaultModelCache.get("test_tag_model")
throwFail(t, AssertIs(ok, true))
throwFail(t, AssertNot(info, nil))
if t == nil {
diff --git a/core/admin/healthcheck.go b/core/admin/healthcheck.go
index 79738d1d..73a6cb08 100644
--- a/core/admin/healthcheck.go
+++ b/core/admin/healthcheck.go
@@ -27,7 +27,7 @@
//
// AddHealthCheck("database",&DatabaseCheck{})
//
-// more docs: http://beego.me/docs/module/toolbox.md
+// more docs: http://beego.vip/docs/module/toolbox.md
package admin
// AdminCheckList holds health checker map
diff --git a/core/config/config.go b/core/config/config.go
index bccbc738..95a4eb26 100644
--- a/core/config/config.go
+++ b/core/config/config.go
@@ -37,7 +37,7 @@
// cnf.DIY(key string) (interface{}, error)
// cnf.GetSection(section string) (map[string]string, error)
// cnf.SaveConfigFile(filename string) error
-// More docs http://beego.me/docs/module/config.md
+// More docs http://beego.vip/docs/module/config.md
package config
import (
diff --git a/core/config/ini.go b/core/config/ini.go
index 4d80fbbf..e3a395e5 100644
--- a/core/config/ini.go
+++ b/core/config/ini.go
@@ -478,7 +478,7 @@ func (c *IniConfigContainer) DIY(key string) (v interface{}, err error) {
if v, ok := c.data[strings.ToLower(key)]; ok {
return v, nil
}
- return v, errors.New("key not find")
+ return v, errors.New("key not found")
}
// section.key or key
@@ -520,7 +520,7 @@ func init() {
err := InitGlobalInstance("ini", "conf/app.conf")
if err != nil {
- logs.Debug("init global config instance failed. If you donot use this, just ignore it. ", err)
+ logs.Debug("init global config instance failed. If you do not use this, just ignore it. ", err)
}
}
diff --git a/core/config/xml/xml.go b/core/config/xml/xml.go
index c260d3b5..2240ab8a 100644
--- a/core/config/xml/xml.go
+++ b/core/config/xml/xml.go
@@ -26,7 +26,7 @@
//
// cnf, err := config.NewConfig("xml", "config.xml")
//
-// More docs http://beego.me/docs/module/config.md
+// More docs http://beego.vip/docs/module/config.md
package xml
import (
diff --git a/core/config/yaml/yaml.go b/core/config/yaml/yaml.go
index ae02ad16..64c4823b 100644
--- a/core/config/yaml/yaml.go
+++ b/core/config/yaml/yaml.go
@@ -21,7 +21,7 @@
//
// cnf, err := config.NewConfig("yaml", "config.yaml")
//
-// More docs http://beego.me/docs/module/config.md
+// More docs http://beego.vip/docs/module/config.md
package yaml
import (
diff --git a/core/logs/formatter.go b/core/logs/formatter.go
index 6e9a5bd8..6fa4f70c 100644
--- a/core/logs/formatter.go
+++ b/core/logs/formatter.go
@@ -15,6 +15,7 @@
package logs
import (
+ "fmt"
"path"
"strconv"
)
@@ -64,9 +65,10 @@ func GetFormatter(name string) (LogFormatter, bool) {
// 'l' level number, 't' prefix of level type, 'T' full name of level type
func (p *PatternLogFormatter) ToString(lm *LogMsg) string {
s := []rune(p.Pattern)
+ msg := fmt.Sprintf(lm.Msg, lm.Args...)
m := map[rune]string{
'w': lm.When.Format(p.getWhenFormatter()),
- 'm': lm.Msg,
+ 'm': msg,
'n': strconv.Itoa(lm.LineNumber),
'l': strconv.Itoa(lm.Level),
't': levelPrefix[lm.Level],
diff --git a/core/logs/formatter_test.go b/core/logs/formatter_test.go
index a1853d72..f78a2861 100644
--- a/core/logs/formatter_test.go
+++ b/core/logs/formatter_test.go
@@ -17,7 +17,6 @@ package logs
import (
"encoding/json"
"errors"
- "strconv"
"testing"
"time"
@@ -26,7 +25,7 @@ import (
type CustomFormatter struct{}
-func (c *CustomFormatter) Format(lm *LogMsg) string {
+func (*CustomFormatter) Format(lm *LogMsg) string {
return "hello, msg: " + lm.Msg
}
@@ -50,15 +49,15 @@ func (t *TestLogger) WriteMsg(lm *LogMsg) error {
return nil
}
-func (t *TestLogger) Destroy() {
+func (*TestLogger) Destroy() {
panic("implement me")
}
-func (t *TestLogger) Flush() {
+func (*TestLogger) Flush() {
panic("implement me")
}
-func (t *TestLogger) SetFormatter(f LogFormatter) {
+func (*TestLogger) SetFormatter(_ LogFormatter) {
panic("implement me")
}
@@ -78,18 +77,40 @@ func TestPatternLogFormatter(t *testing.T) {
Pattern: "%F:%n|%w%t>> %m",
WhenFormat: "2006-01-02",
}
- when := time.Now()
- lm := &LogMsg{
- Msg: "message",
- FilePath: "/User/go/beego/main.go",
- Level: LevelWarn,
- LineNumber: 10,
- When: when,
+ when, _ := time.Parse(tes.WhenFormat, "2022-04-17")
+ testCases := []struct {
+ msg *LogMsg
+ want string
+ }{
+ {
+ msg: &LogMsg{
+ Msg: "hello %s",
+ FilePath: "/User/go/beego/main.go",
+ Level: LevelWarn,
+ LineNumber: 10,
+ When: when,
+ Args: []interface{}{"world"},
+ },
+ want: "/User/go/beego/main.go:10|2022-04-17[W]>> hello world",
+ },
+ {
+ msg: &LogMsg{
+ Msg: "hello",
+ FilePath: "/User/go/beego/main.go",
+ Level: LevelWarn,
+ LineNumber: 10,
+ When: when,
+ },
+ want: "/User/go/beego/main.go:10|2022-04-17[W]>> hello",
+ },
+ {
+ msg: &LogMsg{},
+ want: ":0|0001-01-01[M]>> ",
+ },
}
- got := tes.ToString(lm)
- want := lm.FilePath + ":" + strconv.Itoa(lm.LineNumber) + "|" +
- when.Format(tes.WhenFormat) + levelPrefix[lm.Level] + ">> " + lm.Msg
- if got != want {
- t.Errorf("want %s, got %s", want, got)
+
+ for _, tc := range testCases {
+ got := tes.ToString(tc.msg)
+ assert.Equal(t, tc.want, got)
}
}
diff --git a/core/logs/log.go b/core/logs/log.go
index 9ce8a07b..e5e736ca 100644
--- a/core/logs/log.go
+++ b/core/logs/log.go
@@ -30,7 +30,7 @@
// log.Debug("debug")
// log.Critical("critical")
//
-// more docs http://beego.me/docs/module/logs.md
+// more docs http://beego.vip/docs/module/logs.md
package logs
import (
diff --git a/core/logs/multifile.go b/core/logs/multifile.go
index 0ad8244f..009bd32f 100644
--- a/core/logs/multifile.go
+++ b/core/logs/multifile.go
@@ -83,12 +83,12 @@ func (f *multiFileLogWriter) Init(config string) error {
return nil
}
-func (f *multiFileLogWriter) Format(lm *LogMsg) string {
+func (*multiFileLogWriter) Format(lm *LogMsg) string {
return lm.OldStyleFormat()
}
func (f *multiFileLogWriter) SetFormatter(fmt LogFormatter) {
- f.fullLogWriter.SetFormatter(f)
+ f.fullLogWriter.SetFormatter(fmt)
}
func (f *multiFileLogWriter) Destroy() {
diff --git a/core/utils/pagination/doc.go b/core/utils/pagination/doc.go
index c2df00aa..cd6bc7c2 100644
--- a/core/utils/pagination/doc.go
+++ b/core/utils/pagination/doc.go
@@ -52,7 +52,7 @@ In your view templates:
See also
-http://beego.me/docs/mvc/view/page.md
+http://beego.vip/docs/mvc/view/page.md
*/
package pagination
diff --git a/core/validation/validation.go b/core/validation/validation.go
index 78a31f13..7605d22f 100644
--- a/core/validation/validation.go
+++ b/core/validation/validation.go
@@ -43,7 +43,7 @@
// }
// }
//
-// more info: http://beego.me/docs/mvc/controller/validation.md
+// more info: http://beego.vip/docs/mvc/controller/validation.md
package validation
import (
@@ -107,7 +107,7 @@ func (r *Result) Message(message string, args ...interface{}) *Result {
// A Validation context manages data validation and error messages.
type Validation struct {
// if this field set true, in struct tag valid
- // if the struct field vale is empty
+ // if the struct field value is empty
// it will skip those valid functions, see CanSkipFuncs
RequiredFirst bool
diff --git a/go.mod b/go.mod
index 46e6f139..448dc825 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
module github.com/beego/beego/v2
-go 1.14
+go 1.18
require (
github.com/beego/x2j v0.0.0-20131220205130-a0352aadc542
@@ -8,8 +8,6 @@ require (
github.com/casbin/casbin v1.9.1
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58
github.com/couchbase/go-couchbase v0.1.0
- github.com/couchbase/gomemcached v0.1.3 // indirect
- github.com/couchbase/goutils v0.1.0 // indirect
github.com/elastic/go-elasticsearch/v6 v6.8.10
github.com/elazarl/go-bindata-assetfs v1.0.1
github.com/go-kit/kit v0.10.0
@@ -21,20 +19,59 @@ require (
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
github.com/hashicorp/golang-lru v0.5.4
github.com/ledisdb/ledisdb v0.0.0-20200510135210-d35789ec47e6
- github.com/lib/pq v1.10.2
+ github.com/lib/pq v1.10.5
github.com/mattn/go-sqlite3 v1.14.7
- github.com/mitchellh/mapstructure v1.4.1
+ github.com/mitchellh/mapstructure v1.4.3
github.com/opentracing/opentracing-go v1.2.0
github.com/pelletier/go-toml v1.9.2
github.com/pkg/errors v0.9.1
- github.com/prometheus/client_golang v1.11.0
+ github.com/prometheus/client_golang v1.12.1
github.com/shiena/ansicolor v0.0.0-20200904210342-c7312218db18
github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec
- github.com/stretchr/testify v1.7.0
- go.etcd.io/etcd/client/v3 v3.5.0
+ github.com/stretchr/testify v1.7.1
+ go.etcd.io/etcd/client/v3 v3.5.4
+ go.opentelemetry.io/otel v1.7.0
+ go.opentelemetry.io/otel/trace v1.7.0
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a
google.golang.org/grpc v1.38.0
google.golang.org/protobuf v1.26.0
gopkg.in/yaml.v2 v2.4.0
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
)
+
+require (
+ github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible // indirect
+ github.com/beorn7/perks v1.0.1 // indirect
+ github.com/cespare/xxhash/v2 v2.1.2 // indirect
+ github.com/coreos/go-semver v0.3.0 // indirect
+ github.com/coreos/go-systemd/v22 v22.3.2 // indirect
+ github.com/couchbase/gomemcached v0.1.3 // indirect
+ github.com/couchbase/goutils v0.1.0 // indirect
+ github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76 // indirect
+ github.com/davecgh/go-spew v1.1.1 // indirect
+ github.com/edsrzf/mmap-go v1.0.0 // indirect
+ github.com/go-logfmt/logfmt v0.5.0 // indirect
+ github.com/go-logr/logr v1.2.3 // indirect
+ github.com/go-logr/stdr v1.2.2 // indirect
+ github.com/golang/protobuf v1.5.2 // indirect
+ github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db // indirect
+ github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
+ github.com/pmezard/go-difflib v1.0.0 // indirect
+ github.com/prometheus/client_model v0.2.0 // indirect
+ github.com/prometheus/common v0.32.1 // indirect
+ github.com/prometheus/procfs v0.7.3 // indirect
+ github.com/siddontang/go v0.0.0-20170517070808-cb568a3e5cc0 // indirect
+ github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d // indirect
+ github.com/syndtr/goleveldb v0.0.0-20160425020131-cfa635847112 // indirect
+ go.etcd.io/etcd/api/v3 v3.5.4 // indirect
+ go.etcd.io/etcd/client/pkg/v3 v3.5.4 // indirect
+ go.uber.org/atomic v1.7.0 // indirect
+ go.uber.org/multierr v1.6.0 // indirect
+ go.uber.org/zap v1.17.0 // indirect
+ golang.org/x/net v0.0.0-20210525063256-abc453219eb5 // indirect
+ golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect
+ golang.org/x/text v0.3.6 // indirect
+ google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect
+)
+
+replace github.com/gomodule/redigo => github.com/gomodule/redigo v1.8.8
diff --git a/go.sum b/go.sum
index d9f9a12f..72b8a53b 100644
--- a/go.sum
+++ b/go.sum
@@ -1,6 +1,38 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
+cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
+cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
+cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
+cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
+cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
+cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
+cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
+cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
+cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
+cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
+cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
+cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
+cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
+cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
+cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
+cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
+cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
+cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
+cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
+cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
+cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
+cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
+cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
+cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
+cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
+cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
+cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
+cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
+cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
+dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
@@ -38,8 +70,12 @@ github.com/casbin/casbin v1.9.1/go.mod h1:z8uPsfBJGUsnkagrt3G8QvjgTKFMBJ32UP8HpZ
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
-github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
+github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
+github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
+github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58 h1:F1EaeKL/ta07PY/k9Os/UFtwERei2/XzGemhpGnBKNg=
@@ -51,7 +87,6 @@ github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
-github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7 h1:u9SHYsPQNyt5tgDm3YN7+9dYrpK96E5wFilTFWIDZOM=
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
@@ -91,10 +126,12 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
-github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/glendc/gopher-json v0.0.0-20170414221815-dc4743023d0c/go.mod h1:Gja1A+xZ9BoviGJNA2E9vFkPjjsl+CoJxSXiQM1UXtw=
+github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
+github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
+github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo=
@@ -104,6 +141,11 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
+github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
+github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
+github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-redis/redis/v7 v7.4.0 h1:7obg6wUoj05T0EpY0o8B59S9w5yeMWql7sw2kwNW1x4=
github.com/go-redis/redis/v7 v7.4.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
@@ -121,11 +163,21 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
+github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
+github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
@@ -140,24 +192,38 @@ github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
-github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0=
-github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
+github.com/gomodule/redigo v1.8.8 h1:f6cXq6RRfiyrOJEV7p3JhLDlmawGBVBBP1MggY8Mo4E=
+github.com/gomodule/redigo v1.8.8/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
+github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
+github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
+github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
+github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
+github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
+github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
@@ -193,6 +259,7 @@ github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/J
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
+github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
@@ -203,6 +270,9 @@ github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/u
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
+github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
+github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
@@ -218,8 +288,8 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/ledisdb/ledisdb v0.0.0-20200510135210-d35789ec47e6 h1:wxyqOzKxsRJ6vVRL9sXQ64Z45wmBuQ+OTH9sLsC5rKc=
github.com/ledisdb/ledisdb v0.0.0-20200510135210-d35789ec47e6/go.mod h1:n931TsDuKuq+uX4v1fulaMbA/7ZLLhjc85h7chZGBCQ=
-github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8=
-github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
+github.com/lib/pq v1.10.5 h1:J+gdV2cUmX7ZqL2B0lFcW0m+egaHC2V3lpO8nWxyYiQ=
+github.com/lib/pq v1.10.5/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
@@ -239,12 +309,13 @@ github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS4
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
-github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
-github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs=
+github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
@@ -302,8 +373,10 @@ github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
-github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ=
github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
+github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
+github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk=
+github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
@@ -315,15 +388,17 @@ github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
-github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
+github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4=
+github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
-github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
+github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
+github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
@@ -360,8 +435,9 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
-github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/syndtr/goleveldb v0.0.0-20160425020131-cfa635847112 h1:NBrpnvz0pDPf3+HXZ1C9GcJd1DTpWDLcLWZhNq6uP7o=
github.com/syndtr/goleveldb v0.0.0-20160425020131-cfa635847112/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
@@ -369,22 +445,31 @@ github.com/ugorji/go v0.0.0-20171122102828-84cb69a8af83/go.mod h1:hnLbHMwcvSihnD
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
+github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/gopher-lua v0.0.0-20171031051903-609c9cd26973/go.mod h1:aEV29XrmTYFr3CiRxZeGHpkvbwq+prZduBqMaascyCU=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
-go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738 h1:VcrIfasaLFkyjk6KNlXQSzO+B0fZcnECiDrKJsfxka0=
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
-go.etcd.io/etcd/api/v3 v3.5.0 h1:GsV3S+OfZEOCNXdtNkBSR7kgLobAa/SO6tCxRa0GAYw=
-go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
-go.etcd.io/etcd/client/pkg/v3 v3.5.0 h1:2aQv6F436YnN7I4VbI8PPYrBhu+SmrTaADcf8Mi/6PU=
-go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
-go.etcd.io/etcd/client/v3 v3.5.0 h1:62Eh0XOro+rDwkrypAGDfgmNh5Joq+z+W9HZdlXMzek=
-go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0=
+go.etcd.io/etcd/api/v3 v3.5.4 h1:OHVyt3TopwtUQ2GKdd5wu3PmmipR4FTwCqoEjSyRdIc=
+go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A=
+go.etcd.io/etcd/client/pkg/v3 v3.5.4 h1:lrneYvz923dvC14R54XcA7FXoZ3mlGZAgmwhfm7HqOg=
+go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
+go.etcd.io/etcd/client/v3 v3.5.4 h1:p83BUL3tAYS0OT/r0qglgc3M1JjhM0diV8DSWAhVXv4=
+go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
+go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
+go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opentelemetry.io/otel v1.7.0 h1:Z2lA3Tdch0iDcrhJXDIlC94XE+bxok1F9B+4Lz/lGsM=
+go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk=
+go.opentelemetry.io/otel/trace v1.7.0 h1:O37Iogk1lEkMRXewVtZ1BBTVn5JEp8GrJvP92bJqC6o=
+go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48yyE4TNvoHqU=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
@@ -402,20 +487,41 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
+golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
+golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
+golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
+golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
+golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
+golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
+golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
+golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
+golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
+golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
+golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
@@ -431,27 +537,47 @@ golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
+golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
+golang.org/x/net v0.0.0-20210525063256-abc453219eb5 h1:wjuX4b5yYQnEQHzd+CBcrcC6OVR2J1CN6mUy0oSxIPo=
+golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
+golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
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-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/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-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -464,33 +590,59 @@ golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40 h1:JWgyZ1qgdTaF3N3oxC+MdTV7qvEEgHo3otj+HB5CM7Q=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
+golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -498,16 +650,47 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
+golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
+golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
+golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
+golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -516,16 +699,60 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
+google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
+google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
+google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
+google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
+google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
+google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
+google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
+google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
+google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
+google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
+google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
+google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
+google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
+google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
+google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c h1:wtujag7C+4D6KMoulW9YauvK2lgdvCMS260jsqqBXr0=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
@@ -533,12 +760,18 @@ google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZi
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
+google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
+google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
+google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
@@ -550,6 +783,7 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
@@ -585,8 +819,15 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
+honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
+rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
+rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
+rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
diff --git a/server/web/adminui.go b/server/web/adminui.go
index 54d67354..75a8badc 100644
--- a/server/web/adminui.go
+++ b/server/web/adminui.go
@@ -21,10 +21,10 @@ var indexTpl = `
For detail usage please check our document:
-Toolbox
+Toolbox
-Live Monitor
+Live Monitor
{{.Content}}
{{end}}`
diff --git a/server/web/context/context.go b/server/web/context/context.go
index 42cc4035..e165527b 100644
--- a/server/web/context/context.go
+++ b/server/web/context/context.go
@@ -19,7 +19,7 @@
//
// ctx := context.Context{Request:req,ResponseWriter:rw}
//
-// more docs http://beego.me/docs/module/context.md
+// more docs http://beego.vip/docs/module/context.md
package context
import (
diff --git a/server/web/doc.go b/server/web/doc.go
index 48c21342..0bde987e 100644
--- a/server/web/doc.go
+++ b/server/web/doc.go
@@ -12,6 +12,6 @@ beego is inspired by Tornado, Sinatra and Flask with the added benefit of some G
beego.Run()
}
-more information: http://beego.me
+more information: http://beego.vip
*/
package web
diff --git a/server/web/grace/grace.go b/server/web/grace/grace.go
index 96ae10ef..bad7e61d 100644
--- a/server/web/grace/grace.go
+++ b/server/web/grace/grace.go
@@ -105,8 +105,17 @@ func init() {
}
}
+// ServerOption configures how we set up the connection.
+type ServerOption func(*Server)
+
+func WithShutdownCallback(shutdownCallback func()) ServerOption {
+ return func(srv *Server) {
+ srv.shutdownCallbacks = append(srv.shutdownCallbacks, shutdownCallback)
+ }
+}
+
// NewServer returns a new graceServer.
-func NewServer(addr string, handler http.Handler) (srv *Server) {
+func NewServer(addr string, handler http.Handler, opts ...ServerOption) (srv *Server) {
regLock.Lock()
defer regLock.Unlock()
@@ -148,6 +157,10 @@ func NewServer(addr string, handler http.Handler) (srv *Server) {
Handler: handler,
}
+ for _, opt := range opts {
+ opt(srv)
+ }
+
runningServersOrder = append(runningServersOrder, addr)
runningServers[addr] = srv
return srv
diff --git a/server/web/grace/server.go b/server/web/grace/server.go
index 5546546d..e9d36a00 100644
--- a/server/web/grace/server.go
+++ b/server/web/grace/server.go
@@ -20,31 +20,41 @@ import (
// Server embedded http.Server
type Server struct {
*http.Server
- ln net.Listener
- SignalHooks map[int]map[os.Signal][]func()
- sigChan chan os.Signal
- isChild bool
- state uint8
- Network string
- terminalChan chan error
+ ln net.Listener
+ SignalHooks map[int]map[os.Signal][]func()
+ sigChan chan os.Signal
+ isChild bool
+ state uint8
+ Network string
+ terminalChan chan error
+ shutdownCallbacks []func()
}
// Serve accepts incoming connections on the Listener l
// and creates a new service goroutine for each.
// The service goroutines read requests and then call srv.Handler to reply to them.
func (srv *Server) Serve() (err error) {
+ return srv.internalServe(srv.ln)
+}
+
+func (srv *Server) ServeWithListener(ln net.Listener) (err error) {
+ go srv.handleSignals()
+ return srv.internalServe(ln)
+}
+
+func (srv *Server) internalServe(ln net.Listener) (err error) {
srv.state = StateRunning
defer func() { srv.state = StateTerminate }()
// When Shutdown is called, Serve, ListenAndServe, and ListenAndServeTLS
// immediately return ErrServerClosed. Make sure the program doesn't exit
// and waits instead for Shutdown to return.
- if err = srv.Server.Serve(srv.ln); err != nil && err != http.ErrServerClosed {
+ if err = srv.Server.Serve(ln); err != nil && err != http.ErrServerClosed {
log.Println(syscall.Getpid(), "Server.Serve() error:", err)
return err
}
- log.Println(syscall.Getpid(), srv.ln.Addr(), "Listener closed.")
+ log.Println(syscall.Getpid(), ln.Addr(), "Listener closed.")
// wait for Shutdown to return
if shutdownErr := <-srv.terminalChan; shutdownErr != nil {
return shutdownErr
@@ -95,6 +105,15 @@ func (srv *Server) ListenAndServe() (err error) {
//
// If srv.Addr is blank, ":https" is used.
func (srv *Server) ListenAndServeTLS(certFile, keyFile string) (err error) {
+ ln, err := srv.ListenTLS(certFile, keyFile)
+ if err != nil {
+ return err
+ }
+
+ return srv.ServeTLS(ln)
+}
+
+func (srv *Server) ListenTLS(certFile string, keyFile string) (net.Listener, error) {
addr := srv.Addr
if addr == "" {
addr = ":https"
@@ -108,20 +127,35 @@ func (srv *Server) ListenAndServeTLS(certFile, keyFile string) (err error) {
}
srv.TLSConfig.Certificates = make([]tls.Certificate, 1)
- srv.TLSConfig.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
+ cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
- return
+ return nil, err
}
+ srv.TLSConfig.Certificates[0] = cert
go srv.handleSignals()
ln, err := srv.getListener(addr)
if err != nil {
log.Println(err)
+ return nil, err
+ }
+ tlsListener := tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, srv.TLSConfig)
+ return tlsListener, nil
+}
+
+// ListenAndServeMutualTLS listens on the TCP network address srv.Addr and then calls
+// Serve to handle requests on incoming mutual TLS connections.
+func (srv *Server) ListenAndServeMutualTLS(certFile, keyFile, trustFile string) (err error) {
+ ln, err := srv.ListenMutualTLS(certFile, keyFile, trustFile)
+ if err != nil {
return err
}
- srv.ln = tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, srv.TLSConfig)
+ return srv.ServeTLS(ln)
+}
+
+func (srv *Server) ServeTLS(ln net.Listener) error {
if srv.isChild {
process, err := os.FindProcess(os.Getppid())
if err != nil {
@@ -134,13 +168,12 @@ func (srv *Server) ListenAndServeTLS(certFile, keyFile string) (err error) {
}
}
+ go srv.handleSignals()
log.Println(os.Getpid(), srv.Addr)
- return srv.Serve()
+ return srv.internalServe(ln)
}
-// ListenAndServeMutualTLS listens on the TCP network address srv.Addr and then calls
-// Serve to handle requests on incoming mutual TLS connections.
-func (srv *Server) ListenAndServeMutualTLS(certFile, keyFile, trustFile string) (err error) {
+func (srv *Server) ListenMutualTLS(certFile string, keyFile string, trustFile string) (net.Listener, error) {
addr := srv.Addr
if addr == "" {
addr = ":https"
@@ -154,16 +187,17 @@ func (srv *Server) ListenAndServeMutualTLS(certFile, keyFile, trustFile string)
}
srv.TLSConfig.Certificates = make([]tls.Certificate, 1)
- srv.TLSConfig.Certificates[0], err = tls.LoadX509KeyPair(certFile, keyFile)
+ cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil {
- return
+ return nil, err
}
+ srv.TLSConfig.Certificates[0] = cert
srv.TLSConfig.ClientAuth = tls.RequireAndVerifyClientCert
pool := x509.NewCertPool()
data, err := ioutil.ReadFile(trustFile)
if err != nil {
log.Println(err)
- return err
+ return nil, err
}
pool.AppendCertsFromPEM(data)
srv.TLSConfig.ClientCAs = pool
@@ -173,24 +207,10 @@ func (srv *Server) ListenAndServeMutualTLS(certFile, keyFile, trustFile string)
ln, err := srv.getListener(addr)
if err != nil {
log.Println(err)
- return err
+ return nil, err
}
- srv.ln = tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, srv.TLSConfig)
-
- if srv.isChild {
- process, err := os.FindProcess(os.Getppid())
- if err != nil {
- log.Println(err)
- return err
- }
- err = process.Signal(syscall.SIGTERM)
- if err != nil {
- return err
- }
- }
-
- log.Println(os.Getpid(), srv.Addr)
- return srv.Serve()
+ tlsListener := tls.NewListener(tcpKeepAliveListener{ln.(*net.TCPListener)}, srv.TLSConfig)
+ return tlsListener, nil
}
// getListener either opens a new socket to listen on, or takes the acceptor socket
@@ -292,6 +312,9 @@ func (srv *Server) shutdown() {
ctx, cancel = context.WithTimeout(context.Background(), DefaultTimeout)
defer cancel()
}
+ for _, shutdownCallback := range srv.shutdownCallbacks {
+ shutdownCallback()
+ }
srv.terminalChan <- srv.Server.Shutdown(ctx)
}
diff --git a/server/web/namespace.go b/server/web/namespace.go
index 825aa4b8..8da8a797 100644
--- a/server/web/namespace.go
+++ b/server/web/namespace.go
@@ -48,7 +48,7 @@ func NewNamespace(prefix string, params ...LinkNamespace) *Namespace {
// if cond return true can run this namespace, else can't
// usage:
// ns.Cond(func (ctx *context.Context) bool{
-// if ctx.Input.Domain() == "api.beego.me" {
+// if ctx.Input.Domain() == "api.beego.vip" {
// return true
// }
// return false
diff --git a/server/web/namespace_test.go b/server/web/namespace_test.go
index e0e15d6f..9451a525 100644
--- a/server/web/namespace_test.go
+++ b/server/web/namespace_test.go
@@ -174,7 +174,7 @@ func TestNamespaceCond(t *testing.T) {
ns := NewNamespace("/v2")
ns.Cond(func(ctx *context.Context) bool {
- return ctx.Input.Domain() == "beego.me"
+ return ctx.Input.Domain() == "beego.vip"
}).
AutoRouter(&TestController{})
AddNamespace(ns)
diff --git a/server/web/router.go b/server/web/router.go
index c4400b20..e37da0b7 100644
--- a/server/web/router.go
+++ b/server/web/router.go
@@ -132,6 +132,10 @@ func (c *ControllerInfo) GetPattern() string {
return c.pattern
}
+func (c *ControllerInfo) GetMethod() map[string]string {
+ return c.methods
+}
+
func WithRouterMethods(ctrlInterface ControllerInterface, mappingMethod ...string) ControllerOption {
return func(c *ControllerInfo) {
c.methods = parseMappingMethods(ctrlInterface, mappingMethod)
@@ -1315,6 +1319,32 @@ func (p *ControllerRegister) FindRouter(context *beecontext.Context) (routerInfo
return
}
+// GetAllControllerInfo get all ControllerInfo
+func (p *ControllerRegister) GetAllControllerInfo() (routerInfos []*ControllerInfo) {
+ for _, webTree := range p.routers {
+ composeControllerInfos(webTree, &routerInfos)
+ }
+ return
+}
+
+func composeControllerInfos(tree *Tree, routerInfos *[]*ControllerInfo) {
+ if tree.fixrouters != nil {
+ for _, subTree := range tree.fixrouters {
+ composeControllerInfos(subTree, routerInfos)
+ }
+ }
+ if tree.wildcard != nil {
+ composeControllerInfos(tree.wildcard, routerInfos)
+ }
+ if tree.leaves != nil {
+ for _, l := range tree.leaves {
+ if c, ok := l.runObject.(*ControllerInfo); ok {
+ *routerInfos = append(*routerInfos, c)
+ }
+ }
+ }
+}
+
func toURL(params map[string]string) string {
if len(params) == 0 {
return ""
diff --git a/server/web/router_test.go b/server/web/router_test.go
index 5009d24e..95e4937d 100644
--- a/server/web/router_test.go
+++ b/server/web/router_test.go
@@ -19,6 +19,8 @@ import (
"fmt"
"net/http"
"net/http/httptest"
+ "reflect"
+ "sort"
"strings"
"testing"
@@ -1097,3 +1099,32 @@ func TestRouterAddRouterPointerMethodPanicNotImplementInterface(t *testing.T) {
handler := NewControllerRegister()
handler.AddRouterMethod(method, "/user", (*TestControllerWithInterface).PingPointer)
}
+
+func TestGetAllControllerInfo(t *testing.T) {
+ handler := NewControllerRegister()
+ handler.Add("/level1", &TestController{}, WithRouterMethods(&TestController{}, "get:Get"))
+ handler.Add("/level1/level2", &TestController{}, WithRouterMethods(&TestController{}, "get:Get"))
+ handler.Add("/:name1", &TestController{}, WithRouterMethods(&TestController{}, "post:Post"))
+
+ var actualPatterns []string
+ var actualMethods []string
+ for _, controllerInfo := range handler.GetAllControllerInfo() {
+ actualPatterns = append(actualPatterns, controllerInfo.GetPattern())
+ for _, httpMethod := range controllerInfo.GetMethod() {
+ actualMethods = append(actualMethods, httpMethod)
+ }
+ }
+ sort.Strings(actualPatterns)
+ expectedPatterns := []string{"/level1", "/level1/level2", "/:name1"}
+ sort.Strings(expectedPatterns)
+ if !reflect.DeepEqual(actualPatterns, expectedPatterns) {
+ t.Errorf("ControllerInfo.GetMethod expected %#v, but %#v got", expectedPatterns, actualPatterns)
+ }
+
+ sort.Strings(actualMethods)
+ expectedMethods := []string{"Get", "Get", "Post"}
+ sort.Strings(expectedMethods)
+ if !reflect.DeepEqual(actualMethods, expectedMethods) {
+ t.Errorf("ControllerInfo.GetMethod expected %#v, but %#v got", expectedMethods, actualMethods)
+ }
+}
diff --git a/server/web/server.go b/server/web/server.go
index ec9b6ef9..0011d455 100644
--- a/server/web/server.go
+++ b/server/web/server.go
@@ -49,9 +49,10 @@ func init() {
// HttpServer defines beego application with a new PatternServeMux.
type HttpServer struct {
- Handlers *ControllerRegister
- Server *http.Server
- Cfg *Config
+ Handlers *ControllerRegister
+ Server *http.Server
+ Cfg *Config
+ LifeCycleCallbacks []LifeCycleCallback
}
// NewHttpSever returns a new beego application.
@@ -76,6 +77,13 @@ func NewHttpServerWithCfg(cfg *Config) *HttpServer {
// MiddleWare function for http.Handler
type MiddleWare func(http.Handler) http.Handler
+// LifeCycleCallback configures callback.
+// Developer can implement this interface to add custom logic to server lifecycle
+type LifeCycleCallback interface {
+ AfterStart(app *HttpServer)
+ BeforeShutdown(app *HttpServer)
+}
+
// Run beego application.
func (app *HttpServer) Run(addr string, mws ...MiddleWare) {
initBeforeHTTPRun()
@@ -98,12 +106,18 @@ func (app *HttpServer) Run(addr string, mws ...MiddleWare) {
// run cgi server
if app.Cfg.Listen.EnableFcgi {
+ for _, lifeCycleCallback := range app.LifeCycleCallbacks {
+ lifeCycleCallback.AfterStart(app)
+ }
if app.Cfg.Listen.EnableStdIo {
if err = fcgi.Serve(nil, app.Handlers); err == nil { // standard I/O
logs.Info("Use FCGI via standard I/O")
} else {
logs.Critical("Cannot use FCGI via standard I/O", err)
}
+ for _, lifeCycleCallback := range app.LifeCycleCallbacks {
+ lifeCycleCallback.BeforeShutdown(app)
+ }
return
}
if app.Cfg.Listen.HTTPPort == 0 {
@@ -116,11 +130,14 @@ func (app *HttpServer) Run(addr string, mws ...MiddleWare) {
l, err = net.Listen("tcp", addr)
}
if err != nil {
- logs.Critical("Listen: ", err)
+ logs.Critical("Listen for Fcgi: ", err)
}
if err = fcgi.Serve(l, app.Handlers); err != nil {
logs.Critical("fcgi.Serve: ", err)
}
+ for _, lifeCycleCallback := range app.LifeCycleCallbacks {
+ lifeCycleCallback.BeforeShutdown(app)
+ }
return
}
@@ -137,6 +154,14 @@ func (app *HttpServer) Run(addr string, mws ...MiddleWare) {
// run graceful mode
if app.Cfg.Listen.Graceful {
+ var opts []grace.ServerOption
+ for _, lifeCycleCallback := range app.LifeCycleCallbacks {
+ lifeCycleCallbackDup := lifeCycleCallback
+ opts = append(opts, grace.WithShutdownCallback(func() {
+ lifeCycleCallbackDup.BeforeShutdown(app)
+ }))
+ }
+
httpsAddr := app.Cfg.Listen.HTTPSAddr
app.Server.Addr = httpsAddr
if app.Cfg.Listen.EnableHTTPS || app.Cfg.Listen.EnableMutualHTTPS {
@@ -146,15 +171,16 @@ func (app *HttpServer) Run(addr string, mws ...MiddleWare) {
httpsAddr = fmt.Sprintf("%s:%d", app.Cfg.Listen.HTTPSAddr, app.Cfg.Listen.HTTPSPort)
app.Server.Addr = httpsAddr
}
- server := grace.NewServer(httpsAddr, app.Server.Handler)
+ server := grace.NewServer(httpsAddr, app.Server.Handler, opts...)
server.Server.ReadTimeout = app.Server.ReadTimeout
server.Server.WriteTimeout = app.Server.WriteTimeout
+ var ln net.Listener
if app.Cfg.Listen.EnableMutualHTTPS {
- if err := server.ListenAndServeMutualTLS(app.Cfg.Listen.HTTPSCertFile,
+ if ln, err = server.ListenMutualTLS(app.Cfg.Listen.HTTPSCertFile,
app.Cfg.Listen.HTTPSKeyFile,
app.Cfg.Listen.TrustCaFile); err != nil {
- logs.Critical("ListenAndServeTLS: ", err, fmt.Sprintf("%d", os.Getpid()))
- time.Sleep(100 * time.Microsecond)
+ logs.Critical("ListenMutualTLS: ", err, fmt.Sprintf("%d", os.Getpid()))
+ return
}
} else {
if app.Cfg.Listen.AutoTLS {
@@ -166,24 +192,40 @@ func (app *HttpServer) Run(addr string, mws ...MiddleWare) {
app.Server.TLSConfig = &tls.Config{GetCertificate: m.GetCertificate}
app.Cfg.Listen.HTTPSCertFile, app.Cfg.Listen.HTTPSKeyFile = "", ""
}
- if err := server.ListenAndServeTLS(app.Cfg.Listen.HTTPSCertFile, app.Cfg.Listen.HTTPSKeyFile); err != nil {
- logs.Critical("ListenAndServeTLS: ", err, fmt.Sprintf("%d", os.Getpid()))
- time.Sleep(100 * time.Microsecond)
+ if ln, err = server.ListenTLS(app.Cfg.Listen.HTTPSCertFile, app.Cfg.Listen.HTTPSKeyFile); err != nil {
+ logs.Critical("ListenTLS: ", err, fmt.Sprintf("%d", os.Getpid()))
+ return
}
}
+ for _, callback := range app.LifeCycleCallbacks {
+ callback.AfterStart(app)
+ }
+ if err = server.ServeTLS(ln); err != nil {
+ logs.Critical("ServeTLS: ", err, fmt.Sprintf("%d", os.Getpid()))
+ time.Sleep(100 * time.Microsecond)
+ }
endRunning <- true
}()
}
if app.Cfg.Listen.EnableHTTP {
go func() {
- server := grace.NewServer(addr, app.Server.Handler)
+ server := grace.NewServer(addr, app.Server.Handler, opts...)
server.Server.ReadTimeout = app.Server.ReadTimeout
server.Server.WriteTimeout = app.Server.WriteTimeout
if app.Cfg.Listen.ListenTCP4 {
server.Network = "tcp4"
}
- if err := server.ListenAndServe(); err != nil {
- logs.Critical("ListenAndServe: ", err, fmt.Sprintf("%d", os.Getpid()))
+ ln, err := net.Listen(server.Network, app.Server.Addr)
+ if err != nil {
+ logs.Critical("Listen for HTTP[graceful mode]: ", err)
+ endRunning <- true
+ return
+ }
+ for _, callback := range app.LifeCycleCallbacks {
+ callback.AfterStart(app)
+ }
+ if err := server.ServeWithListener(ln); err != nil {
+ logs.Critical("ServeWithListener: ", err, fmt.Sprintf("%d", os.Getpid()))
time.Sleep(100 * time.Microsecond)
}
endRunning <- true
@@ -239,13 +281,13 @@ func (app *HttpServer) Run(addr string, mws ...MiddleWare) {
if app.Cfg.Listen.ListenTCP4 {
ln, err := net.Listen("tcp4", app.Server.Addr)
if err != nil {
- logs.Critical("ListenAndServe: ", err)
+ logs.Critical("Listen for HTTP[normal mode]: ", err)
time.Sleep(100 * time.Microsecond)
endRunning <- true
return
}
if err = app.Server.Serve(ln); err != nil {
- logs.Critical("ListenAndServe: ", err)
+ logs.Critical("Serve: ", err)
time.Sleep(100 * time.Microsecond)
endRunning <- true
return
diff --git a/server/web/session/couchbase/sess_couchbase.go b/server/web/session/couchbase/sess_couchbase.go
index b9075040..029d0637 100644
--- a/server/web/session/couchbase/sess_couchbase.go
+++ b/server/web/session/couchbase/sess_couchbase.go
@@ -29,7 +29,7 @@
// go globalSessions.GC()
// }
//
-// more docs: http://beego.me/docs/module/session.md
+// more docs: http://beego.vip/docs/module/session.md
package couchbase
import (
diff --git a/server/web/session/memcache/sess_memcache.go b/server/web/session/memcache/sess_memcache.go
index 11aee787..12a68f71 100644
--- a/server/web/session/memcache/sess_memcache.go
+++ b/server/web/session/memcache/sess_memcache.go
@@ -29,7 +29,7 @@
// go globalSessions.GC()
// }
//
-// more docs: http://beego.me/docs/module/session.md
+// more docs: http://beego.vip/docs/module/session.md
package memcache
import (
diff --git a/server/web/session/mysql/sess_mysql.go b/server/web/session/mysql/sess_mysql.go
index 2755bded..c53e0572 100644
--- a/server/web/session/mysql/sess_mysql.go
+++ b/server/web/session/mysql/sess_mysql.go
@@ -37,7 +37,7 @@
// go globalSessions.GC()
// }
//
-// more docs: http://beego.me/docs/module/session.md
+// more docs: http://beego.vip/docs/module/session.md
package mysql
import (
diff --git a/server/web/session/postgres/sess_postgresql.go b/server/web/session/postgres/sess_postgresql.go
index 9914cc0c..fc22c378 100644
--- a/server/web/session/postgres/sess_postgresql.go
+++ b/server/web/session/postgres/sess_postgresql.go
@@ -47,7 +47,7 @@
// go globalSessions.GC()
// }
//
-// more docs: http://beego.me/docs/module/session.md
+// more docs: http://beego.vip/docs/module/session.md
package postgres
import (
diff --git a/server/web/session/redis/sess_redis.go b/server/web/session/redis/sess_redis.go
index acc25f78..2b533374 100644
--- a/server/web/session/redis/sess_redis.go
+++ b/server/web/session/redis/sess_redis.go
@@ -29,7 +29,7 @@
// go globalSessions.GC()
// }
//
-// more docs: http://beego.me/docs/module/session.md
+// more docs: http://beego.vip/docs/module/session.md
package redis
import (
diff --git a/server/web/session/redis_cluster/redis_cluster.go b/server/web/session/redis_cluster/redis_cluster.go
index 4db3bbe9..4727787c 100644
--- a/server/web/session/redis_cluster/redis_cluster.go
+++ b/server/web/session/redis_cluster/redis_cluster.go
@@ -29,7 +29,7 @@
// go globalSessions.GC()
// }
//
-// more docs: http://beego.me/docs/module/session.md
+// more docs: http://beego.vip/docs/module/session.md
package redis_cluster
import (
diff --git a/server/web/session/session.go b/server/web/session/session.go
index 881de8ea..b5300abc 100644
--- a/server/web/session/session.go
+++ b/server/web/session/session.go
@@ -24,7 +24,7 @@
// go globalSessions.GC()
// }
//
-// more docs: http://beego.me/docs/module/session.md
+// more docs: http://beego.vip/docs/module/session.md
package session
import (
diff --git a/server/web/templatefunc.go b/server/web/templatefunc.go
index c0db9990..a44784d8 100644
--- a/server/web/templatefunc.go
+++ b/server/web/templatefunc.go
@@ -242,7 +242,7 @@ func Htmlunquote(text string) string {
// /login?next=/
// /user/John%20Doe
//
-// more detail http://beego.me/docs/mvc/controller/urlbuilding.md
+// more detail http://beego.vip/docs/mvc/controller/urlbuilding.md
func URLFor(endpoint string, values ...interface{}) string {
return BeeApp.Handlers.URLFor(endpoint, values...)
}
diff --git a/server/web/tree.go b/server/web/tree.go
index 24a58a01..3e0b86c5 100644
--- a/server/web/tree.go
+++ b/server/web/tree.go
@@ -341,9 +341,9 @@ func (t *Tree) match(treePattern string, pattern string, wildcardValues []string
if runObject == nil && len(t.fixrouters) > 0 {
// Filter the .json .xml .html extension
for _, str := range allowSuffixExt {
- if strings.HasSuffix(seg, str) && strings.HasSuffix(treePattern, seg) {
+ // pattern == "" avoid cases: /aaa.html/aaa.html could access /aaa/:bbb
+ if strings.HasSuffix(seg, str) && pattern == "" {
for _, subTree := range t.fixrouters {
- // strings.HasSuffix(treePattern, seg) avoid cases: /aaa.html/bbb could access /aaa/bbb
if subTree.prefix == seg[:len(seg)-len(str)] {
runObject = subTree.match(treePattern, pattern, wildcardValues, ctx)
if runObject != nil {
diff --git a/server/web/tree_test.go b/server/web/tree_test.go
index 2e7fa6ce..f43c4a87 100644
--- a/server/web/tree_test.go
+++ b/server/web/tree_test.go
@@ -122,6 +122,9 @@ func init() {
notMatchTestInfo(abcSuffix, "/abc/suffix.html/a"),
matchTestInfo(abcSuffix, "/abc/suffix/a", nil),
notMatchTestInfo(abcSuffix, "/abc.j/suffix/a"),
+ // test for fix of issue 4946
+ notMatchTestInfo("/suffix/:name", "/suffix.html/suffix.html"),
+ matchTestInfo("/suffix/:id/name", "/suffix/1234/name.html", map[string]string{":id": "1234", ":ext": "html"}),
}
}
diff --git a/sonar-project.properties b/sonar-project.properties
index 1a12fb33..dbd5d6ae 100644
--- a/sonar-project.properties
+++ b/sonar-project.properties
@@ -4,4 +4,4 @@ sonar.projectKey=beego_beego
# relative paths to source directories. More details and properties are described
# in https://sonarcloud.io/documentation/project-administration/narrowing-the-focus/
sonar.sources=.
-sonar.exclusions=**/*_test.go
\ No newline at end of file
+sonar.exclusions=**/*_test.go