bump go modules, fix StartTLS email notifications
In #1359, we discovered that StartTLS was not working\ due to the wrong host passed. This bumps the library for the fix. Also, after a switch to go-pkgz/notify MailGun email sending broke due to the difference in the destination email parsing, the fix is also applied after this commit.
This commit is contained in:
committed by
Umputun
parent
9049d7a616
commit
3b5f44da46
@@ -18,12 +18,12 @@ require (
|
||||
github.com/aymerick/douceur v0.2.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/didip/tollbooth/v6 v6.1.2 // indirect
|
||||
github.com/didip/tollbooth_chi v0.0.0-20200828173446-a7173453ea21 // indirect
|
||||
github.com/didip/tollbooth_chi v0.0.0-20220429013743-da966f2f674b // indirect
|
||||
github.com/dlclark/regexp2 v1.4.0 // indirect
|
||||
github.com/go-chi/chi v4.1.1+incompatible // indirect
|
||||
github.com/go-chi/render v1.0.1 // indirect
|
||||
github.com/go-pkgz/expirable-cache v0.0.3 // indirect
|
||||
github.com/go-pkgz/rest v1.14.0 // indirect
|
||||
github.com/go-pkgz/rest v1.15.0 // indirect
|
||||
github.com/gorilla/css v1.0.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
@@ -35,7 +35,7 @@ require (
|
||||
github.com/stretchr/objx v0.3.0 // indirect
|
||||
go.etcd.io/bbolt v1.3.6 // indirect
|
||||
golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9 // indirect
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 // indirect
|
||||
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2 // indirect
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect
|
||||
golang.org/x/time v0.0.0-20220411224347-583f2d630306 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
|
||||
@@ -22,8 +22,8 @@ github.com/didip/tollbooth/v6 v6.0.1/go.mod h1:j2pKs+JQ5PvU/K4jFnrnwntrmfUbYLJE5
|
||||
github.com/didip/tollbooth/v6 v6.1.2 h1:Kdqxmqw9YTv0uKajBUiWQg+GURL/k4vy9gmLCL01PjQ=
|
||||
github.com/didip/tollbooth/v6 v6.1.2/go.mod h1:xjcse6CTHCLuOkzsWrEgdy9WPJFv+p/x6v+MyfP+O9s=
|
||||
github.com/didip/tollbooth_chi v0.0.0-20200524181329-8b84cd7183d9/go.mod h1:YWyIfq3y4ArRfWZ9XksmuusP+7Mad+T0iFZ0kv0XG/M=
|
||||
github.com/didip/tollbooth_chi v0.0.0-20200828173446-a7173453ea21 h1:x7YpwKSBIBcKe9I3aTNOqgSyJ6QKDdtOxnEkxBTsi9w=
|
||||
github.com/didip/tollbooth_chi v0.0.0-20200828173446-a7173453ea21/go.mod h1:0ZVa6kSzS011nfTC1rELyxK4tjVf6vqBnOv7oY2KlsA=
|
||||
github.com/didip/tollbooth_chi v0.0.0-20220429013743-da966f2f674b h1:elkngQhLBcyDIXwL9Z7AfXXbBszUEsLxqNw6WPF8Mtc=
|
||||
github.com/didip/tollbooth_chi v0.0.0-20220429013743-da966f2f674b/go.mod h1:0ZVa6kSzS011nfTC1rELyxK4tjVf6vqBnOv7oY2KlsA=
|
||||
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
|
||||
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
@@ -38,8 +38,8 @@ github.com/go-pkgz/jrpc v0.2.0/go.mod h1:wd8vtQ4CgtCnuqua6x2b1SKIgv0VSOh5Dn0uUIT
|
||||
github.com/go-pkgz/lgr v0.10.4 h1:l7qyFjqEZgwRgaQQSEp6tve4A3OU80VrfzpvtEX8ngw=
|
||||
github.com/go-pkgz/lgr v0.10.4/go.mod h1:CD0s1z6EFpIUplV067gitF77tn25JItzwHNKAPqeCF0=
|
||||
github.com/go-pkgz/rest v1.5.0/go.mod h1:nQaM3RhSTUAmbBZWY4hfe4buyeC9VckvhoCktiQXJxI=
|
||||
github.com/go-pkgz/rest v1.14.0 h1:brDLCzIGoe0IiUZqRFpsiCVM9m3L88A7z62qS0V9Yfk=
|
||||
github.com/go-pkgz/rest v1.14.0/go.mod h1:KUWAqbDteYGS/CiXftomQsKjtEOifXsJ36Ka0skYbmk=
|
||||
github.com/go-pkgz/rest v1.15.0 h1:v/BDqJF9robo85GME85GWJ7O/NjtAO0x7LvO4EqWNRE=
|
||||
github.com/go-pkgz/rest v1.15.0/go.mod h1:KUWAqbDteYGS/CiXftomQsKjtEOifXsJ36Ka0skYbmk=
|
||||
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
|
||||
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
@@ -88,8 +88,8 @@ golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9/go.mod h1:023OzeP/+EPmXeap
|
||||
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 h1:HVyaeDAYux4pnY+D/SiwmLOR36ewZ4iGQIIrtnuCjFA=
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2 h1:NWy5+hlRbC7HK+PmcXVUmW1IMyFce7to56IUvhUFm7Y=
|
||||
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
||||
@@ -46,7 +46,7 @@ func TestEmailNew(t *testing.T) {
|
||||
assert.Equal(t, smtpParams.Port, email.Port, "emailParams.Port unchanged after creation")
|
||||
assert.Equal(t, smtpParams.TLS, email.TLS, "emailParams.TLS unchanged after creation")
|
||||
assert.Equal(t, smtpParams.StartTLS, email.StartTLS, "emailParams.TLS unchanged after creation")
|
||||
assert.Equal(t, "email: with username 'test@username' at server test@host:1000 with TLS", email.String())
|
||||
assert.Equal(t, "email: with username 'test@username' at server test@host:1000 with TLS with StartTLS", email.String())
|
||||
}
|
||||
|
||||
func Test_initTemplatesErr(t *testing.T) {
|
||||
|
||||
+8
-9
@@ -7,17 +7,17 @@ require (
|
||||
github.com/PuerkitoBio/goquery v1.8.0
|
||||
github.com/alecthomas/chroma v0.10.0
|
||||
github.com/didip/tollbooth/v6 v6.1.2
|
||||
github.com/didip/tollbooth_chi v0.0.0-20200828173446-a7173453ea21
|
||||
github.com/didip/tollbooth_chi v0.0.0-20220429013743-da966f2f674b
|
||||
github.com/go-chi/chi/v5 v5.0.7
|
||||
github.com/go-chi/cors v1.2.0
|
||||
github.com/go-chi/cors v1.2.1
|
||||
github.com/go-chi/render v1.0.1
|
||||
github.com/go-pkgz/auth v1.19.0
|
||||
github.com/go-pkgz/jrpc v0.2.0
|
||||
github.com/go-pkgz/lcw v0.8.1
|
||||
github.com/go-pkgz/lgr v0.10.4
|
||||
github.com/go-pkgz/notify v0.0.0-20220429105545-bc5c80a54199
|
||||
github.com/go-pkgz/notify v0.1.1
|
||||
github.com/go-pkgz/repeater v1.1.3
|
||||
github.com/go-pkgz/rest v1.14.0
|
||||
github.com/go-pkgz/rest v1.15.0
|
||||
github.com/go-pkgz/syncs v1.2.0
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible
|
||||
github.com/google/uuid v1.3.0
|
||||
@@ -33,9 +33,9 @@ require (
|
||||
github.com/stretchr/testify v1.7.1
|
||||
go.etcd.io/bbolt v1.3.6
|
||||
go.uber.org/goleak v1.1.12
|
||||
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4
|
||||
golang.org/x/crypto v0.0.0-20220518034528-6f7dac969898
|
||||
golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4
|
||||
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -47,7 +47,7 @@ require (
|
||||
github.com/dlclark/regexp2 v1.4.0 // indirect
|
||||
github.com/go-chi/chi v4.1.1+incompatible // indirect
|
||||
github.com/go-oauth2/oauth2/v4 v4.4.3 // indirect
|
||||
github.com/go-pkgz/email v0.2.1-0.20220428155644-a7e5d837d02f // indirect
|
||||
github.com/go-pkgz/email v0.3.0 // indirect
|
||||
github.com/go-pkgz/expirable-cache v0.0.3 // indirect
|
||||
github.com/go-redis/redis/v7 v7.4.1 // indirect
|
||||
github.com/go-stack/stack v1.8.1 // indirect
|
||||
@@ -63,12 +63,11 @@ require (
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/slack-go/slack v0.10.3 // indirect
|
||||
github.com/stretchr/objx v0.3.0 // indirect
|
||||
github.com/valyala/fasthttp v1.35.0 // indirect
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||
github.com/xdg-go/scram v1.1.1 // indirect
|
||||
github.com/xdg-go/stringprep v1.0.3 // indirect
|
||||
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect
|
||||
go.mongodb.org/mongo-driver v1.9.0 // indirect
|
||||
go.mongodb.org/mongo-driver v1.9.1 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 // indirect
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect
|
||||
|
||||
+18
-23
@@ -73,9 +73,8 @@ github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6 h1:45bxf7AZMw
|
||||
github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
|
||||
github.com/alicebob/miniredis/v2 v2.11.4 h1:GsuyeunTx7EllZBU3/6Ji3dhMQZDpC9rLf1luJ+6M5M=
|
||||
github.com/alicebob/miniredis/v2 v2.11.4/go.mod h1:VL3UDEfAH59bSa7MuHMuFToxkqyHh69s/WUbYlOAuyg=
|
||||
github.com/andybalholm/brotli v1.0.0 h1:7UCwP93aiSfvWpapti8g88vVVGp2qqtGyePsSuDafo4=
|
||||
github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
|
||||
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c=
|
||||
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
@@ -106,8 +105,8 @@ github.com/didip/tollbooth/v6 v6.0.1/go.mod h1:j2pKs+JQ5PvU/K4jFnrnwntrmfUbYLJE5
|
||||
github.com/didip/tollbooth/v6 v6.1.2 h1:Kdqxmqw9YTv0uKajBUiWQg+GURL/k4vy9gmLCL01PjQ=
|
||||
github.com/didip/tollbooth/v6 v6.1.2/go.mod h1:xjcse6CTHCLuOkzsWrEgdy9WPJFv+p/x6v+MyfP+O9s=
|
||||
github.com/didip/tollbooth_chi v0.0.0-20200524181329-8b84cd7183d9/go.mod h1:YWyIfq3y4ArRfWZ9XksmuusP+7Mad+T0iFZ0kv0XG/M=
|
||||
github.com/didip/tollbooth_chi v0.0.0-20200828173446-a7173453ea21 h1:x7YpwKSBIBcKe9I3aTNOqgSyJ6QKDdtOxnEkxBTsi9w=
|
||||
github.com/didip/tollbooth_chi v0.0.0-20200828173446-a7173453ea21/go.mod h1:0ZVa6kSzS011nfTC1rELyxK4tjVf6vqBnOv7oY2KlsA=
|
||||
github.com/didip/tollbooth_chi v0.0.0-20220429013743-da966f2f674b h1:elkngQhLBcyDIXwL9Z7AfXXbBszUEsLxqNw6WPF8Mtc=
|
||||
github.com/didip/tollbooth_chi v0.0.0-20220429013743-da966f2f674b/go.mod h1:0ZVa6kSzS011nfTC1rELyxK4tjVf6vqBnOv7oY2KlsA=
|
||||
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
|
||||
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||
@@ -133,8 +132,8 @@ github.com/go-chi/chi v4.1.1+incompatible h1:MmTgB0R8Bt/jccxp+t6S/1VGIKdJw5J74CK
|
||||
github.com/go-chi/chi v4.1.1+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
|
||||
github.com/go-chi/chi/v5 v5.0.7 h1:rDTPXLDHGATaeHvVlLcR4Qe0zftYethFucbjVQ1PxU8=
|
||||
github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-chi/cors v1.2.0 h1:tV1g1XENQ8ku4Bq3K9ub2AtgG+p16SmzeMSGTwrOKdE=
|
||||
github.com/go-chi/cors v1.2.0/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
|
||||
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
|
||||
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
|
||||
github.com/go-chi/render v1.0.1 h1:4/5tis2cKaNdnv9zFLfXzcquC9HbeZgCnxGnKrltBS8=
|
||||
github.com/go-chi/render v1.0.1/go.mod h1:pq4Rr7HbnsdaeHagklXub+p6Wd16Af5l9koip1OvJns=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
@@ -144,8 +143,8 @@ github.com/go-oauth2/oauth2/v4 v4.4.3 h1:IiU3iAK5NEeZ4mUf5HV9tN7iNlx4AGUkIJ5M1C4
|
||||
github.com/go-oauth2/oauth2/v4 v4.4.3/go.mod h1:NR9Hugz5/Qe2OGxoPBhsTRNjnm/amC+z9+XTwt63rhs=
|
||||
github.com/go-pkgz/auth v1.19.0 h1:TTfbQvlqsuEhRpYAiY/uF5UGP+HWMc5CN2RAhN06ik0=
|
||||
github.com/go-pkgz/auth v1.19.0/go.mod h1:1pu95rx7tFfeIFq0pjQPwCeL6qGYH4+UxHJudhK0T7M=
|
||||
github.com/go-pkgz/email v0.2.1-0.20220428155644-a7e5d837d02f h1:beMw0mHR3m7yh0tl2CwRTAg2Pa9z2LGFzHNDiD93i2Y=
|
||||
github.com/go-pkgz/email v0.2.1-0.20220428155644-a7e5d837d02f/go.mod h1:TpnmSLkQW3FyICit2hn7WIhCUDrhCX6btzz5wS3wHRI=
|
||||
github.com/go-pkgz/email v0.3.0 h1:89FbVF6trHkdn2VVoXlBfZHkdYQ1vLmQ54OhdosaFtc=
|
||||
github.com/go-pkgz/email v0.3.0/go.mod h1:TpnmSLkQW3FyICit2hn7WIhCUDrhCX6btzz5wS3wHRI=
|
||||
github.com/go-pkgz/expirable-cache v0.0.3 h1:rTh6qNPp78z0bQE6HDhXBHUwqnV9i09Vm6dksJLXQDc=
|
||||
github.com/go-pkgz/expirable-cache v0.0.3/go.mod h1:+IauqN00R2FqNRLCLA+X5YljQJrwB179PfiAoMPlTlQ=
|
||||
github.com/go-pkgz/jrpc v0.2.0 h1:CLy/eZyekjraVrxZV18N2R1mYLMJ/nWrgdfyIOGPY/E=
|
||||
@@ -154,14 +153,14 @@ github.com/go-pkgz/lcw v0.8.1 h1:Bpt2yYTE1J8hIhz8tjdm1WPOgH13eo5iTNsXyop7cMQ=
|
||||
github.com/go-pkgz/lcw v0.8.1/go.mod h1:Xw0/ZfApATgbjVPYRZO4XHdWyxAjErDWDWJ7TLlw1Vc=
|
||||
github.com/go-pkgz/lgr v0.10.4 h1:l7qyFjqEZgwRgaQQSEp6tve4A3OU80VrfzpvtEX8ngw=
|
||||
github.com/go-pkgz/lgr v0.10.4/go.mod h1:CD0s1z6EFpIUplV067gitF77tn25JItzwHNKAPqeCF0=
|
||||
github.com/go-pkgz/notify v0.0.0-20220429105545-bc5c80a54199 h1:1PE3B3RboNvAVL3V6b+GXNFHaTiIcTohsqh+HbUkpIg=
|
||||
github.com/go-pkgz/notify v0.0.0-20220429105545-bc5c80a54199/go.mod h1:mSHXWImQev182O0gte/r6pT7NEzlTZozcOhOykjnVqk=
|
||||
github.com/go-pkgz/notify v0.1.1 h1:0EaPnBD/IX8EBVAmKnEHNesyH3rD1v6w0MBLRCwrTUI=
|
||||
github.com/go-pkgz/notify v0.1.1/go.mod h1:XTzsXgwXXsXbl8iz6qTsCq6gLkaOkimL8mJfLrk3bCk=
|
||||
github.com/go-pkgz/repeater v1.1.3 h1:q6+JQF14ESSy28Dd7F+wRelY4F+41HJ0LEy/szNnMiE=
|
||||
github.com/go-pkgz/repeater v1.1.3/go.mod h1:hVTavuO5x3Gxnu8zW7d6sQBfAneKV8X2FjU48kGfpKw=
|
||||
github.com/go-pkgz/rest v1.5.0/go.mod h1:nQaM3RhSTUAmbBZWY4hfe4buyeC9VckvhoCktiQXJxI=
|
||||
github.com/go-pkgz/rest v1.12.2/go.mod h1:KUWAqbDteYGS/CiXftomQsKjtEOifXsJ36Ka0skYbmk=
|
||||
github.com/go-pkgz/rest v1.14.0 h1:brDLCzIGoe0IiUZqRFpsiCVM9m3L88A7z62qS0V9Yfk=
|
||||
github.com/go-pkgz/rest v1.14.0/go.mod h1:KUWAqbDteYGS/CiXftomQsKjtEOifXsJ36Ka0skYbmk=
|
||||
github.com/go-pkgz/rest v1.15.0 h1:v/BDqJF9robo85GME85GWJ7O/NjtAO0x7LvO4EqWNRE=
|
||||
github.com/go-pkgz/rest v1.15.0/go.mod h1:KUWAqbDteYGS/CiXftomQsKjtEOifXsJ36Ka0skYbmk=
|
||||
github.com/go-pkgz/syncs v1.2.0 h1:aiizQFILlMZ4KtRNaYLcDffRbUQZH9fclsgr5KybWyY=
|
||||
github.com/go-pkgz/syncs v1.2.0/go.mod h1:fjThZdM2FkC/oSeiqBTOZOtHpbrCh4HuHbipB5qZJJM=
|
||||
github.com/go-redis/redis/v7 v7.4.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg=
|
||||
@@ -294,7 +293,6 @@ github.com/klauspost/compress v1.10.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYs
|
||||
github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/klauspost/compress v1.15.1 h1:y9FcTHGyrebwfP0ZZqFiaxTaiDnUrGkJkI+f583BL1A=
|
||||
github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||
@@ -384,11 +382,9 @@ github.com/tidwall/tinyqueue v0.0.0-20180302190814-1e39f5511563 h1:Otn9S136ELckZ
|
||||
github.com/tidwall/tinyqueue v0.0.0-20180302190814-1e39f5511563/go.mod h1:mLqSmt7Dv/CNneF2wfcChfN1rvapyQr01LGKnKex0DQ=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasthttp v1.14.0 h1:67bfuW9azCMwW/Jlq/C+VeihNpAuJMWkYPBig1gdi3A=
|
||||
github.com/valyala/fasthttp v1.14.0/go.mod h1:ol1PCaL0dX20wC0htZ7sYCsvCYmrouYra0zHzaclZhE=
|
||||
github.com/valyala/fasthttp v1.35.0 h1:wwkR8mZn2NbigFsaw2Zj5r+xkmzjbrA/lyTmiSlal/Y=
|
||||
github.com/valyala/fasthttp v1.35.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I=
|
||||
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
|
||||
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
||||
github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs=
|
||||
@@ -424,8 +420,8 @@ github.com/yuin/gopher-lua v0.0.0-20191220021717-ab39c6098bdb/go.mod h1:gqRgreBU
|
||||
go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
|
||||
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
|
||||
go.mongodb.org/mongo-driver v1.8.3/go.mod h1:0sQWfOeY63QTntERDJJ/0SuKK0T1uVSgKCuAROlKEPY=
|
||||
go.mongodb.org/mongo-driver v1.9.0 h1:WISF656tVHlYe/kd+istlX++s+UbjL5X8f8qKCwl/Ms=
|
||||
go.mongodb.org/mongo-driver v1.9.0/go.mod h1:0sQWfOeY63QTntERDJJ/0SuKK0T1uVSgKCuAROlKEPY=
|
||||
go.mongodb.org/mongo-driver v1.9.1 h1:m078y9v7sBItkt1aaoe2YlvWEXcD263e1a4E1fBrJ1c=
|
||||
go.mongodb.org/mongo-driver v1.9.1/go.mod h1:0sQWfOeY63QTntERDJJ/0SuKK0T1uVSgKCuAROlKEPY=
|
||||
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=
|
||||
@@ -444,9 +440,8 @@ golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20220208050332-20e1d8d225ab/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 h1:kUhD7nTDoI3fVd9G4ORWrbV5NY0liEs/Jg2pv5f+bBA=
|
||||
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220518034528-6f7dac969898 h1:SLP7Q4Di66FONjDJbCYrCRrh97focO6sLogHO7/g8F0=
|
||||
golang.org/x/crypto v0.0.0-20220518034528-6f7dac969898/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
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=
|
||||
@@ -530,8 +525,8 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 h1:HVyaeDAYux4pnY+D/SiwmLOR36ewZ4iGQIIrtnuCjFA=
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2 h1:NWy5+hlRbC7HK+PmcXVUmW1IMyFce7to56IUvhUFm7Y=
|
||||
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
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=
|
||||
|
||||
+1
@@ -32,6 +32,7 @@ func (l *limiterWrapper) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
default:
|
||||
httpError := tollbooth.LimitByRequest(l.lmt, w, r)
|
||||
if httpError != nil {
|
||||
l.lmt.ExecOnLimitReached(w, r)
|
||||
w.Header().Add("Content-Type", l.lmt.GetMessageContentType())
|
||||
w.WriteHeader(httpError.StatusCode)
|
||||
w.Write([]byte(httpError.Message))
|
||||
|
||||
+1
-1
@@ -51,7 +51,7 @@ func parseHeaderList(headerList string) []string {
|
||||
} else {
|
||||
h = append(h, b)
|
||||
}
|
||||
} else if b == '-' || (b >= '0' && b <= '9') {
|
||||
} else if b == '-' || b == '_' || b == '.' || (b >= '0' && b <= '9') {
|
||||
h = append(h, b)
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -190,7 +190,7 @@ func (em *Sender) client() (c *smtp.Client, err error) {
|
||||
return nil, fmt.Errorf("timeout connecting to %s: %w", srvAddress, err)
|
||||
}
|
||||
|
||||
c, err = smtp.NewClient(conn, srvAddress)
|
||||
c, err = smtp.NewClient(conn, em.host)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to dial: %w", err)
|
||||
}
|
||||
|
||||
+10
-1
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"net/mail"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-pkgz/email"
|
||||
@@ -99,6 +100,9 @@ func (e *Email) String() string {
|
||||
if e.TLS {
|
||||
str += " with TLS"
|
||||
}
|
||||
if e.StartTLS {
|
||||
str += " with StartTLS"
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
@@ -120,7 +124,12 @@ func (e *Email) parseDestination(destination string) (email.Params, error) {
|
||||
}
|
||||
destinations := []string{}
|
||||
for _, addr := range addresses {
|
||||
destinations = append(destinations, addr.String())
|
||||
stringAddr := addr.String()
|
||||
// in case of mailgun, correct RFC5322 address with <> yield 501 error, so we need to remove brackets
|
||||
if strings.HasPrefix(stringAddr, "<") && strings.HasSuffix(stringAddr, ">") {
|
||||
stringAddr = stringAddr[1 : len(stringAddr)-1]
|
||||
}
|
||||
destinations = append(destinations, stringAddr)
|
||||
}
|
||||
|
||||
return email.Params{
|
||||
|
||||
+1
@@ -449,6 +449,7 @@ func (t *Telegram) Request(ctx context.Context, method string, b []byte, data in
|
||||
}
|
||||
|
||||
client := http.Client{Timeout: t.Timeout}
|
||||
defer client.CloseIdleConnections()
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to send request: %w", err)
|
||||
|
||||
+6
@@ -119,6 +119,12 @@ Maybe middleware will allow you to change the flow of the middleware stack execu
|
||||
value of maybeFn(request). This is useful for example if you'd like to skip a middleware handler if
|
||||
a request does not satisfy the maybeFn logic.
|
||||
|
||||
### Benchmarks middleware
|
||||
|
||||
Benchmarks middleware allows to measure the time of request handling, number of request per second and report aggregated metrics. This middleware keeps track of the request in the memory and keep up to 900 points (15 minutes, data-point per second).
|
||||
|
||||
In order to retrieve the data user should call `Stats(d duration)` method. duration is the time window for which the benchmark data should be returned. It can be any duration from 1s to 15m.
|
||||
|
||||
## Helpers
|
||||
|
||||
- `rest.Wrap` - converts a list of middlewares to nested handlers calls (in reverse order)
|
||||
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
package rest
|
||||
|
||||
import (
|
||||
"container/list"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var maxTimeRange = time.Duration(15) * time.Minute
|
||||
|
||||
// Benchmarks is a basic benchmarking middleware collecting and reporting performance metrics
|
||||
// It keeps track of the requests speeds and counts in 1s benchData buckets ,limiting the number of buckets
|
||||
// to maxTimeRange. User can request the benchmark for any time duration. This is intended to be used
|
||||
// for retrieving the benchmark data for the last minute, 5 minutes and up to maxTimeRange.
|
||||
type Benchmarks struct {
|
||||
st time.Time
|
||||
data *list.List
|
||||
lock sync.RWMutex
|
||||
|
||||
nowFn func() time.Time // for testing only
|
||||
}
|
||||
|
||||
type benchData struct {
|
||||
// 1s aggregates
|
||||
requests int
|
||||
respTime time.Duration
|
||||
minRespTime time.Duration
|
||||
maxRespTime time.Duration
|
||||
ts time.Time
|
||||
}
|
||||
|
||||
// BenchmarkStats holds the stats for a given interval
|
||||
type BenchmarkStats struct {
|
||||
Requests int `json:"total_requests"`
|
||||
RequestsSec float64 `json:"total_requests_sec"`
|
||||
AverageRespTime float64 `json:"average_resp_time"`
|
||||
MinRespTime float64 `json:"min_resp_time"`
|
||||
MaxRespTime float64 `json:"max_resp_time"`
|
||||
}
|
||||
|
||||
// NewBenchmarks creates a new benchmark middleware
|
||||
func NewBenchmarks() *Benchmarks {
|
||||
res := &Benchmarks{
|
||||
st: time.Now(),
|
||||
data: list.New(),
|
||||
nowFn: time.Now,
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// Handler calculates 1/5/10m request per second and allows to access those values
|
||||
func (b *Benchmarks) Handler(next http.Handler) http.Handler {
|
||||
|
||||
fn := func(w http.ResponseWriter, r *http.Request) {
|
||||
st := b.nowFn()
|
||||
defer func() {
|
||||
b.update(time.Since(st))
|
||||
}()
|
||||
next.ServeHTTP(w, r)
|
||||
}
|
||||
return http.HandlerFunc(fn)
|
||||
}
|
||||
|
||||
func (b *Benchmarks) update(reqDuration time.Duration) {
|
||||
now := b.nowFn().Truncate(time.Second)
|
||||
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
// keep maxTimeRange in the list, drop the rest
|
||||
for e := b.data.Front(); e != nil; e = e.Next() {
|
||||
if b.data.Front().Value.(benchData).ts.After(b.nowFn().Add(-maxTimeRange)) {
|
||||
break
|
||||
}
|
||||
b.data.Remove(b.data.Front())
|
||||
}
|
||||
|
||||
last := b.data.Back()
|
||||
if last == nil || last.Value.(benchData).ts.Before(now) {
|
||||
b.data.PushBack(benchData{requests: 1, respTime: reqDuration, ts: now,
|
||||
minRespTime: reqDuration, maxRespTime: reqDuration})
|
||||
return
|
||||
}
|
||||
|
||||
bd := last.Value.(benchData)
|
||||
bd.requests++
|
||||
bd.respTime += reqDuration
|
||||
|
||||
if bd.minRespTime == 0 || reqDuration < bd.minRespTime {
|
||||
bd.minRespTime = reqDuration
|
||||
}
|
||||
if bd.maxRespTime == 0 || reqDuration > bd.maxRespTime {
|
||||
bd.maxRespTime = reqDuration
|
||||
}
|
||||
|
||||
last.Value = bd
|
||||
}
|
||||
|
||||
// Stats returns the current benchmark stats for the given duration
|
||||
func (b *Benchmarks) Stats(interval time.Duration) BenchmarkStats {
|
||||
if interval < time.Second { // minimum interval is 1s due to the bucket size
|
||||
return BenchmarkStats{}
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
var (
|
||||
requests int
|
||||
respTime time.Duration
|
||||
)
|
||||
|
||||
stInterval, fnInterval := time.Time{}, time.Time{}
|
||||
var minRespTime, maxRespTime time.Duration
|
||||
for e := b.data.Back(); e != nil; e = e.Prev() { // reverse order
|
||||
bd := e.Value.(benchData)
|
||||
if bd.ts.Before(b.nowFn().Add(-interval)) {
|
||||
break
|
||||
}
|
||||
if minRespTime == 0 || bd.minRespTime < minRespTime {
|
||||
minRespTime = bd.minRespTime
|
||||
}
|
||||
if maxRespTime == 0 || bd.maxRespTime > maxRespTime {
|
||||
maxRespTime = bd.maxRespTime
|
||||
}
|
||||
requests += bd.requests
|
||||
respTime += bd.respTime
|
||||
if fnInterval.IsZero() {
|
||||
fnInterval = bd.ts.Add(time.Second)
|
||||
}
|
||||
stInterval = bd.ts
|
||||
}
|
||||
|
||||
if requests == 0 {
|
||||
return BenchmarkStats{}
|
||||
}
|
||||
|
||||
return BenchmarkStats{
|
||||
Requests: requests,
|
||||
RequestsSec: float64(requests) / (fnInterval.Sub(stInterval).Seconds()),
|
||||
AverageRespTime: respTime.Seconds() / float64(requests),
|
||||
MinRespTime: minRespTime.Seconds(),
|
||||
MaxRespTime: maxRespTime.Seconds(),
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -114,7 +114,7 @@ func (bw *bulkWrite) runBatch(ctx context.Context, batch bulkWriteBatch) (BulkWr
|
||||
batchErr.Labels = writeErr.Labels
|
||||
batchErr.WriteConcernError = convertDriverWriteConcernError(writeErr.WriteConcernError)
|
||||
}
|
||||
batchRes.InsertedCount = int64(res.N)
|
||||
batchRes.InsertedCount = res.N
|
||||
case *DeleteOneModel, *DeleteManyModel:
|
||||
res, err := bw.runDelete(ctx, batch)
|
||||
if err != nil {
|
||||
@@ -126,7 +126,7 @@ func (bw *bulkWrite) runBatch(ctx context.Context, batch bulkWriteBatch) (BulkWr
|
||||
batchErr.Labels = writeErr.Labels
|
||||
batchErr.WriteConcernError = convertDriverWriteConcernError(writeErr.WriteConcernError)
|
||||
}
|
||||
batchRes.DeletedCount = int64(res.N)
|
||||
batchRes.DeletedCount = res.N
|
||||
case *ReplaceOneModel, *UpdateOneModel, *UpdateManyModel:
|
||||
res, err := bw.runUpdate(ctx, batch)
|
||||
if err != nil {
|
||||
@@ -138,8 +138,8 @@ func (bw *bulkWrite) runBatch(ctx context.Context, batch bulkWriteBatch) (BulkWr
|
||||
batchErr.Labels = writeErr.Labels
|
||||
batchErr.WriteConcernError = convertDriverWriteConcernError(writeErr.WriteConcernError)
|
||||
}
|
||||
batchRes.MatchedCount = int64(res.N)
|
||||
batchRes.ModifiedCount = int64(res.NModified)
|
||||
batchRes.MatchedCount = res.N
|
||||
batchRes.ModifiedCount = res.NModified
|
||||
batchRes.UpsertedCount = int64(len(res.Upserted))
|
||||
for _, upsert := range res.Upserted {
|
||||
batchRes.UpsertedIDs[int64(batch.indexes[upsert.Index])] = upsert.ID
|
||||
|
||||
+3
-3
@@ -473,7 +473,7 @@ func (coll *Collection) delete(ctx context.Context, filter interface{}, deleteOn
|
||||
if rr&expectedRr == 0 {
|
||||
return nil, err
|
||||
}
|
||||
return &DeleteResult{DeletedCount: int64(op.Result().N)}, err
|
||||
return &DeleteResult{DeletedCount: op.Result().N}, err
|
||||
}
|
||||
|
||||
// DeleteOne executes a delete command to delete at most one document from the collection.
|
||||
@@ -582,8 +582,8 @@ func (coll *Collection) updateOrReplace(ctx context.Context, filter bsoncore.Doc
|
||||
|
||||
opRes := op.Result()
|
||||
res := &UpdateResult{
|
||||
MatchedCount: int64(opRes.N),
|
||||
ModifiedCount: int64(opRes.NModified),
|
||||
MatchedCount: opRes.N,
|
||||
ModifiedCount: opRes.NModified,
|
||||
UpsertedCount: int64(len(opRes.Upserted)),
|
||||
}
|
||||
if len(opRes.Upserted) > 0 {
|
||||
|
||||
+1
-1
@@ -7,4 +7,4 @@
|
||||
package version // import "go.mongodb.org/mongo-driver/version"
|
||||
|
||||
// Driver is the current version of the driver.
|
||||
var Driver = "v1.9.0"
|
||||
var Driver = "v1.9.1"
|
||||
|
||||
+33
-65
@@ -18,7 +18,6 @@ import (
|
||||
"io/ioutil"
|
||||
"math/big"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
"golang.org/x/crypto/ocsp"
|
||||
@@ -28,9 +27,6 @@ import (
|
||||
var (
|
||||
tlsFeatureExtensionOID = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 1, 24}
|
||||
mustStapleFeatureValue = big.NewInt(5)
|
||||
|
||||
defaultRequestTimeout = 5 * time.Second
|
||||
errGotOCSPResponse = errors.New("done")
|
||||
)
|
||||
|
||||
// Error represents an OCSP verification error
|
||||
@@ -126,10 +122,7 @@ func getParsedResponse(ctx context.Context, cfg config, connState tls.Connection
|
||||
if cfg.disableEndpointChecking {
|
||||
return nil, nil
|
||||
}
|
||||
externalResponse, err := contactResponders(ctx, cfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
externalResponse := contactResponders(ctx, cfg)
|
||||
if externalResponse == nil {
|
||||
// None of the responders were available.
|
||||
return nil, nil
|
||||
@@ -210,33 +203,21 @@ func isMustStapleCertificate(cert *x509.Certificate) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// contactResponders will send a request to the OCSP responders reported by cfg.serverCert. The first response that
|
||||
// conclusively identifies cfg.serverCert as good or revoked will be returned. If all responders are unavailable or no
|
||||
// responder returns a conclusive status, (nil, nil) will be returned.
|
||||
func contactResponders(ctx context.Context, cfg config) (*ResponseDetails, error) {
|
||||
// contactResponders will send a request to all OCSP responders reported by cfg.serverCert. The
|
||||
// first response that conclusively identifies cfg.serverCert as good or revoked will be returned.
|
||||
// If all responders are unavailable or no responder returns a conclusive status, it returns nil.
|
||||
// contactResponders will wait for up to 5 seconds to get a certificate status response.
|
||||
func contactResponders(ctx context.Context, cfg config) *ResponseDetails {
|
||||
if len(cfg.serverCert.OCSPServer) == 0 {
|
||||
return nil, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
requestCtx := ctx // Either ctx or a new context derived from ctx with a five second timeout.
|
||||
userContextUsed := true
|
||||
var cancelFn context.CancelFunc
|
||||
// Limit all OCSP responder calls to a maximum of 5 seconds or when the passed-in context expires,
|
||||
// whichever happens first.
|
||||
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
// Use a context with defaultRequestTimeout if ctx does not have a deadline set or the current deadline is further
|
||||
// out than defaultRequestTimeout. If the current deadline is less than less than defaultRequestTimeout out, respect
|
||||
// it. Calling context.WithTimeout would do this for us, but we need to know which context we're using.
|
||||
wantDeadline := time.Now().Add(defaultRequestTimeout)
|
||||
if deadline, ok := ctx.Deadline(); !ok || deadline.After(wantDeadline) {
|
||||
userContextUsed = false
|
||||
requestCtx, cancelFn = context.WithDeadline(ctx, wantDeadline)
|
||||
}
|
||||
defer func() {
|
||||
if cancelFn != nil {
|
||||
cancelFn()
|
||||
}
|
||||
}()
|
||||
|
||||
group, groupCtx := errgroup.WithContext(requestCtx)
|
||||
group, ctx := errgroup.WithContext(ctx)
|
||||
ocspResponses := make(chan *ocsp.Response, len(cfg.serverCert.OCSPServer))
|
||||
defer close(ocspResponses)
|
||||
|
||||
@@ -244,6 +225,11 @@ func contactResponders(ctx context.Context, cfg config) (*ResponseDetails, error
|
||||
// Re-assign endpoint so it gets re-scoped rather than using the iteration variable in the goroutine. See
|
||||
// https://golang.org/doc/faq#closures_and_goroutines.
|
||||
endpoint := endpoint
|
||||
|
||||
// Start a group of goroutines that each attempt to request the certificate status from one
|
||||
// of the OCSP endpoints listed in the server certificate. We want to "soft fail" on all
|
||||
// errors, so this function never returns actual errors. Only a "done" error is returned
|
||||
// when a response is received so the errgroup cancels any other in-progress requests.
|
||||
group.Go(func() error {
|
||||
// Use bytes.NewReader instead of bytes.NewBuffer because a bytes.Buffer is an owning representation and the
|
||||
// docs recommend not using the underlying []byte after creating the buffer, so a new copy of the request
|
||||
@@ -252,35 +238,16 @@ func contactResponders(ctx context.Context, cfg config) (*ResponseDetails, error
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
request = request.WithContext(groupCtx)
|
||||
request = request.WithContext(ctx)
|
||||
|
||||
// Execute the request and handle errors as follows:
|
||||
//
|
||||
// 1. If the original context expired or was cancelled, propagate the error up so the caller will abort the
|
||||
// verification and return control to the user.
|
||||
//
|
||||
// 2. If any other errors occurred, including the defaultRequestTimeout expiring, or the response has a
|
||||
// non-200 status code, suppress the error because we want to ignore this responder and wait for a different
|
||||
// one to respond.
|
||||
httpResponse, err := http.DefaultClient.Do(request)
|
||||
if err != nil {
|
||||
urlErr, ok := err.(*url.Error)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
timeout := urlErr.Timeout()
|
||||
cancelled := urlErr.Err == context.Canceled // Timeout() does not return true for context.Cancelled.
|
||||
if cancelled || (userContextUsed && timeout) {
|
||||
// Handle the original context expiring or being cancelled. The url.Error type supports Unwrap, so
|
||||
// users can use errors.Is to check for context errors.
|
||||
return err
|
||||
}
|
||||
return nil // Ignore all other errors.
|
||||
return nil
|
||||
}
|
||||
defer func() {
|
||||
_ = httpResponse.Body.Close()
|
||||
}()
|
||||
|
||||
if httpResponse.StatusCode != 200 {
|
||||
return nil
|
||||
}
|
||||
@@ -292,26 +259,27 @@ func contactResponders(ctx context.Context, cfg config) (*ResponseDetails, error
|
||||
|
||||
ocspResponse, err := ocsp.ParseResponseForCert(httpBytes, cfg.serverCert, cfg.issuer)
|
||||
if err != nil || verifyResponse(cfg, ocspResponse) != nil || ocspResponse.Status == ocsp.Unknown {
|
||||
// If there was an error parsing/validating the response or the response was inconclusive, suppress
|
||||
// the error because we want to ignore this responder.
|
||||
// If there was an error parsing/validating the response or the response was
|
||||
// inconclusive, suppress the error because we want to ignore this responder.
|
||||
return nil
|
||||
}
|
||||
|
||||
// Store the response and return a sentinel error so the error group will exit and any in-flight requests
|
||||
// will be cancelled.
|
||||
// Send the conclusive response on the response channel and return a "done" error that
|
||||
// will cause the errgroup to cancel all other in-progress requests.
|
||||
ocspResponses <- ocspResponse
|
||||
return errGotOCSPResponse
|
||||
return errors.New("done")
|
||||
})
|
||||
}
|
||||
|
||||
if err := group.Wait(); err != nil && err != errGotOCSPResponse {
|
||||
return nil, err
|
||||
_ = group.Wait()
|
||||
select {
|
||||
case res := <-ocspResponses:
|
||||
return extractResponseDetails(res)
|
||||
default:
|
||||
// If there is no OCSP response on the response channel, all OCSP calls either failed or
|
||||
// were inconclusive. Return nil.
|
||||
return nil
|
||||
}
|
||||
if len(ocspResponses) == 0 {
|
||||
// None of the responders gave a conclusive response.
|
||||
return nil, nil
|
||||
}
|
||||
return extractResponseDetails(<-ocspResponses), nil
|
||||
}
|
||||
|
||||
// verifyResponse checks that the provided OCSP response is valid.
|
||||
|
||||
+3
-3
@@ -42,7 +42,7 @@ type Delete struct {
|
||||
// DeleteResult represents a delete result returned by the server.
|
||||
type DeleteResult struct {
|
||||
// Number of documents successfully deleted.
|
||||
N int32
|
||||
N int64
|
||||
}
|
||||
|
||||
func buildDeleteResult(response bsoncore.Document) (DeleteResult, error) {
|
||||
@@ -55,9 +55,9 @@ func buildDeleteResult(response bsoncore.Document) (DeleteResult, error) {
|
||||
switch element.Key() {
|
||||
case "n":
|
||||
var ok bool
|
||||
dr.N, ok = element.Value().AsInt32OK()
|
||||
dr.N, ok = element.Value().AsInt64OK()
|
||||
if !ok {
|
||||
return dr, fmt.Errorf("response field 'n' is type int32, but received BSON type %s", element.Value().Type)
|
||||
return dr, fmt.Errorf("response field 'n' is type int32 or int64, but received BSON type %s", element.Value().Type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -41,7 +41,7 @@ type Insert struct {
|
||||
// InsertResult represents an insert result returned by the server.
|
||||
type InsertResult struct {
|
||||
// Number of documents successfully inserted.
|
||||
N int32
|
||||
N int64
|
||||
}
|
||||
|
||||
func buildInsertResult(response bsoncore.Document) (InsertResult, error) {
|
||||
@@ -54,9 +54,9 @@ func buildInsertResult(response bsoncore.Document) (InsertResult, error) {
|
||||
switch element.Key() {
|
||||
case "n":
|
||||
var ok bool
|
||||
ir.N, ok = element.Value().AsInt32OK()
|
||||
ir.N, ok = element.Value().AsInt64OK()
|
||||
if !ok {
|
||||
return ir, fmt.Errorf("response field 'n' is type int32, but received BSON type %s", element.Value().Type)
|
||||
return ir, fmt.Errorf("response field 'n' is type int32 or int64, but received BSON type %s", element.Value().Type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -51,9 +51,9 @@ type Upsert struct {
|
||||
// UpdateResult contains information for the result of an Update operation.
|
||||
type UpdateResult struct {
|
||||
// Number of documents matched.
|
||||
N int32
|
||||
N int64
|
||||
// Number of documents modified.
|
||||
NModified int32
|
||||
NModified int64
|
||||
// Information about upserted documents.
|
||||
Upserted []Upsert
|
||||
}
|
||||
@@ -68,15 +68,15 @@ func buildUpdateResult(response bsoncore.Document) (UpdateResult, error) {
|
||||
switch element.Key() {
|
||||
case "nModified":
|
||||
var ok bool
|
||||
ur.NModified, ok = element.Value().Int32OK()
|
||||
ur.NModified, ok = element.Value().AsInt64OK()
|
||||
if !ok {
|
||||
return ur, fmt.Errorf("response field 'nModified' is type int32, but received BSON type %s", element.Value().Type)
|
||||
return ur, fmt.Errorf("response field 'nModified' is type int32 or int64, but received BSON type %s", element.Value().Type)
|
||||
}
|
||||
case "n":
|
||||
var ok bool
|
||||
ur.N, ok = element.Value().Int32OK()
|
||||
ur.N, ok = element.Value().AsInt64OK()
|
||||
if !ok {
|
||||
return ur, fmt.Errorf("response field 'n' is type int32, but received BSON type %s", element.Value().Type)
|
||||
return ur, fmt.Errorf("response field 'n' is type int32 or int64, but received BSON type %s", element.Value().Type)
|
||||
}
|
||||
case "upserted":
|
||||
arr, ok := element.Value().ArrayOK()
|
||||
|
||||
+14
@@ -306,6 +306,20 @@ func (c *Client) UpdateReg(ctx context.Context, acct *Account) (*Account, error)
|
||||
return c.updateRegRFC(ctx, acct)
|
||||
}
|
||||
|
||||
// AccountKeyRollover attempts to transition a client's account key to a new key.
|
||||
// On success client's Key is updated which is not concurrency safe.
|
||||
// On failure an error will be returned.
|
||||
// The new key is already registered with the ACME provider if the following is true:
|
||||
// - error is of type acme.Error
|
||||
// - StatusCode should be 409 (Conflict)
|
||||
// - Location header will have the KID of the associated account
|
||||
//
|
||||
// More about account key rollover can be found at
|
||||
// https://tools.ietf.org/html/rfc8555#section-7.3.5.
|
||||
func (c *Client) AccountKeyRollover(ctx context.Context, newKey crypto.Signer) error {
|
||||
return c.accountKeyRollover(ctx, newKey)
|
||||
}
|
||||
|
||||
// Authorize performs the initial step in the pre-authorization flow,
|
||||
// as opposed to order-based flow.
|
||||
// The caller will then need to choose from and perform a set of returned
|
||||
|
||||
+31
-6
@@ -33,6 +33,10 @@ const noKeyID = KeyID("")
|
||||
// See https://tools.ietf.org/html/rfc8555#section-6.3 for more details.
|
||||
const noPayload = ""
|
||||
|
||||
// noNonce indicates that the nonce should be omitted from the protected header.
|
||||
// See jwsEncodeJSON for details.
|
||||
const noNonce = ""
|
||||
|
||||
// jsonWebSignature can be easily serialized into a JWS following
|
||||
// https://tools.ietf.org/html/rfc7515#section-3.2.
|
||||
type jsonWebSignature struct {
|
||||
@@ -45,10 +49,15 @@ type jsonWebSignature struct {
|
||||
// The result is serialized in JSON format containing either kid or jwk
|
||||
// fields based on the provided KeyID value.
|
||||
//
|
||||
// If kid is non-empty, its quoted value is inserted in the protected head
|
||||
// The claimset is marshalled using json.Marshal unless it is a string.
|
||||
// In which case it is inserted directly into the message.
|
||||
//
|
||||
// If kid is non-empty, its quoted value is inserted in the protected header
|
||||
// as "kid" field value. Otherwise, JWK is computed using jwkEncode and inserted
|
||||
// as "jwk" field value. The "jwk" and "kid" fields are mutually exclusive.
|
||||
//
|
||||
// If nonce is non-empty, its quoted value is inserted in the protected header.
|
||||
//
|
||||
// See https://tools.ietf.org/html/rfc7515#section-7.
|
||||
func jwsEncodeJSON(claimset interface{}, key crypto.Signer, kid KeyID, nonce, url string) ([]byte, error) {
|
||||
if key == nil {
|
||||
@@ -58,20 +67,36 @@ func jwsEncodeJSON(claimset interface{}, key crypto.Signer, kid KeyID, nonce, ur
|
||||
if alg == "" || !sha.Available() {
|
||||
return nil, ErrUnsupportedKey
|
||||
}
|
||||
var phead string
|
||||
headers := struct {
|
||||
Alg string `json:"alg"`
|
||||
KID string `json:"kid,omitempty"`
|
||||
JWK json.RawMessage `json:"jwk,omitempty"`
|
||||
Nonce string `json:"nonce,omitempty"`
|
||||
URL string `json:"url"`
|
||||
}{
|
||||
Alg: alg,
|
||||
Nonce: nonce,
|
||||
URL: url,
|
||||
}
|
||||
switch kid {
|
||||
case noKeyID:
|
||||
jwk, err := jwkEncode(key.Public())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
phead = fmt.Sprintf(`{"alg":%q,"jwk":%s,"nonce":%q,"url":%q}`, alg, jwk, nonce, url)
|
||||
headers.JWK = json.RawMessage(jwk)
|
||||
default:
|
||||
phead = fmt.Sprintf(`{"alg":%q,"kid":%q,"nonce":%q,"url":%q}`, alg, kid, nonce, url)
|
||||
headers.KID = string(kid)
|
||||
}
|
||||
phead = base64.RawURLEncoding.EncodeToString([]byte(phead))
|
||||
phJSON, err := json.Marshal(headers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
phead := base64.RawURLEncoding.EncodeToString([]byte(phJSON))
|
||||
var payload string
|
||||
if claimset != noPayload {
|
||||
if val, ok := claimset.(string); ok {
|
||||
payload = val
|
||||
} else {
|
||||
cs, err := json.Marshal(claimset)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
+39
@@ -24,6 +24,9 @@ import (
|
||||
//
|
||||
// It only works with CAs implementing RFC 8555.
|
||||
func (c *Client) DeactivateReg(ctx context.Context) error {
|
||||
if _, err := c.Discover(ctx); err != nil { // required by c.accountKID
|
||||
return err
|
||||
}
|
||||
url := string(c.accountKID(ctx))
|
||||
if url == "" {
|
||||
return ErrNoAccount
|
||||
@@ -148,6 +151,42 @@ func responseAccount(res *http.Response) (*Account, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
// accountKeyRollover attempts to perform account key rollover.
|
||||
// On success it will change client.Key to the new key.
|
||||
func (c *Client) accountKeyRollover(ctx context.Context, newKey crypto.Signer) error {
|
||||
dir, err := c.Discover(ctx) // Also required by c.accountKID
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
kid := c.accountKID(ctx)
|
||||
if kid == noKeyID {
|
||||
return ErrNoAccount
|
||||
}
|
||||
oldKey, err := jwkEncode(c.Key.Public())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
payload := struct {
|
||||
Account string `json:"account"`
|
||||
OldKey json.RawMessage `json:"oldKey"`
|
||||
}{
|
||||
Account: string(kid),
|
||||
OldKey: json.RawMessage(oldKey),
|
||||
}
|
||||
inner, err := jwsEncodeJSON(payload, newKey, noKeyID, noNonce, dir.KeyChangeURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res, err := c.post(ctx, nil, dir.KeyChangeURL, base64.RawURLEncoding.EncodeToString(inner), wantStatus(http.StatusOK))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
c.Key = newKey
|
||||
return nil
|
||||
}
|
||||
|
||||
// AuthorizeOrder initiates the order-based application for certificate issuance,
|
||||
// as opposed to pre-authorization in Authorize.
|
||||
// It is only supported by CAs implementing RFC 8555.
|
||||
|
||||
Vendored
+8
-10
@@ -60,7 +60,7 @@ github.com/didip/tollbooth/v6
|
||||
github.com/didip/tollbooth/v6/errors
|
||||
github.com/didip/tollbooth/v6/libstring
|
||||
github.com/didip/tollbooth/v6/limiter
|
||||
# github.com/didip/tollbooth_chi v0.0.0-20200828173446-a7173453ea21
|
||||
# github.com/didip/tollbooth_chi v0.0.0-20220429013743-da966f2f674b
|
||||
## explicit; go 1.14
|
||||
github.com/didip/tollbooth_chi
|
||||
# github.com/dlclark/regexp2 v1.4.0
|
||||
@@ -75,7 +75,7 @@ github.com/go-chi/chi/middleware
|
||||
## explicit; go 1.14
|
||||
github.com/go-chi/chi/v5
|
||||
github.com/go-chi/chi/v5/middleware
|
||||
# github.com/go-chi/cors v1.2.0
|
||||
# github.com/go-chi/cors v1.2.1
|
||||
## explicit; go 1.14
|
||||
github.com/go-chi/cors
|
||||
# github.com/go-chi/render v1.0.1
|
||||
@@ -95,7 +95,7 @@ github.com/go-pkgz/auth/middleware
|
||||
github.com/go-pkgz/auth/provider
|
||||
github.com/go-pkgz/auth/provider/sender
|
||||
github.com/go-pkgz/auth/token
|
||||
# github.com/go-pkgz/email v0.2.1-0.20220428155644-a7e5d837d02f
|
||||
# github.com/go-pkgz/email v0.3.0
|
||||
## explicit; go 1.17
|
||||
github.com/go-pkgz/email
|
||||
# github.com/go-pkgz/expirable-cache v0.0.3
|
||||
@@ -112,14 +112,14 @@ github.com/go-pkgz/lcw/internal/cache
|
||||
# github.com/go-pkgz/lgr v0.10.4
|
||||
## explicit; go 1.15
|
||||
github.com/go-pkgz/lgr
|
||||
# github.com/go-pkgz/notify v0.0.0-20220429105545-bc5c80a54199
|
||||
# github.com/go-pkgz/notify v0.1.1
|
||||
## explicit; go 1.17
|
||||
github.com/go-pkgz/notify
|
||||
# github.com/go-pkgz/repeater v1.1.3
|
||||
## explicit; go 1.12
|
||||
github.com/go-pkgz/repeater
|
||||
github.com/go-pkgz/repeater/strategy
|
||||
# github.com/go-pkgz/rest v1.14.0
|
||||
# github.com/go-pkgz/rest v1.15.0
|
||||
## explicit; go 1.16
|
||||
github.com/go-pkgz/rest
|
||||
github.com/go-pkgz/rest/logger
|
||||
@@ -227,8 +227,6 @@ github.com/stretchr/objx
|
||||
github.com/stretchr/testify/assert
|
||||
github.com/stretchr/testify/mock
|
||||
github.com/stretchr/testify/require
|
||||
# github.com/valyala/fasthttp v1.35.0
|
||||
## explicit; go 1.15
|
||||
# github.com/xdg-go/pbkdf2 v1.0.0
|
||||
## explicit; go 1.9
|
||||
github.com/xdg-go/pbkdf2
|
||||
@@ -244,7 +242,7 @@ github.com/youmark/pkcs8
|
||||
# go.etcd.io/bbolt v1.3.6
|
||||
## explicit; go 1.12
|
||||
go.etcd.io/bbolt
|
||||
# go.mongodb.org/mongo-driver v1.9.0
|
||||
# go.mongodb.org/mongo-driver v1.9.1
|
||||
## explicit; go 1.10
|
||||
go.mongodb.org/mongo-driver/bson
|
||||
go.mongodb.org/mongo-driver/bson/bsoncodec
|
||||
@@ -285,7 +283,7 @@ go.mongodb.org/mongo-driver/x/mongo/driver/wiremessage
|
||||
## explicit; go 1.13
|
||||
go.uber.org/goleak
|
||||
go.uber.org/goleak/internal/stack
|
||||
# golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4
|
||||
# golang.org/x/crypto v0.0.0-20220518034528-6f7dac969898
|
||||
## explicit; go 1.17
|
||||
golang.org/x/crypto/acme
|
||||
golang.org/x/crypto/acme/autocert
|
||||
@@ -296,7 +294,7 @@ golang.org/x/crypto/scrypt
|
||||
## explicit; go 1.12
|
||||
golang.org/x/image/draw
|
||||
golang.org/x/image/math/f64
|
||||
# golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4
|
||||
# golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2
|
||||
## explicit; go 1.17
|
||||
golang.org/x/net/context
|
||||
golang.org/x/net/context/ctxhttp
|
||||
|
||||
Reference in New Issue
Block a user