Browse Source

Merge branch 'fixapi' of yongxu/sparrow into v2

lijian 1 year ago
parent
commit
1b129a6b88
100 changed files with 3496 additions and 2467 deletions
  1. 18 18
      go.mod
  2. 38 44
      go.sum
  3. 4 4
      services/knowoapi/controllers/alert.go
  4. 1 1
      services/knowoapi/controllers/application.go
  5. 4 4
      services/knowoapi/controllers/device.go
  6. 1 1
      services/knowoapi/controllers/errorresponse.go
  7. 1 1
      services/knowoapi/controllers/parsebody.go
  8. 1 1
      services/knowoapi/controllers/product.go
  9. 1 1
      services/knowoapi/controllers/protocal.go
  10. 2 2
      services/knowoapi/controllers/role.go
  11. 1 1
      services/knowoapi/controllers/rule_chain.go
  12. 1 1
      services/knowoapi/controllers/sensor.go
  13. 1 1
      services/knowoapi/controllers/sub_device.go
  14. 1 1
      services/knowoapi/controllers/token.go
  15. 2 2
      services/knowoapi/controllers/user.go
  16. BIN
      services/knowoapi/knowoapi
  17. 1 11
      services/knowoapi/main.go
  18. 5 7
      services/knowoapi/router.go
  19. 7 0
      vendor/github.com/andybalholm/brotli/README.md
  20. 56 0
      vendor/github.com/andybalholm/brotli/bitwriter.go
  21. 275 36
      vendor/github.com/andybalholm/brotli/brotli_bit_stream.go
  22. 38 13
      vendor/github.com/andybalholm/brotli/compress_fragment_two_pass.go
  23. 168 0
      vendor/github.com/andybalholm/brotli/encoder.go
  24. 5 0
      vendor/github.com/andybalholm/brotli/entropy_encode_static.go
  25. 1 1
      vendor/github.com/andybalholm/brotli/http.go
  26. 45 0
      vendor/github.com/andybalholm/brotli/matchfinder/emitter.go
  27. 169 0
      vendor/github.com/andybalholm/brotli/matchfinder/m0.go
  28. 297 0
      vendor/github.com/andybalholm/brotli/matchfinder/m4.go
  29. 103 0
      vendor/github.com/andybalholm/brotli/matchfinder/matchfinder.go
  30. 53 0
      vendor/github.com/andybalholm/brotli/matchfinder/textencoder.go
  31. 43 0
      vendor/github.com/andybalholm/brotli/writer.go
  32. 8 6
      vendor/github.com/blang/semver/v4/LICENSE
  33. 23 0
      vendor/github.com/blang/semver/v4/json.go
  34. 416 0
      vendor/github.com/blang/semver/v4/range.go
  35. 476 0
      vendor/github.com/blang/semver/v4/semver.go
  36. 28 0
      vendor/github.com/blang/semver/v4/sort.go
  37. 30 0
      vendor/github.com/blang/semver/v4/sql.go
  38. 8 1
      vendor/github.com/gobwas/ws/dialer.go
  39. 5 1
      vendor/github.com/gobwas/ws/http.go
  40. 90 6
      vendor/github.com/gobwas/ws/wsutil/reader.go
  41. 1 1
      vendor/github.com/gomarkdown/markdown/README.md
  42. 1 1
      vendor/github.com/gomarkdown/markdown/parser/inline.go
  43. 7 0
      vendor/github.com/google/uuid/CHANGELOG.md
  44. 16 5
      vendor/github.com/google/uuid/time.go
  45. 53 0
      vendor/github.com/google/uuid/uuid.go
  46. 56 0
      vendor/github.com/google/uuid/version6.go
  47. 75 0
      vendor/github.com/google/uuid/version7.go
  48. 20 0
      vendor/github.com/gorilla/websocket/.editorconfig
  49. 1 25
      vendor/github.com/gorilla/websocket/.gitignore
  50. 3 0
      vendor/github.com/gorilla/websocket/.golangci.yml
  51. 0 9
      vendor/github.com/gorilla/websocket/AUTHORS
  52. 22 17
      vendor/github.com/gorilla/websocket/LICENSE
  53. 34 0
      vendor/github.com/gorilla/websocket/Makefile
  54. 8 11
      vendor/github.com/gorilla/websocket/README.md
  55. 33 11
      vendor/github.com/gorilla/websocket/client.go
  56. 7 2
      vendor/github.com/gorilla/websocket/compression.go
  57. 60 23
      vendor/github.com/gorilla/websocket/conn.go
  58. 4 0
      vendor/github.com/gorilla/websocket/mask.go
  59. 13 4
      vendor/github.com/gorilla/websocket/proxy.go
  60. 33 9
      vendor/github.com/gorilla/websocket/server.go
  61. 0 3
      vendor/github.com/gorilla/websocket/tls_handshake.go
  62. 0 21
      vendor/github.com/gorilla/websocket/tls_handshake_116.go
  63. 17 2
      vendor/github.com/gorilla/websocket/util.go
  64. 0 473
      vendor/github.com/gorilla/websocket/x_net_proxy.go
  65. 0 354
      vendor/github.com/hashicorp/go-version/LICENSE
  66. 0 66
      vendor/github.com/hashicorp/go-version/README.md
  67. 0 204
      vendor/github.com/hashicorp/go-version/constraint.go
  68. 0 384
      vendor/github.com/hashicorp/go-version/version.go
  69. 0 17
      vendor/github.com/hashicorp/go-version/version_collection.go
  70. 0 379
      vendor/github.com/iris-contrib/middleware/cors/cors.go
  71. 0 70
      vendor/github.com/iris-contrib/middleware/cors/util.go
  72. 0 22
      vendor/github.com/kataras/iris/mvc/reflect.go
  73. 43 0
      vendor/github.com/kataras/iris/v12/HISTORY.md
  74. 1 1
      vendor/github.com/kataras/iris/v12/LICENSE
  75. 103 75
      vendor/github.com/kataras/iris/v12/README.md
  76. 2 2
      vendor/github.com/kataras/iris/v12/README_ES.md
  77. 2 2
      vendor/github.com/kataras/iris/v12/README_FA.md
  78. 2 2
      vendor/github.com/kataras/iris/v12/README_FR.md
  79. 2 2
      vendor/github.com/kataras/iris/v12/README_GR.md
  80. 2 2
      vendor/github.com/kataras/iris/v12/README_JA.md
  81. 2 2
      vendor/github.com/kataras/iris/v12/README_KO.md
  82. 2 2
      vendor/github.com/kataras/iris/v12/README_PT_BR.md
  83. 2 2
      vendor/github.com/kataras/iris/v12/README_RU.md
  84. 2 2
      vendor/github.com/kataras/iris/v12/README_VN.md
  85. 1 1
      vendor/github.com/kataras/iris/v12/README_ZH_HANS.md
  86. 2 2
      vendor/github.com/kataras/iris/v12/README_ZH_HANT.md
  87. 17 0
      vendor/github.com/kataras/iris/v12/aliases.go
  88. 29 2
      vendor/github.com/kataras/iris/v12/configuration.go
  89. 2 0
      vendor/github.com/kataras/iris/v12/context/configuration.go
  90. 87 22
      vendor/github.com/kataras/iris/v12/context/context.go
  91. 1 1
      vendor/github.com/kataras/iris/v12/context/handler.go
  92. 67 60
      vendor/github.com/kataras/iris/v12/core/host/supervisor.go
  93. 2 2
      vendor/github.com/kataras/iris/v12/core/host/task.go
  94. 134 0
      vendor/github.com/kataras/iris/v12/core/host/waiter.go
  95. 1 1
      vendor/github.com/kataras/iris/v12/core/memstore/lifetime.go
  96. 1 1
      vendor/github.com/kataras/iris/v12/core/netutil/addr.go
  97. 81 0
      vendor/github.com/kataras/iris/v12/core/router/api_builder.go
  98. 11 0
      vendor/github.com/kataras/iris/v12/core/router/party.go
  99. 2 2
      vendor/github.com/kataras/iris/v12/doc.go
  100. 2 1
      vendor/github.com/kataras/iris/v12/hero/struct.go

+ 18 - 18
go.mod

@@ -10,10 +10,10 @@ require (
 	github.com/gogf/gf v1.16.9
 	github.com/gogf/gf/v2 v2.6.1
 	github.com/influxdata/influxdb-client-go/v2 v2.13.0
-	github.com/iris-contrib/middleware/cors v0.0.0-20231105204038-60b21ca77167
 	github.com/iris-contrib/middleware/jwt v0.0.0-20231105204038-60b21ca77167
 	github.com/jinzhu/gorm v1.9.16
 	github.com/kataras/iris v0.0.2
+	github.com/kataras/iris/v12 v12.2.10
 	github.com/martini-contrib/binding v0.0.0-20160701174519-05d3e151b6cf
 	github.com/martini-contrib/render v0.0.0-20150707142108-ec18f8345a11
 	github.com/opentracing/opentracing-go v1.2.0
@@ -27,7 +27,7 @@ require (
 	github.com/stretchr/testify v1.8.4
 	github.com/uber/jaeger-client-go v2.30.0+incompatible
 	go.etcd.io/etcd/client/v3 v3.5.11
-	golang.org/x/net v0.19.0
+	golang.org/x/net v0.20.0
 	golang.org/x/time v0.5.0
 	google.golang.org/grpc v1.60.1
 	google.golang.org/protobuf v1.32.0
@@ -43,11 +43,12 @@ require (
 	github.com/Joker/jade v1.1.3 // indirect
 	github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect
 	github.com/ajg/form v1.5.1 // indirect
-	github.com/andybalholm/brotli v1.0.6 // indirect
+	github.com/andybalholm/brotli v1.1.0 // indirect
 	github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
 	github.com/aymerick/douceur v0.2.0 // indirect
 	github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible // indirect
 	github.com/beorn7/perks v1.0.1 // indirect
+	github.com/blang/semver/v4 v4.0.0 // indirect
 	github.com/cespare/xxhash/v2 v2.2.0 // indirect
 	github.com/clbanning/mxj v1.8.5-0.20200714211355-ff02cfb8ea28 // indirect
 	github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect
@@ -64,17 +65,17 @@ require (
 	github.com/gobwas/glob v0.2.3 // indirect
 	github.com/gobwas/httphead v0.1.0 // indirect
 	github.com/gobwas/pool v0.2.1 // indirect
-	github.com/gobwas/ws v1.3.0 // indirect
+	github.com/gobwas/ws v1.3.2 // indirect
 	github.com/gogo/protobuf v1.3.2 // indirect
 	github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
 	github.com/golang/protobuf v1.5.3 // indirect
 	github.com/golang/snappy v0.0.4 // indirect
-	github.com/gomarkdown/markdown v0.0.0-20230922112808-5421fefb8386 // indirect
+	github.com/gomarkdown/markdown v0.0.0-20231222211730-1d6d20845b47 // indirect
 	github.com/gomodule/redigo v1.8.5 // indirect
 	github.com/google/go-querystring v1.1.0 // indirect
-	github.com/google/uuid v1.4.0 // indirect
+	github.com/google/uuid v1.5.0 // indirect
 	github.com/gorilla/css v1.0.0 // indirect
-	github.com/gorilla/websocket v1.5.0 // indirect
+	github.com/gorilla/websocket v1.5.1 // indirect
 	github.com/grokify/html-strip-tags-go v0.0.1 // indirect
 	github.com/hashicorp/go-version v1.2.1 // indirect
 	github.com/imkira/go-interpol v1.1.0 // indirect
@@ -89,12 +90,11 @@ require (
 	github.com/json-iterator/go v1.1.12 // indirect
 	github.com/kataras/blocks v0.0.8 // indirect
 	github.com/kataras/golog v0.1.11 // indirect
-	github.com/kataras/iris/v12 v12.2.8 // indirect
-	github.com/kataras/neffos v0.0.22 // indirect
+	github.com/kataras/neffos v0.0.24-0.20240110215151-1db32f4ef9ed // indirect
 	github.com/kataras/pio v0.0.13 // indirect
 	github.com/kataras/sitemap v0.0.6 // indirect
 	github.com/kataras/tunnel v0.0.4 // indirect
-	github.com/klauspost/compress v1.17.2 // indirect
+	github.com/klauspost/compress v1.17.4 // indirect
 	github.com/mailgun/raymond/v2 v2.0.48 // indirect
 	github.com/mailru/easyjson v0.7.7 // indirect
 	github.com/mattn/go-colorable v0.1.13 // indirect
@@ -106,8 +106,8 @@ require (
 	github.com/mitchellh/go-wordwrap v1.0.1 // indirect
 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 	github.com/modern-go/reflect2 v1.0.2 // indirect
-	github.com/nats-io/nats.go v1.28.0 // indirect
-	github.com/nats-io/nkeys v0.4.6 // indirect
+	github.com/nats-io/nats.go v1.31.0 // indirect
+	github.com/nats-io/nkeys v0.4.7 // indirect
 	github.com/nats-io/nuid v1.0.1 // indirect
 	github.com/oapi-codegen/runtime v1.0.0 // indirect
 	github.com/olekukonko/tablewriter v0.0.5 // indirect
@@ -124,8 +124,8 @@ require (
 	github.com/sanity-io/litter v1.5.5 // indirect
 	github.com/schollz/closestmatch v2.1.0+incompatible // indirect
 	github.com/sergi/go-diff v1.1.0 // indirect
-	github.com/tdewolff/minify/v2 v2.20.6 // indirect
-	github.com/tdewolff/parse/v2 v2.7.4 // indirect
+	github.com/tdewolff/minify/v2 v2.20.14 // indirect
+	github.com/tdewolff/parse/v2 v2.7.8 // indirect
 	github.com/uber/jaeger-lib v2.4.1+incompatible // indirect
 	github.com/valyala/bytebufferpool v1.0.0 // indirect
 	github.com/vmihailenco/msgpack/v5 v5.4.1 // indirect
@@ -145,10 +145,10 @@ require (
 	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/crypto v0.16.0 // indirect
-	golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
-	golang.org/x/sync v0.4.0 // indirect
-	golang.org/x/sys v0.15.0 // indirect
+	golang.org/x/crypto v0.18.0 // indirect
+	golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 // indirect
+	golang.org/x/sync v0.6.0 // indirect
+	golang.org/x/sys v0.16.0 // indirect
 	golang.org/x/text v0.14.0 // indirect
 	golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f // indirect
 	google.golang.org/genproto v0.0.0-20231002182017-d307bd883b97 // indirect

+ 38 - 44
go.sum

@@ -27,8 +27,8 @@ github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
 github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
 github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
 github.com/andybalholm/brotli v1.0.1-0.20200619015827-c3da72aa01ed/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
-github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI=
-github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
+github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
+github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
 github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
 github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=
 github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
@@ -39,6 +39,8 @@ github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible h1
 github.com/aymerick/raymond v2.0.3-0.20180322193309-b565731e1464+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
 github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
 github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
+github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
 github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
 github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
 github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
@@ -116,8 +118,8 @@ github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6Wezm
 github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
 github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
 github.com/gobwas/ws v1.0.3/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
-github.com/gobwas/ws v1.3.0 h1:sbeU3Y4Qzlb+MOzIe6mQGf7QR4Hkv6ZD0qhGkBFL2O0=
-github.com/gobwas/ws v1.3.0/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
+github.com/gobwas/ws v1.3.2 h1:zlnbNHxumkRvfPWgfXu8RBwyNR1x8wh9cf5PTOCqs9Q=
+github.com/gobwas/ws v1.3.2/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
 github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
 github.com/gogf/gf v1.16.9 h1:Q803UmmRo59+Ws08sMVFOcd8oNpkSWL9vS33hlo/Cyk=
 github.com/gogf/gf v1.16.9/go.mod h1:8Q/kw05nlVRp+4vv7XASBsMe9L1tsVKiGoeP2AHnlkk=
@@ -148,8 +150,8 @@ github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu
 github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
 github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
-github.com/gomarkdown/markdown v0.0.0-20230922112808-5421fefb8386 h1:EcQR3gusLHN46TAD+G+EbaaqJArt5vHhNpXAa12PQf4=
-github.com/gomarkdown/markdown v0.0.0-20230922112808-5421fefb8386/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
+github.com/gomarkdown/markdown v0.0.0-20231222211730-1d6d20845b47 h1:k4Tw0nt6lwro3Uin8eqoET7MDA4JnT8YgbCjc/g5E3k=
+github.com/gomarkdown/markdown v0.0.0-20231222211730-1d6d20845b47/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
 github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
 github.com/gomodule/redigo v1.8.5 h1:nRAxCa+SVsyjSBrtZmG/cqb6VbTmuRzpg/PoTFlpumc=
 github.com/gomodule/redigo v1.8.5/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
@@ -169,13 +171,13 @@ github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD
 github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
 github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/google/uuid v1.1.2-0.20200519141726-cb32006e483f/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
-github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
+github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 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/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
-github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
-github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
+github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
+github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
 github.com/grokify/html-strip-tags-go v0.0.1 h1:0fThFwLbW7P/kOiTBs03FsJSV9RM2M/Q/MOnCQxKMo0=
 github.com/grokify/html-strip-tags-go v0.0.1/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78=
 github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI=
@@ -195,8 +197,6 @@ github.com/iris-contrib/httpexpect/v2 v2.15.2 h1:T9THsdP1woyAqKHwjkEsbCnMefsAFvk
 github.com/iris-contrib/httpexpect/v2 v2.15.2/go.mod h1:JLDgIqnFy5loDSUv1OA2j0mb6p/rDhiCqigP22Uq9xE=
 github.com/iris-contrib/jade v1.1.4 h1:WoYdfyJFfZIUgqNAeOyRfTNQZOksSlZ6+FnXR3AEpX0=
 github.com/iris-contrib/jade v1.1.4/go.mod h1:EDqR+ur9piDl6DUgs6qRrlfzmlx/D5UybogqrXvJTBE=
-github.com/iris-contrib/middleware/cors v0.0.0-20231105204038-60b21ca77167 h1:zs9HA+Jn+NsbXTH6tER40sFDcnaFUtBljj5YAnwUfk4=
-github.com/iris-contrib/middleware/cors v0.0.0-20231105204038-60b21ca77167/go.mod h1:D/Xr6gLnI2E5jZJ6FC6pLiF1inXUWqnft6DibmTUuBo=
 github.com/iris-contrib/middleware/jwt v0.0.0-20231105204038-60b21ca77167 h1:x2POmaLt4fmAoO8ZvxrqLPRDtB7ZUiR5LC9ftNY8JYc=
 github.com/iris-contrib/middleware/jwt v0.0.0-20231105204038-60b21ca77167/go.mod h1:txkPY4oCyoRH302p0mx6IsAupinDtULtZ84V7L4dN+A=
 github.com/iris-contrib/pongo2 v0.0.1 h1:zGP7pW51oi5eQZMIlGA3I+FHY9/HOQWDB+572yin0to=
@@ -225,11 +225,11 @@ github.com/kataras/golog v0.1.11 h1:dGkcCVsIpqiAMWTlebn/ZULHxFvfG4K43LF1cNWSh20=
 github.com/kataras/golog v0.1.11/go.mod h1:mAkt1vbPowFUuUGvexyQ5NFW6djEgGyxQBIARJ0AH4A=
 github.com/kataras/iris v0.0.2 h1:Tteb6pXLN9QiXvTCXCP31LRHu1LHlVA6Rappr9vWa1c=
 github.com/kataras/iris v0.0.2/go.mod h1:ab8yy1jWHFgoI+/B+zoIsQpVY/XUY+NNvVCXJ27Zat8=
-github.com/kataras/iris/v12 v12.2.8 h1:p+PcqyO45dSib8B4I8Wc0fz+6B/CVkOsikCpbeNOkuo=
-github.com/kataras/iris/v12 v12.2.8/go.mod h1:on94BX0C5jhuxgWKDZVpcTqymksZDIxWFN+nL7axjRA=
+github.com/kataras/iris/v12 v12.2.10 h1:rEJVM7qMoyhv8wpgkA1yGxibFcONE0jkJ70LFLibTAA=
+github.com/kataras/iris/v12 v12.2.10/go.mod h1:z4+E+kLMqZ7U4WtDsYfFnG7BjMTXLkdzMAXLVMLnMNs=
 github.com/kataras/neffos v0.0.16/go.mod h1:BqWkF1c6cSyqw85dfCdqXxK5cMo/hyBGhtNuFkxHyMg=
-github.com/kataras/neffos v0.0.22 h1:3M4lHrUl//2OKmS9t9z3AKIZqwha6ABeA6WoF03HEv8=
-github.com/kataras/neffos v0.0.22/go.mod h1:IIJZcUDvwBxJGlDj942dqQgyznVKYDti91f8Ez+RRxE=
+github.com/kataras/neffos v0.0.24-0.20240110215151-1db32f4ef9ed h1:iCsmmi2n7vUyWJ0NS1Wsu8N5oIS+C05fyIo3YTBQHMQ=
+github.com/kataras/neffos v0.0.24-0.20240110215151-1db32f4ef9ed/go.mod h1:VLyfPmZh2Tbxjc2XKe1J0xwwKqiUD2zTA36Xcp+UIDs=
 github.com/kataras/pio v0.0.8/go.mod h1:NFfMp2kVP1rmV4N6gH6qgWpuoDKlrOeYi3VrAIWCGsE=
 github.com/kataras/pio v0.0.13 h1:x0rXVX0fviDTXOOLOmr4MUxOabu1InVSTu5itF8CXCM=
 github.com/kataras/pio v0.0.13/go.mod h1:k3HNuSw+eJ8Pm2lA4lRhg3DiCjVgHlP8hmXApSej3oM=
@@ -243,8 +243,8 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
 github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
 github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
 github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
-github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4=
-github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
+github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
+github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
 github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
 github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
@@ -287,8 +287,6 @@ github.com/mediocregopher/radix/v3 v3.8.1/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i
 github.com/microcosm-cc/bluemonday v1.0.3/go.mod h1:8iwZnFn2CDDNZ0r6UXhF4xawGvzaqzCRa1n3/lO3W2w=
 github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58=
 github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs=
-github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g=
-github.com/minio/highwayhash v1.0.2/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
 github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
 github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
 github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
@@ -299,19 +297,14 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
 github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
 github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
-github.com/nats-io/jwt v0.3.2 h1:+RB5hMpXUUA2dfxuhBTEkMOrYmM+gKIZYS1KjSostMI=
 github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
-github.com/nats-io/jwt/v2 v2.5.3 h1:/9SWvzc6hTfamcgXJ3uYRpgj+QuY2aLNqRiqrKcrpEo=
-github.com/nats-io/jwt/v2 v2.5.3/go.mod h1:iysuPemFcc7p4IoYots3IuELSI4EDe9Y0bQMe+I3Bf4=
-github.com/nats-io/nats-server/v2 v2.9.11 h1:4y5SwWvWI59V5mcqtuoqKq6L9NDUydOP3Ekwuwl8cZI=
-github.com/nats-io/nats-server/v2 v2.9.11/go.mod h1:b0oVuxSlkvS3ZjMkncFeACGyZohbO4XhSqW1Lt7iRRY=
 github.com/nats-io/nats.go v1.9.2/go.mod h1:AjGArbfyR50+afOUotNX2Xs5SYHf+CoOa5HH1eEl2HE=
-github.com/nats-io/nats.go v1.28.0 h1:Th4G6zdsz2d0OqXdfzKLClo6bOfoI/b1kInhRtFIy5c=
-github.com/nats-io/nats.go v1.28.0/go.mod h1:XpbWUlOElGwTYbMR7imivs7jJj9GtK7ypv321Wp6pjc=
+github.com/nats-io/nats.go v1.31.0 h1:/WFBHEc/dOKBF6qf1TZhrdEfTmOZ5JzdJ+Y3m6Y/p7E=
+github.com/nats-io/nats.go v1.31.0/go.mod h1:di3Bm5MLsoB4Bx61CBTsxuarI36WbhAwOm8QrW39+i8=
 github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
 github.com/nats-io/nkeys v0.1.4/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s=
-github.com/nats-io/nkeys v0.4.6 h1:IzVe95ru2CT6ta874rt9saQRkWfe2nFj1NtvYSLqMzY=
-github.com/nats-io/nkeys v0.4.6/go.mod h1:4DxZNzenSVd1cYQoAa8948QY3QDjrHfcfVADymtkpts=
+github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI=
+github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc=
 github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
 github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
 github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
@@ -405,12 +398,13 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
 github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
 github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
 github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502/go.mod h1:p9lPsd+cx33L3H9nNoecRRxPssFKUwwI50I3pZ0yT+8=
-github.com/tdewolff/minify/v2 v2.20.6 h1:R4+Iw1ZqJxrqH52WWHtCpukMuhmO/EasY8YlDiSxphw=
-github.com/tdewolff/minify/v2 v2.20.6/go.mod h1:9t0EY9xySGt1vrP8iscmJfywQwDCQyQBYN6ge+9GwP0=
-github.com/tdewolff/parse/v2 v2.7.4 h1:zrUn2CFg9+5llbUZcsycctFlNRyV1D5gFBZRxuGzdzk=
-github.com/tdewolff/parse/v2 v2.7.4/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA=
-github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52 h1:gAQliwn+zJrkjAHVcBEYW/RFvd2St4yYimisvozAYlA=
+github.com/tdewolff/minify/v2 v2.20.14 h1:sktSuVixRwk0ryQjqvKBu/uYS+MWmkwEFMEWtFZ+TdE=
+github.com/tdewolff/minify/v2 v2.20.14/go.mod h1:qnIJbnG2dSzk7LIa/UUwgN2OjS8ir6RRlqc0T/1q2xY=
+github.com/tdewolff/parse/v2 v2.7.8 h1:1cnVqa8L63xFkc2vfRsZTM6Qy35nJpTvQ2Uvdv3vbvs=
+github.com/tdewolff/parse/v2 v2.7.8/go.mod h1:3FbJWZp3XT9OWVN3Hmfp0p/a08v4h8J9W1aghka0soA=
 github.com/tdewolff/test v1.0.11-0.20231101010635-f1265d231d52/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
+github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739 h1:IkjBCtQOOjIn03u/dMQK9g+Iw9ewps4mCl1nB8Sscbo=
+github.com/tdewolff/test v1.0.11-0.20240106005702-7de5f7df4739/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8=
 github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o=
 github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
 github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg=
@@ -486,16 +480,16 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
 golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
-golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
-golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
+golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
+golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
 golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/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-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
-golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
-golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
+golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o=
+golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
 golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
 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=
@@ -534,8 +528,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
 golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
 golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
 golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
-golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
-golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
+golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
+golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
 golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 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=
@@ -546,8 +540,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
-golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
+golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
+golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -574,8 +568,8 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
-golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
+golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=

+ 4 - 4
services/knowoapi/controllers/alert.go

@@ -4,11 +4,11 @@ import (
 	"sparrow/pkg/models"
 	"sparrow/services/knowoapi/services"
 
-	"github.com/kataras/iris"
-	"github.com/kataras/iris/mvc"
+	"github.com/kataras/iris/v12"
+	"github.com/kataras/iris/v12/mvc"
 )
 
-//AlertController api
+// AlertController api
 type AlertController struct {
 	Ctx     iris.Context
 	Service services.AlertService
@@ -32,7 +32,7 @@ func (a *AlertController) Post() {
 	done(a.Ctx, alert)
 }
 
-//Delete 删除
+// Delete 删除
 // DELETE /alert
 func (a *AlertController) Delete() {
 	alert := new(models.AlarmRule)

+ 1 - 1
services/knowoapi/controllers/application.go

@@ -12,7 +12,7 @@ import (
 
 	"github.com/opentracing/opentracing-go"
 
-	"github.com/kataras/iris"
+	"github.com/kataras/iris/v12"
 )
 
 // AppController api

+ 4 - 4
services/knowoapi/controllers/device.go

@@ -9,7 +9,7 @@ import (
 	"strconv"
 	"time"
 
-	"github.com/kataras/iris"
+	"github.com/kataras/iris/v12"
 )
 
 // DeviceController api
@@ -49,8 +49,8 @@ func (a *DeviceController) Get() {
 	})
 }
 
-//设备数量,包含在线数量,离线数量,总数量
-//GET /devicecount
+// 设备数量,包含在线数量,离线数量,总数量
+// GET /devicecount
 func (a *DeviceController) GetDevicecount() {
 	vid := a.getVendorID(a.Ctx)
 	data, err := a.Service.GetDevicesCountByVenderId(vid)
@@ -63,7 +63,7 @@ func (a *DeviceController) GetDevicecount() {
 	done(a.Ctx, data)
 }
 
-//获取设备在线状态
+// 获取设备在线状态
 // GET /devicestatus?device_id=
 func (a *DeviceController) GetDevicestatus() {
 

+ 1 - 1
services/knowoapi/controllers/errorresponse.go

@@ -4,7 +4,7 @@ import (
 	"fmt"
 	"sparrow/pkg/server"
 
-	"github.com/kataras/iris"
+	"github.com/kataras/iris/v12"
 )
 
 const (

+ 1 - 1
services/knowoapi/controllers/parsebody.go

@@ -3,7 +3,7 @@ package controllers
 import (
 	"sparrow/services/knowoapi/model"
 
-	"github.com/kataras/iris"
+	"github.com/kataras/iris/v12"
 )
 
 // parseBody 转化请求body

+ 1 - 1
services/knowoapi/controllers/product.go

@@ -8,7 +8,7 @@ import (
 	"sparrow/services/knowoapi/services"
 	"strings"
 
-	"github.com/kataras/iris"
+	"github.com/kataras/iris/v12"
 	opentracing "github.com/opentracing/opentracing-go"
 	"github.com/opentracing/opentracing-go/ext"
 )

+ 1 - 1
services/knowoapi/controllers/protocal.go

@@ -1,7 +1,7 @@
 package controllers
 
 import (
-	"github.com/kataras/iris"
+	"github.com/kataras/iris/v12"
 	"sparrow/pkg/models"
 	"sparrow/services/knowoapi/services"
 )

+ 2 - 2
services/knowoapi/controllers/role.go

@@ -4,7 +4,7 @@ import (
 	"sparrow/pkg/models"
 	"sparrow/services/knowoapi/services"
 
-	"github.com/kataras/iris"
+	"github.com/kataras/iris/v12"
 )
 
 // RoleController role
@@ -14,7 +14,7 @@ type RoleController struct {
 	Token   Token
 }
 
-// Post ``
+// Post 
 // POST /admin/role
 func (a *RoleController) Post() {
 	role := new(models.Role)

+ 1 - 1
services/knowoapi/controllers/rule_chain.go

@@ -1,7 +1,7 @@
 package controllers
 
 import (
-	"github.com/kataras/iris"
+	"github.com/kataras/iris/v12"
 	"sparrow/pkg/models"
 	"sparrow/services/knowoapi/services"
 )

+ 1 - 1
services/knowoapi/controllers/sensor.go

@@ -1,7 +1,7 @@
 package controllers
 
 import (
-	"github.com/kataras/iris"
+	"github.com/kataras/iris/v12"
 	"sparrow/pkg/models"
 	"sparrow/services/knowoapi/services"
 )

+ 1 - 1
services/knowoapi/controllers/sub_device.go

@@ -1,7 +1,7 @@
 package controllers
 
 import (
-	"github.com/kataras/iris"
+	"github.com/kataras/iris/v12"
 	"sparrow/services/knowoapi/services"
 )
 

+ 1 - 1
services/knowoapi/controllers/token.go

@@ -5,7 +5,7 @@ import (
 	"sparrow/services/knowoapi/model"
 	"time"
 
-	"github.com/kataras/iris"
+	"github.com/kataras/iris/v12"
 
 	jwt "github.com/dgrijalva/jwt-go"
 )

+ 2 - 2
services/knowoapi/controllers/user.go

@@ -6,7 +6,7 @@ import (
 	"sparrow/services/knowoapi/model"
 	"sparrow/services/knowoapi/services"
 
-	"github.com/kataras/iris"
+	"github.com/kataras/iris/v12"
 )
 
 // UserController api
@@ -42,7 +42,7 @@ func (a *UserController) PostLogin() {
 }
 
 // PostRegistry 注册
-//POST /registry
+// POST /registry
 func (a *UserController) PostRegistry() {
 	req := &models.Reqrequest{}
 	if err := parseBody(a.Ctx, req); err != nil {

BIN
services/knowoapi/knowoapi


+ 1 - 11
services/knowoapi/main.go

@@ -6,8 +6,7 @@ import (
 	"sparrow/pkg/server"
 	"sparrow/services/knowoapi/model"
 
-	"github.com/iris-contrib/middleware/cors"
-	"github.com/kataras/iris"
+	"github.com/kataras/iris/v12"
 )
 
 func main() {
@@ -33,15 +32,6 @@ func main() {
 
 func newApp() *iris.Application {
 	app := iris.New()
-	//cors
-	opts := cors.Options{
-		AllowedOrigins: []string{"*"},
-		AllowedHeaders: []string{"Content-Type", "Authorization"},
-		AllowedMethods: []string{"POST", "GET", "DELETE", "PUT"},
-		ExposedHeaders: []string{"X-Header"},
-		//Debug:          true,
-	}
-	app.Use(cors.New(opts))
 	app.AllowMethods(iris.MethodOptions)
 	registerErrors(app)
 	db, err := getDB()

+ 5 - 7
services/knowoapi/router.go

@@ -1,6 +1,7 @@
 package main
 
 import (
+	"github.com/kataras/iris/v12/mvc"
 	"sparrow/pkg/generator"
 	"sparrow/services/knowoapi/controllers"
 	"sparrow/services/knowoapi/model"
@@ -10,8 +11,7 @@ import (
 
 	jwt "github.com/dgrijalva/jwt-go"
 	jwtmiddleware "github.com/iris-contrib/middleware/jwt"
-	"github.com/kataras/iris"
-	"github.com/kataras/iris/mvc"
+	"github.com/kataras/iris/v12"
 )
 
 func registerErrors(srv *iris.Application) {
@@ -29,12 +29,10 @@ func handleErrors(ctx iris.Context) {
 // jwt 中间件配置
 func newJWThandle() func(ctx iris.Context) {
 	jwtHandler := jwtmiddleware.New(jwtmiddleware.Config{
-		ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) {
-			return []byte(model.SignedString), nil
-		},
-		ErrorHandler: func(ctx iris.Context, message string) {
+		ValidationKeyGetter: nil,
+		ErrorHandler: func(ctx iris.Context, err error) {
 			ctx.StatusCode(iris.StatusUnauthorized)
-			ctx.Values().Set("reason", message)
+			ctx.Values().Set("reason", err)
 		},
 		SigningMethod: jwt.SigningMethodHS256,
 	})

+ 7 - 0
vendor/github.com/andybalholm/brotli/README.md

@@ -2,6 +2,13 @@ This package is a brotli compressor and decompressor implemented in Go.
 It was translated from the reference implementation (https://github.com/google/brotli)
 with the `c2go` tool at https://github.com/andybalholm/c2go.
 
+I have been working on new compression algorithms (not translated from C)
+in the matchfinder package.
+You can use them with the NewWriterV2 function.
+Currently they give better results than the old implementation
+(at least for compressing my test file, Newton’s *Opticks*) 
+on levels 2 to 6.
+
 I am using it in production with https://github.com/andybalholm/redwood.
 
 API documentation is found at https://pkg.go.dev/github.com/andybalholm/brotli?tab=doc.

+ 56 - 0
vendor/github.com/andybalholm/brotli/bitwriter.go

@@ -0,0 +1,56 @@
+package brotli
+
+/* Copyright 2010 Google Inc. All Rights Reserved.
+
+   Distributed under MIT license.
+   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT
+*/
+
+/* Write bits into a byte array. */
+
+type bitWriter struct {
+	dst []byte
+
+	// Data waiting to be written is the low nbits of bits.
+	bits  uint64
+	nbits uint
+}
+
+func (w *bitWriter) writeBits(nb uint, b uint64) {
+	w.bits |= b << w.nbits
+	w.nbits += nb
+	if w.nbits >= 32 {
+		bits := w.bits
+		w.bits >>= 32
+		w.nbits -= 32
+		w.dst = append(w.dst,
+			byte(bits),
+			byte(bits>>8),
+			byte(bits>>16),
+			byte(bits>>24),
+		)
+	}
+}
+
+func (w *bitWriter) writeSingleBit(bit bool) {
+	if bit {
+		w.writeBits(1, 1)
+	} else {
+		w.writeBits(1, 0)
+	}
+}
+
+func (w *bitWriter) jumpToByteBoundary() {
+	dst := w.dst
+	for w.nbits != 0 {
+		dst = append(dst, byte(w.bits))
+		w.bits >>= 8
+		if w.nbits > 8 { // Avoid underflow
+			w.nbits -= 8
+		} else {
+			w.nbits = 0
+		}
+	}
+	w.bits = 0
+	w.dst = dst
+}

+ 275 - 36
vendor/github.com/andybalholm/brotli/brotli_bit_stream.go

@@ -7,12 +7,18 @@ import (
 
 const maxHuffmanTreeSize = (2*numCommandSymbols + 1)
 
-/* The maximum size of Huffman dictionary for distances assuming that
-   NPOSTFIX = 0 and NDIRECT = 0. */
+/*
+The maximum size of Huffman dictionary for distances assuming that
+
+	NPOSTFIX = 0 and NDIRECT = 0.
+*/
 const maxSimpleDistanceAlphabetSize = 140
 
-/* Represents the range of values belonging to a prefix code:
-   [offset, offset + 2^nbits) */
+/*
+Represents the range of values belonging to a prefix code:
+
+	[offset, offset + 2^nbits)
+*/
 type prefixCodeRange struct {
 	offset uint32
 	nbits  uint32
@@ -96,9 +102,12 @@ func nextBlockTypeCode(calculator *blockTypeCodeCalculator, type_ byte) uint {
 	return type_code
 }
 
-/* |nibblesbits| represents the 2 bits to encode MNIBBLES (0-3)
-   REQUIRES: length > 0
-   REQUIRES: length <= (1 << 24) */
+/*
+|nibblesbits| represents the 2 bits to encode MNIBBLES (0-3)
+
+	REQUIRES: length > 0
+	REQUIRES: length <= (1 << 24)
+*/
 func encodeMlen(length uint, bits *uint64, numbits *uint, nibblesbits *uint64) {
 	var lg uint
 	if length == 1 {
@@ -132,8 +141,11 @@ func storeCommandExtra(cmd *command, storage_ix *uint, storage []byte) {
 	writeBits(uint(insnumextra+getCopyExtra(copycode)), bits, storage_ix, storage)
 }
 
-/* Data structure that stores almost everything that is needed to encode each
-   block switch command. */
+/*
+Data structure that stores almost everything that is needed to encode each
+
+	block switch command.
+*/
 type blockSplitCode struct {
 	type_code_calculator blockTypeCodeCalculator
 	type_depths          [maxBlockTypeSymbols]byte
@@ -154,9 +166,12 @@ func storeVarLenUint8(n uint, storage_ix *uint, storage []byte) {
 	}
 }
 
-/* Stores the compressed meta-block header.
-   REQUIRES: length > 0
-   REQUIRES: length <= (1 << 24) */
+/*
+Stores the compressed meta-block header.
+
+	REQUIRES: length > 0
+	REQUIRES: length <= (1 << 24)
+*/
 func storeCompressedMetaBlockHeader(is_final_block bool, length uint, storage_ix *uint, storage []byte) {
 	var lenbits uint64
 	var nlenbits uint
@@ -186,9 +201,12 @@ func storeCompressedMetaBlockHeader(is_final_block bool, length uint, storage_ix
 	}
 }
 
-/* Stores the uncompressed meta-block header.
-   REQUIRES: length > 0
-   REQUIRES: length <= (1 << 24) */
+/*
+Stores the uncompressed meta-block header.
+
+	REQUIRES: length > 0
+	REQUIRES: length <= (1 << 24)
+*/
 func storeUncompressedMetaBlockHeader(length uint, storage_ix *uint, storage []byte) {
 	var lenbits uint64
 	var nlenbits uint
@@ -312,8 +330,11 @@ func storeSimpleHuffmanTree(depths []byte, symbols []uint, num_symbols uint, max
 	}
 }
 
-/* num = alphabet size
-   depths = symbol depths */
+/*
+num = alphabet size
+
+	depths = symbol depths
+*/
 func storeHuffmanTree(depths []byte, num uint, tree []huffmanTree, storage_ix *uint, storage []byte) {
 	var huffman_tree [numCommandSymbols]byte
 	var huffman_tree_extra_bits [numCommandSymbols]byte
@@ -367,8 +388,11 @@ func storeHuffmanTree(depths []byte, num uint, tree []huffmanTree, storage_ix *u
 	storeHuffmanTreeToBitMask(huffman_tree_size, huffman_tree[:], huffman_tree_extra_bits[:], code_length_bitdepth[:], code_length_bitdepth_symbols[:], storage_ix, storage)
 }
 
-/* Builds a Huffman tree from histogram[0:length] into depth[0:length] and
-   bits[0:length] and stores the encoded tree to the bit stream. */
+/*
+Builds a Huffman tree from histogram[0:length] into depth[0:length] and
+
+	bits[0:length] and stores the encoded tree to the bit stream.
+*/
 func buildAndStoreHuffmanTree(histogram []uint32, histogram_length uint, alphabet_size uint, tree []huffmanTree, depth []byte, bits []uint16, storage_ix *uint, storage []byte) {
 	var count uint = 0
 	var s4 = [4]uint{0}
@@ -623,6 +647,203 @@ func buildAndStoreHuffmanTreeFast(histogram []uint32, histogram_total uint, max_
 	}
 }
 
+func buildAndStoreHuffmanTreeFastBW(histogram []uint32, histogram_total uint, max_bits uint, depth []byte, bits []uint16, bw *bitWriter) {
+	var count uint = 0
+	var symbols = [4]uint{0}
+	var length uint = 0
+	var total uint = histogram_total
+	for total != 0 {
+		if histogram[length] != 0 {
+			if count < 4 {
+				symbols[count] = length
+			}
+
+			count++
+			total -= uint(histogram[length])
+		}
+
+		length++
+	}
+
+	if count <= 1 {
+		bw.writeBits(4, 1)
+		bw.writeBits(max_bits, uint64(symbols[0]))
+		depth[symbols[0]] = 0
+		bits[symbols[0]] = 0
+		return
+	}
+
+	for i := 0; i < int(length); i++ {
+		depth[i] = 0
+	}
+	{
+		var max_tree_size uint = 2*length + 1
+		tree, _ := huffmanTreePool.Get().(*[]huffmanTree)
+		if tree == nil || cap(*tree) < int(max_tree_size) {
+			tmp := make([]huffmanTree, max_tree_size)
+			tree = &tmp
+		} else {
+			*tree = (*tree)[:max_tree_size]
+		}
+		var count_limit uint32
+		for count_limit = 1; ; count_limit *= 2 {
+			var node int = 0
+			var l uint
+			for l = length; l != 0; {
+				l--
+				if histogram[l] != 0 {
+					if histogram[l] >= count_limit {
+						initHuffmanTree(&(*tree)[node:][0], histogram[l], -1, int16(l))
+					} else {
+						initHuffmanTree(&(*tree)[node:][0], count_limit, -1, int16(l))
+					}
+
+					node++
+				}
+			}
+			{
+				var n int = node
+				/* Points to the next leaf node. */ /* Points to the next non-leaf node. */
+				var sentinel huffmanTree
+				var i int = 0
+				var j int = n + 1
+				var k int
+
+				sortHuffmanTreeItems(*tree, uint(n), huffmanTreeComparator(sortHuffmanTree1))
+
+				/* The nodes are:
+				   [0, n): the sorted leaf nodes that we start with.
+				   [n]: we add a sentinel here.
+				   [n + 1, 2n): new parent nodes are added here, starting from
+				                (n+1). These are naturally in ascending order.
+				   [2n]: we add a sentinel at the end as well.
+				   There will be (2n+1) elements at the end. */
+				initHuffmanTree(&sentinel, math.MaxUint32, -1, -1)
+
+				(*tree)[node] = sentinel
+				node++
+				(*tree)[node] = sentinel
+				node++
+
+				for k = n - 1; k > 0; k-- {
+					var left int
+					var right int
+					if (*tree)[i].total_count_ <= (*tree)[j].total_count_ {
+						left = i
+						i++
+					} else {
+						left = j
+						j++
+					}
+
+					if (*tree)[i].total_count_ <= (*tree)[j].total_count_ {
+						right = i
+						i++
+					} else {
+						right = j
+						j++
+					}
+
+					/* The sentinel node becomes the parent node. */
+					(*tree)[node-1].total_count_ = (*tree)[left].total_count_ + (*tree)[right].total_count_
+
+					(*tree)[node-1].index_left_ = int16(left)
+					(*tree)[node-1].index_right_or_value_ = int16(right)
+
+					/* Add back the last sentinel node. */
+					(*tree)[node] = sentinel
+					node++
+				}
+
+				if setDepth(2*n-1, *tree, depth, 14) {
+					/* We need to pack the Huffman tree in 14 bits. If this was not
+					   successful, add fake entities to the lowest values and retry. */
+					break
+				}
+			}
+		}
+
+		huffmanTreePool.Put(tree)
+	}
+
+	convertBitDepthsToSymbols(depth, length, bits)
+	if count <= 4 {
+		var i uint
+
+		/* value of 1 indicates a simple Huffman code */
+		bw.writeBits(2, 1)
+
+		bw.writeBits(2, uint64(count)-1) /* NSYM - 1 */
+
+		/* Sort */
+		for i = 0; i < count; i++ {
+			var j uint
+			for j = i + 1; j < count; j++ {
+				if depth[symbols[j]] < depth[symbols[i]] {
+					var tmp uint = symbols[j]
+					symbols[j] = symbols[i]
+					symbols[i] = tmp
+				}
+			}
+		}
+
+		if count == 2 {
+			bw.writeBits(max_bits, uint64(symbols[0]))
+			bw.writeBits(max_bits, uint64(symbols[1]))
+		} else if count == 3 {
+			bw.writeBits(max_bits, uint64(symbols[0]))
+			bw.writeBits(max_bits, uint64(symbols[1]))
+			bw.writeBits(max_bits, uint64(symbols[2]))
+		} else {
+			bw.writeBits(max_bits, uint64(symbols[0]))
+			bw.writeBits(max_bits, uint64(symbols[1]))
+			bw.writeBits(max_bits, uint64(symbols[2]))
+			bw.writeBits(max_bits, uint64(symbols[3]))
+
+			/* tree-select */
+			bw.writeSingleBit(depth[symbols[0]] == 1)
+		}
+	} else {
+		var previous_value byte = 8
+		var i uint
+
+		/* Complex Huffman Tree */
+		storeStaticCodeLengthCodeBW(bw)
+
+		/* Actual RLE coding. */
+		for i = 0; i < length; {
+			var value byte = depth[i]
+			var reps uint = 1
+			var k uint
+			for k = i + 1; k < length && depth[k] == value; k++ {
+				reps++
+			}
+
+			i += reps
+			if value == 0 {
+				bw.writeBits(uint(kZeroRepsDepth[reps]), kZeroRepsBits[reps])
+			} else {
+				if previous_value != value {
+					bw.writeBits(uint(kCodeLengthDepth[value]), uint64(kCodeLengthBits[value]))
+					reps--
+				}
+
+				if reps < 3 {
+					for reps != 0 {
+						reps--
+						bw.writeBits(uint(kCodeLengthDepth[value]), uint64(kCodeLengthBits[value]))
+					}
+				} else {
+					reps -= 3
+					bw.writeBits(uint(kNonZeroRepsDepth[reps]), kNonZeroRepsBits[reps])
+				}
+
+				previous_value = value
+			}
+		}
+	}
+}
+
 func indexOf(v []byte, v_size uint, value byte) uint {
 	var i uint = 0
 	for ; i < v_size; i++ {
@@ -674,12 +895,15 @@ func moveToFrontTransform(v_in []uint32, v_size uint, v_out []uint32) {
 	}
 }
 
-/* Finds runs of zeros in v[0..in_size) and replaces them with a prefix code of
-   the run length plus extra bits (lower 9 bits is the prefix code and the rest
-   are the extra bits). Non-zero values in v[] are shifted by
-   *max_length_prefix. Will not create prefix codes bigger than the initial
-   value of *max_run_length_prefix. The prefix code of run length L is simply
-   Log2Floor(L) and the number of extra bits is the same as the prefix code. */
+/*
+Finds runs of zeros in v[0..in_size) and replaces them with a prefix code of
+
+	the run length plus extra bits (lower 9 bits is the prefix code and the rest
+	are the extra bits). Non-zero values in v[] are shifted by
+	*max_length_prefix. Will not create prefix codes bigger than the initial
+	value of *max_run_length_prefix. The prefix code of run length L is simply
+	Log2Floor(L) and the number of extra bits is the same as the prefix code.
+*/
 func runLengthCodeZeros(in_size uint, v []uint32, out_size *uint, max_run_length_prefix *uint32) {
 	var max_reps uint32 = 0
 	var i uint
@@ -799,8 +1023,11 @@ func storeBlockSwitch(code *blockSplitCode, block_len uint32, block_type byte, i
 	writeBits(uint(len_nextra), uint64(len_extra), storage_ix, storage)
 }
 
-/* Builds a BlockSplitCode data structure from the block split given by the
-   vector of block types and block lengths and stores it to the bit stream. */
+/*
+Builds a BlockSplitCode data structure from the block split given by the
+
+	vector of block types and block lengths and stores it to the bit stream.
+*/
 func buildAndStoreBlockSplitCode(types []byte, lengths []uint32, num_blocks uint, num_types uint, tree []huffmanTree, code *blockSplitCode, storage_ix *uint, storage []byte) {
 	var type_histo [maxBlockTypeSymbols]uint32
 	var length_histo [numBlockLenSymbols]uint32
@@ -919,14 +1146,20 @@ func cleanupBlockEncoder(self *blockEncoder) {
 	blockEncoderPool.Put(self)
 }
 
-/* Creates entropy codes of block lengths and block types and stores them
-   to the bit stream. */
+/*
+Creates entropy codes of block lengths and block types and stores them
+
+	to the bit stream.
+*/
 func buildAndStoreBlockSwitchEntropyCodes(self *blockEncoder, tree []huffmanTree, storage_ix *uint, storage []byte) {
 	buildAndStoreBlockSplitCode(self.block_types_, self.block_lengths_, self.num_blocks_, self.num_block_types_, tree, &self.block_split_code_, storage_ix, storage)
 }
 
-/* Stores the next symbol with the entropy code of the current block type.
-   Updates the block type and block length at block boundaries. */
+/*
+Stores the next symbol with the entropy code of the current block type.
+
+	Updates the block type and block length at block boundaries.
+*/
 func storeSymbol(self *blockEncoder, symbol uint, storage_ix *uint, storage []byte) {
 	if self.block_len_ == 0 {
 		self.block_ix_++
@@ -945,9 +1178,12 @@ func storeSymbol(self *blockEncoder, symbol uint, storage_ix *uint, storage []by
 	}
 }
 
-/* Stores the next symbol with the entropy code of the current block type and
-   context value.
-   Updates the block type and block length at block boundaries. */
+/*
+Stores the next symbol with the entropy code of the current block type and
+
+	context value.
+	Updates the block type and block length at block boundaries.
+*/
 func storeSymbolWithContext(self *blockEncoder, symbol uint, context uint, context_map []uint32, storage_ix *uint, storage []byte, context_bits uint) {
 	if self.block_len_ == 0 {
 		self.block_ix_++
@@ -1268,8 +1504,11 @@ func storeMetaBlockFast(input []byte, start_pos uint, length uint, mask uint, is
 	}
 }
 
-/* This is for storing uncompressed blocks (simple raw storage of
-   bytes-as-bytes). */
+/*
+This is for storing uncompressed blocks (simple raw storage of
+
+	bytes-as-bytes).
+*/
 func storeUncompressedMetaBlock(is_final_block bool, input []byte, position uint, mask uint, len uint, storage_ix *uint, storage []byte) {
 	var masked_pos uint = position & mask
 	storeUncompressedMetaBlockHeader(uint(len), storage_ix, storage)

+ 38 - 13
vendor/github.com/andybalholm/brotli/compress_fragment_two_pass.go

@@ -39,8 +39,11 @@ func isMatch1(p1 []byte, p2 []byte, length uint) bool {
 	return p1[4] == p2[4] && p1[5] == p2[5]
 }
 
-/* Builds a command and distance prefix code (each 64 symbols) into "depth" and
-   "bits" based on "histogram" and stores it into the bit stream. */
+/*
+Builds a command and distance prefix code (each 64 symbols) into "depth" and
+
+	"bits" based on "histogram" and stores it into the bit stream.
+*/
 func buildAndStoreCommandPrefixCode(histogram []uint32, depth []byte, bits []uint16, storage_ix *uint, storage []byte) {
 	var tree [129]huffmanTree
 	var cmd_depth = [numCommandSymbols]byte{0}
@@ -216,6 +219,25 @@ func storeMetaBlockHeader(len uint, is_uncompressed bool, storage_ix *uint, stor
 	writeSingleBit(is_uncompressed, storage_ix, storage)
 }
 
+func storeMetaBlockHeaderBW(len uint, is_uncompressed bool, bw *bitWriter) {
+	var nibbles uint = 6
+
+	/* ISLAST */
+	bw.writeBits(1, 0)
+
+	if len <= 1<<16 {
+		nibbles = 4
+	} else if len <= 1<<20 {
+		nibbles = 5
+	}
+
+	bw.writeBits(2, uint64(nibbles)-4)
+	bw.writeBits(nibbles*4, uint64(len)-1)
+
+	/* ISUNCOMPRESSED */
+	bw.writeSingleBit(is_uncompressed)
+}
+
 func createCommands(input []byte, block_size uint, input_size uint, base_ip_ptr []byte, table []int, table_bits uint, min_match uint, literals *[]byte, commands *[]uint32) {
 	var ip int = 0
 	var shift uint = 64 - table_bits
@@ -710,19 +732,22 @@ func compressFragmentTwoPassImpl(input []byte, input_size uint, is_last bool, co
 	}
 }
 
-/* Compresses "input" string to the "*storage" buffer as one or more complete
-   meta-blocks, and updates the "*storage_ix" bit position.
+/*
+Compresses "input" string to the "*storage" buffer as one or more complete
 
-   If "is_last" is 1, emits an additional empty last meta-block.
+	meta-blocks, and updates the "*storage_ix" bit position.
 
-   REQUIRES: "input_size" is greater than zero, or "is_last" is 1.
-   REQUIRES: "input_size" is less or equal to maximal metablock size (1 << 24).
-   REQUIRES: "command_buf" and "literal_buf" point to at least
-              kCompressFragmentTwoPassBlockSize long arrays.
-   REQUIRES: All elements in "table[0..table_size-1]" are initialized to zero.
-   REQUIRES: "table_size" is a power of two
-   OUTPUT: maximal copy distance <= |input_size|
-   OUTPUT: maximal copy distance <= BROTLI_MAX_BACKWARD_LIMIT(18) */
+	If "is_last" is 1, emits an additional empty last meta-block.
+
+	REQUIRES: "input_size" is greater than zero, or "is_last" is 1.
+	REQUIRES: "input_size" is less or equal to maximal metablock size (1 << 24).
+	REQUIRES: "command_buf" and "literal_buf" point to at least
+	           kCompressFragmentTwoPassBlockSize long arrays.
+	REQUIRES: All elements in "table[0..table_size-1]" are initialized to zero.
+	REQUIRES: "table_size" is a power of two
+	OUTPUT: maximal copy distance <= |input_size|
+	OUTPUT: maximal copy distance <= BROTLI_MAX_BACKWARD_LIMIT(18)
+*/
 func compressFragmentTwoPass(input []byte, input_size uint, is_last bool, command_buf []uint32, literal_buf []byte, table []int, table_size uint, storage_ix *uint, storage []byte) {
 	var initial_storage_ix uint = *storage_ix
 	var table_bits uint = uint(log2FloorNonZero(table_size))

+ 168 - 0
vendor/github.com/andybalholm/brotli/encoder.go

@@ -0,0 +1,168 @@
+package brotli
+
+import "github.com/andybalholm/brotli/matchfinder"
+
+// An Encoder implements the matchfinder.Encoder interface, writing in Brotli format.
+type Encoder struct {
+	wroteHeader bool
+	bw          bitWriter
+	distCache   []distanceCode
+}
+
+func (e *Encoder) Reset() {
+	e.wroteHeader = false
+	e.bw = bitWriter{}
+}
+
+func (e *Encoder) Encode(dst []byte, src []byte, matches []matchfinder.Match, lastBlock bool) []byte {
+	e.bw.dst = dst
+	if !e.wroteHeader {
+		e.bw.writeBits(4, 15)
+		e.wroteHeader = true
+	}
+
+	var literalHisto [256]uint32
+	var commandHisto [704]uint32
+	var distanceHisto [64]uint32
+	literalCount := 0
+	commandCount := 0
+	distanceCount := 0
+
+	if len(e.distCache) < len(matches) {
+		e.distCache = make([]distanceCode, len(matches))
+	}
+
+	// first pass: build the histograms
+	pos := 0
+
+	// d is the ring buffer of the last 4 distances.
+	d := [4]int{-10, -10, -10, -10}
+	for i, m := range matches {
+		if m.Unmatched > 0 {
+			for _, c := range src[pos : pos+m.Unmatched] {
+				literalHisto[c]++
+			}
+			literalCount += m.Unmatched
+		}
+
+		insertCode := getInsertLengthCode(uint(m.Unmatched))
+		copyCode := getCopyLengthCode(uint(m.Length))
+		if m.Length == 0 {
+			// If the stream ends with unmatched bytes, we need a dummy copy length.
+			copyCode = 2
+		}
+		command := combineLengthCodes(insertCode, copyCode, false)
+		commandHisto[command]++
+		commandCount++
+
+		if command >= 128 && m.Length != 0 {
+			var distCode distanceCode
+			switch m.Distance {
+			case d[3]:
+				distCode.code = 0
+			case d[2]:
+				distCode.code = 1
+			case d[1]:
+				distCode.code = 2
+			case d[0]:
+				distCode.code = 3
+			case d[3] - 1:
+				distCode.code = 4
+			case d[3] + 1:
+				distCode.code = 5
+			case d[3] - 2:
+				distCode.code = 6
+			case d[3] + 2:
+				distCode.code = 7
+			case d[3] - 3:
+				distCode.code = 8
+			case d[3] + 3:
+				distCode.code = 9
+
+				// In my testing, codes 10–15 actually reduced the compression ratio.
+
+			default:
+				distCode = getDistanceCode(m.Distance)
+			}
+			e.distCache[i] = distCode
+			distanceHisto[distCode.code]++
+			distanceCount++
+			if distCode.code != 0 {
+				d[0], d[1], d[2], d[3] = d[1], d[2], d[3], m.Distance
+			}
+		}
+
+		pos += m.Unmatched + m.Length
+	}
+
+	storeMetaBlockHeaderBW(uint(len(src)), false, &e.bw)
+	e.bw.writeBits(13, 0)
+
+	var literalDepths [256]byte
+	var literalBits [256]uint16
+	buildAndStoreHuffmanTreeFastBW(literalHisto[:], uint(literalCount), 8, literalDepths[:], literalBits[:], &e.bw)
+
+	var commandDepths [704]byte
+	var commandBits [704]uint16
+	buildAndStoreHuffmanTreeFastBW(commandHisto[:], uint(commandCount), 10, commandDepths[:], commandBits[:], &e.bw)
+
+	var distanceDepths [64]byte
+	var distanceBits [64]uint16
+	buildAndStoreHuffmanTreeFastBW(distanceHisto[:], uint(distanceCount), 6, distanceDepths[:], distanceBits[:], &e.bw)
+
+	pos = 0
+	for i, m := range matches {
+		insertCode := getInsertLengthCode(uint(m.Unmatched))
+		copyCode := getCopyLengthCode(uint(m.Length))
+		if m.Length == 0 {
+			// If the stream ends with unmatched bytes, we need a dummy copy length.
+			copyCode = 2
+		}
+		command := combineLengthCodes(insertCode, copyCode, false)
+		e.bw.writeBits(uint(commandDepths[command]), uint64(commandBits[command]))
+		if kInsExtra[insertCode] > 0 {
+			e.bw.writeBits(uint(kInsExtra[insertCode]), uint64(m.Unmatched)-uint64(kInsBase[insertCode]))
+		}
+		if kCopyExtra[copyCode] > 0 {
+			e.bw.writeBits(uint(kCopyExtra[copyCode]), uint64(m.Length)-uint64(kCopyBase[copyCode]))
+		}
+
+		if m.Unmatched > 0 {
+			for _, c := range src[pos : pos+m.Unmatched] {
+				e.bw.writeBits(uint(literalDepths[c]), uint64(literalBits[c]))
+			}
+		}
+
+		if command >= 128 && m.Length != 0 {
+			distCode := e.distCache[i]
+			e.bw.writeBits(uint(distanceDepths[distCode.code]), uint64(distanceBits[distCode.code]))
+			if distCode.nExtra > 0 {
+				e.bw.writeBits(distCode.nExtra, distCode.extraBits)
+			}
+		}
+
+		pos += m.Unmatched + m.Length
+	}
+
+	if lastBlock {
+		e.bw.writeBits(2, 3) // islast + isempty
+		e.bw.jumpToByteBoundary()
+	}
+	return e.bw.dst
+}
+
+type distanceCode struct {
+	code      int
+	nExtra    uint
+	extraBits uint64
+}
+
+func getDistanceCode(distance int) distanceCode {
+	d := distance + 3
+	nbits := log2FloorNonZero(uint(d)) - 1
+	prefix := (d >> nbits) & 1
+	offset := (2 + prefix) << nbits
+	distcode := int(2*(nbits-1)) + prefix + 16
+	extra := d - offset
+	return distanceCode{distcode, uint(nbits), uint64(extra)}
+}

+ 5 - 0
vendor/github.com/andybalholm/brotli/entropy_encode_static.go

@@ -782,6 +782,11 @@ func storeStaticCodeLengthCode(storage_ix *uint, storage []byte) {
 	writeBits(40, 0x0000FF55555554, storage_ix, storage)
 }
 
+func storeStaticCodeLengthCodeBW(bw *bitWriter) {
+	bw.writeBits(32, 0x55555554)
+	bw.writeBits(8, 0xFF)
+}
+
 var kZeroRepsBits = [numCommandSymbols]uint64{
 	0x00000000,
 	0x00000000,

+ 1 - 1
vendor/github.com/andybalholm/brotli/http.go

@@ -20,7 +20,7 @@ func HTTPCompressor(w http.ResponseWriter, r *http.Request) io.WriteCloser {
 	switch encoding {
 	case "br":
 		w.Header().Set("Content-Encoding", "br")
-		return NewWriter(w)
+		return NewWriterV2(w, DefaultCompression)
 	case "gzip":
 		w.Header().Set("Content-Encoding", "gzip")
 		return gzip.NewWriter(w)

+ 45 - 0
vendor/github.com/andybalholm/brotli/matchfinder/emitter.go

@@ -0,0 +1,45 @@
+package matchfinder
+
+// An absoluteMatch is like a Match, but it stores indexes into the byte
+// stream instead of lengths.
+type absoluteMatch struct {
+	// Start is the index of the first byte.
+	Start int
+
+	// End is the index of the byte after the last byte
+	// (so that End - Start = Length).
+	End int
+
+	// Match is the index of the previous data that matches
+	// (Start - Match = Distance).
+	Match int
+}
+
+// A matchEmitter manages the output of matches for a MatchFinder.
+type matchEmitter struct {
+	// Dst is the destination slice that Matches are added to.
+	Dst []Match
+
+	// NextEmit is the index of the next byte to emit.
+	NextEmit int
+}
+
+func (e *matchEmitter) emit(m absoluteMatch) {
+	e.Dst = append(e.Dst, Match{
+		Unmatched: m.Start - e.NextEmit,
+		Length:    m.End - m.Start,
+		Distance:  m.Start - m.Match,
+	})
+	e.NextEmit = m.End
+}
+
+// trim shortens m if it extends past maxEnd. Then if the length is at least
+// minLength, the match is emitted.
+func (e *matchEmitter) trim(m absoluteMatch, maxEnd int, minLength int) {
+	if m.End > maxEnd {
+		m.End = maxEnd
+	}
+	if m.End-m.Start >= minLength {
+		e.emit(m)
+	}
+}

+ 169 - 0
vendor/github.com/andybalholm/brotli/matchfinder/m0.go

@@ -0,0 +1,169 @@
+package matchfinder
+
+import (
+	"encoding/binary"
+)
+
+// M0 is an implementation of the MatchFinder interface based
+// on the algorithm used by snappy, but modified to be more like the algorithm
+// used by compression level 0 of the brotli reference implementation.
+//
+// It has a maximum block size of 65536 bytes.
+type M0 struct {
+	// Lazy turns on "lazy matching," for higher compression but less speed.
+	Lazy bool
+
+	MaxDistance int
+	MaxLength   int
+}
+
+func (M0) Reset() {}
+
+const (
+	m0HashLen = 5
+
+	m0TableBits = 14
+	m0TableSize = 1 << m0TableBits
+	m0Shift     = 32 - m0TableBits
+	// m0TableMask is redundant, but helps the compiler eliminate bounds
+	// checks.
+	m0TableMask = m0TableSize - 1
+)
+
+func (m M0) hash(data uint64) uint64 {
+	hash := (data << (64 - 8*m0HashLen)) * hashMul64
+	return hash >> (64 - m0TableBits)
+}
+
+// FindMatches looks for matches in src, appends them to dst, and returns dst.
+// src must not be longer than 65536 bytes.
+func (m M0) FindMatches(dst []Match, src []byte) []Match {
+	const inputMargin = 16 - 1
+	const minNonLiteralBlockSize = 1 + 1 + inputMargin
+
+	if len(src) < minNonLiteralBlockSize {
+		dst = append(dst, Match{
+			Unmatched: len(src),
+		})
+		return dst
+	}
+	if len(src) > 65536 {
+		panic("block too long")
+	}
+
+	var table [m0TableSize]uint16
+
+	// sLimit is when to stop looking for offset/length copies. The inputMargin
+	// lets us use a fast path for emitLiteral in the main loop, while we are
+	// looking for copies.
+	sLimit := len(src) - inputMargin
+
+	// nextEmit is where in src the next emitLiteral should start from.
+	nextEmit := 0
+
+	// The encoded form must start with a literal, as there are no previous
+	// bytes to copy, so we start looking for hash matches at s == 1.
+	s := 1
+	nextHash := m.hash(binary.LittleEndian.Uint64(src[s:]))
+
+	for {
+		// Copied from the C++ snappy implementation:
+		//
+		// Heuristic match skipping: If 32 bytes are scanned with no matches
+		// found, start looking only at every other byte. If 32 more bytes are
+		// scanned (or skipped), look at every third byte, etc.. When a match
+		// is found, immediately go back to looking at every byte. This is a
+		// small loss (~5% performance, ~0.1% density) for compressible data
+		// due to more bookkeeping, but for non-compressible data (such as
+		// JPEG) it's a huge win since the compressor quickly "realizes" the
+		// data is incompressible and doesn't bother looking for matches
+		// everywhere.
+		//
+		// The "skip" variable keeps track of how many bytes there are since
+		// the last match; dividing it by 32 (ie. right-shifting by five) gives
+		// the number of bytes to move ahead for each iteration.
+		skip := 32
+
+		nextS := s
+		candidate := 0
+		for {
+			s = nextS
+			bytesBetweenHashLookups := skip >> 5
+			nextS = s + bytesBetweenHashLookups
+			skip += bytesBetweenHashLookups
+			if nextS > sLimit {
+				goto emitRemainder
+			}
+			candidate = int(table[nextHash&m0TableMask])
+			table[nextHash&m0TableMask] = uint16(s)
+			nextHash = m.hash(binary.LittleEndian.Uint64(src[nextS:]))
+			if m.MaxDistance != 0 && s-candidate > m.MaxDistance {
+				continue
+			}
+			if binary.LittleEndian.Uint32(src[s:]) == binary.LittleEndian.Uint32(src[candidate:]) {
+				break
+			}
+		}
+
+		// Invariant: we have a 4-byte match at s.
+		base := s
+		s = extendMatch(src, candidate+4, s+4)
+
+		origBase := base
+		if m.Lazy && base+1 < sLimit {
+			newBase := base + 1
+			h := m.hash(binary.LittleEndian.Uint64(src[newBase:]))
+			newCandidate := int(table[h&m0TableMask])
+			table[h&m0TableMask] = uint16(newBase)
+			okDistance := true
+			if m.MaxDistance != 0 && newBase-newCandidate > m.MaxDistance {
+				okDistance = false
+			}
+			if okDistance && binary.LittleEndian.Uint32(src[newBase:]) == binary.LittleEndian.Uint32(src[newCandidate:]) {
+				newS := extendMatch(src, newCandidate+4, newBase+4)
+				if newS-newBase > s-base+1 {
+					s = newS
+					base = newBase
+					candidate = newCandidate
+				}
+			}
+		}
+
+		if m.MaxLength != 0 && s-base > m.MaxLength {
+			s = base + m.MaxLength
+		}
+		dst = append(dst, Match{
+			Unmatched: base - nextEmit,
+			Length:    s - base,
+			Distance:  base - candidate,
+		})
+		nextEmit = s
+		if s >= sLimit {
+			goto emitRemainder
+		}
+
+		if m.Lazy {
+			// If lazy matching is enabled, we update the hash table for
+			// every byte in the match.
+			for i := origBase + 2; i < s-1; i++ {
+				x := binary.LittleEndian.Uint64(src[i:])
+				table[m.hash(x)&m0TableMask] = uint16(i)
+			}
+		}
+
+		// We could immediately start working at s now, but to improve
+		// compression we first update the hash table at s-1 and at s.
+		x := binary.LittleEndian.Uint64(src[s-1:])
+		prevHash := m.hash(x >> 0)
+		table[prevHash&m0TableMask] = uint16(s - 1)
+		nextHash = m.hash(x >> 8)
+	}
+
+emitRemainder:
+	if nextEmit < len(src) {
+		dst = append(dst, Match{
+			Unmatched: len(src) - nextEmit,
+		})
+	}
+	return dst
+}

+ 297 - 0
vendor/github.com/andybalholm/brotli/matchfinder/m4.go

@@ -0,0 +1,297 @@
+package matchfinder
+
+import (
+	"encoding/binary"
+	"math/bits"
+	"runtime"
+)
+
+// M4 is an implementation of the MatchFinder
+// interface that uses a hash table to find matches,
+// optional match chains,
+// and the advanced parsing technique from
+// https://fastcompression.blogspot.com/2011/12/advanced-parsing-strategies.html.
+type M4 struct {
+	// MaxDistance is the maximum distance (in bytes) to look back for
+	// a match. The default is 65535.
+	MaxDistance int
+
+	// MinLength is the length of the shortest match to return.
+	// The default is 4.
+	MinLength int
+
+	// HashLen is the number of bytes to use to calculate the hashes.
+	// The maximum is 8 and the default is 6.
+	HashLen int
+
+	// TableBits is the number of bits in the hash table indexes.
+	// The default is 17 (128K entries).
+	TableBits int
+
+	// ChainLength is how many entries to search on the "match chain" of older
+	// locations with the same hash as the current location.
+	ChainLength int
+
+	// DistanceBitCost is used when comparing two matches to see
+	// which is better. The comparison is primarily based on the length
+	// of the matches, but it can also take the distance into account,
+	// in terms of the number of bits needed to represent the distance.
+	// One byte of length is given a score of 256, so 32 (256/8) would
+	// be a reasonable first guess for the value of one bit.
+	// (The default is 0, which bases the comparison solely on length.)
+	DistanceBitCost int
+
+	table []uint32
+	chain []uint16
+
+	history []byte
+}
+
+func (q *M4) Reset() {
+	for i := range q.table {
+		q.table[i] = 0
+	}
+	q.history = q.history[:0]
+	q.chain = q.chain[:0]
+}
+
+func (q *M4) score(m absoluteMatch) int {
+	return (m.End-m.Start)*256 + bits.LeadingZeros32(uint32(m.Start-m.Match))*q.DistanceBitCost
+}
+
+func (q *M4) FindMatches(dst []Match, src []byte) []Match {
+	if q.MaxDistance == 0 {
+		q.MaxDistance = 65535
+	}
+	if q.MinLength == 0 {
+		q.MinLength = 4
+	}
+	if q.HashLen == 0 {
+		q.HashLen = 6
+	}
+	if q.TableBits == 0 {
+		q.TableBits = 17
+	}
+	if len(q.table) < 1<<q.TableBits {
+		q.table = make([]uint32, 1<<q.TableBits)
+	}
+
+	e := matchEmitter{Dst: dst}
+
+	if len(q.history) > q.MaxDistance*2 {
+		// Trim down the history buffer.
+		delta := len(q.history) - q.MaxDistance
+		copy(q.history, q.history[delta:])
+		q.history = q.history[:q.MaxDistance]
+		if q.ChainLength > 0 {
+			q.chain = q.chain[:q.MaxDistance]
+		}
+
+		for i, v := range q.table {
+			newV := int(v) - delta
+			if newV < 0 {
+				newV = 0
+			}
+			q.table[i] = uint32(newV)
+		}
+	}
+
+	// Append src to the history buffer.
+	e.NextEmit = len(q.history)
+	q.history = append(q.history, src...)
+	if q.ChainLength > 0 {
+		q.chain = append(q.chain, make([]uint16, len(src))...)
+	}
+	src = q.history
+
+	// matches stores the matches that have been found but not emitted,
+	// in reverse order. (matches[0] is the most recent one.)
+	var matches [3]absoluteMatch
+	for i := e.NextEmit; i < len(src)-7; i++ {
+		if matches[0] != (absoluteMatch{}) && i >= matches[0].End {
+			// We have found some matches, and we're far enough along that we probably
+			// won't find overlapping matches, so we might as well emit them.
+			if matches[1] != (absoluteMatch{}) {
+				e.trim(matches[1], matches[0].Start, q.MinLength)
+			}
+			e.emit(matches[0])
+			matches = [3]absoluteMatch{}
+		}
+
+		// Calculate and store the hash.
+		h := ((binary.LittleEndian.Uint64(src[i:]) & (1<<(8*q.HashLen) - 1)) * hashMul64) >> (64 - q.TableBits)
+		candidate := int(q.table[h])
+		q.table[h] = uint32(i)
+		if q.ChainLength > 0 && candidate != 0 {
+			delta := i - candidate
+			if delta < 1<<16 {
+				q.chain[i] = uint16(delta)
+			}
+		}
+
+		if i < matches[0].End && i != matches[0].End+2-q.HashLen {
+			continue
+		}
+		if candidate == 0 || i-candidate > q.MaxDistance {
+			continue
+		}
+
+		// Look for a match.
+		var currentMatch absoluteMatch
+
+		if i-candidate != matches[0].Start-matches[0].Match {
+			if binary.LittleEndian.Uint32(src[candidate:]) == binary.LittleEndian.Uint32(src[i:]) {
+				m := extendMatch2(src, i, candidate, e.NextEmit)
+				if m.End-m.Start > q.MinLength {
+					currentMatch = m
+				}
+			}
+		}
+
+		for j := 0; j < q.ChainLength; j++ {
+			delta := q.chain[candidate]
+			if delta == 0 {
+				break
+			}
+			candidate -= int(delta)
+			if candidate <= 0 || i-candidate > q.MaxDistance {
+				break
+			}
+			if i-candidate != matches[0].Start-matches[0].Match {
+				if binary.LittleEndian.Uint32(src[candidate:]) == binary.LittleEndian.Uint32(src[i:]) {
+					m := extendMatch2(src, i, candidate, e.NextEmit)
+					if m.End-m.Start > q.MinLength && q.score(m) > q.score(currentMatch) {
+						currentMatch = m
+					}
+				}
+			}
+		}
+
+		if currentMatch.End-currentMatch.Start < q.MinLength {
+			continue
+		}
+
+		overlapPenalty := 0
+		if matches[0] != (absoluteMatch{}) {
+			overlapPenalty = 275
+			if currentMatch.Start <= matches[1].End {
+				// This match would completely replace the previous match,
+				// so there is no penalty for overlap.
+				overlapPenalty = 0
+			}
+		}
+
+		if q.score(currentMatch) <= q.score(matches[0])+overlapPenalty {
+			continue
+		}
+
+		matches = [3]absoluteMatch{
+			currentMatch,
+			matches[0],
+			matches[1],
+		}
+
+		if matches[2] == (absoluteMatch{}) {
+			continue
+		}
+
+		// We have three matches, so it's time to emit one and/or eliminate one.
+		switch {
+		case matches[0].Start < matches[2].End:
+			// The first and third matches overlap; discard the one in between.
+			matches = [3]absoluteMatch{
+				matches[0],
+				matches[2],
+				absoluteMatch{},
+			}
+
+		case matches[0].Start < matches[2].End+q.MinLength:
+			// The first and third matches don't overlap, but there's no room for
+			// another match between them. Emit the first match and discard the second.
+			e.emit(matches[2])
+			matches = [3]absoluteMatch{
+				matches[0],
+				absoluteMatch{},
+				absoluteMatch{},
+			}
+
+		default:
+			// Emit the first match, shortening it if necessary to avoid overlap with the second.
+			e.trim(matches[2], matches[1].Start, q.MinLength)
+			matches[2] = absoluteMatch{}
+		}
+	}
+
+	// We've found all the matches now; emit the remaining ones.
+	if matches[1] != (absoluteMatch{}) {
+		e.trim(matches[1], matches[0].Start, q.MinLength)
+	}
+	if matches[0] != (absoluteMatch{}) {
+		e.emit(matches[0])
+	}
+
+	dst = e.Dst
+	if e.NextEmit < len(src) {
+		dst = append(dst, Match{
+			Unmatched: len(src) - e.NextEmit,
+		})
+	}
+
+	return dst
+}
+
+const hashMul64 = 0x1E35A7BD1E35A7BD
+
+// extendMatch returns the largest k such that k <= len(src) and that
+// src[i:i+k-j] and src[j:k] have the same contents.
+//
+// It assumes that:
+//
+//	0 <= i && i < j && j <= len(src)
+func extendMatch(src []byte, i, j int) int {
+	switch runtime.GOARCH {
+	case "amd64":
+		// As long as we are 8 or more bytes before the end of src, we can load and
+		// compare 8 bytes at a time. If those 8 bytes are equal, repeat.
+		for j+8 < len(src) {
+			iBytes := binary.LittleEndian.Uint64(src[i:])
+			jBytes := binary.LittleEndian.Uint64(src[j:])
+			if iBytes != jBytes {
+				// If those 8 bytes were not equal, XOR the two 8 byte values, and return
+				// the index of the first byte that differs. The BSF instruction finds the
+				// least significant 1 bit, the amd64 architecture is little-endian, and
+				// the shift by 3 converts a bit index to a byte index.
+				return j + bits.TrailingZeros64(iBytes^jBytes)>>3
+			}
+			i, j = i+8, j+8
+		}
+	case "386":
+		// On a 32-bit CPU, we do it 4 bytes at a time.
+		for j+4 < len(src) {
+			iBytes := binary.LittleEndian.Uint32(src[i:])
+			jBytes := binary.LittleEndian.Uint32(src[j:])
+			if iBytes != jBytes {
+				return j + bits.TrailingZeros32(iBytes^jBytes)>>3
+			}
+			i, j = i+4, j+4
+		}
+	}
+	for ; j < len(src) && src[i] == src[j]; i, j = i+1, j+1 {
+	}
+	return j
+}
+
+// Given a 4-byte match at src[start] and src[candidate], extendMatch2 extends it
+// upward as far as possible, and downward no farther than to min.
+func extendMatch2(src []byte, start, candidate, min int) absoluteMatch {
+	end := extendMatch(src, candidate+4, start+4)
+	for start > min && candidate > 0 && src[start-1] == src[candidate-1] {
+		start--
+		candidate--
+	}
+	return absoluteMatch{
+		Start: start,
+		End:   end,
+		Match: candidate,
+	}
+}

+ 103 - 0
vendor/github.com/andybalholm/brotli/matchfinder/matchfinder.go

@@ -0,0 +1,103 @@
+// The matchfinder package defines reusable components for data compression.
+//
+// Many compression libraries have two main parts:
+//   - Something that looks for repeated sequences of bytes
+//   - An encoder for the compressed data format (often an entropy coder)
+//
+// Although these are logically two separate steps, the implementations are
+// usually closely tied together. You can't use flate's matcher with snappy's
+// encoder, for example. This package defines interfaces and an intermediate
+// representation to allow mixing and matching compression components.
+package matchfinder
+
+import "io"
+
+// A Match is the basic unit of LZ77 compression.
+type Match struct {
+	Unmatched int // the number of unmatched bytes since the previous match
+	Length    int // the number of bytes in the matched string; it may be 0 at the end of the input
+	Distance  int // how far back in the stream to copy from
+}
+
+// A MatchFinder performs the LZ77 stage of compression, looking for matches.
+type MatchFinder interface {
+	// FindMatches looks for matches in src, appends them to dst, and returns dst.
+	FindMatches(dst []Match, src []byte) []Match
+
+	// Reset clears any internal state, preparing the MatchFinder to be used with
+	// a new stream.
+	Reset()
+}
+
+// An Encoder encodes the data in its final format.
+type Encoder interface {
+	// Encode appends the encoded format of src to dst, using the match
+	// information from matches.
+	Encode(dst []byte, src []byte, matches []Match, lastBlock bool) []byte
+
+	// Reset clears any internal state, preparing the Encoder to be used with
+	// a new stream.
+	Reset()
+}
+
+// A Writer uses MatchFinder and Encoder to write compressed data to Dest.
+type Writer struct {
+	Dest        io.Writer
+	MatchFinder MatchFinder
+	Encoder     Encoder
+
+	// BlockSize is the number of bytes to compress at a time. If it is zero,
+	// each Write operation will be treated as one block.
+	BlockSize int
+
+	err     error
+	inBuf   []byte
+	outBuf  []byte
+	matches []Match
+}
+
+func (w *Writer) Write(p []byte) (n int, err error) {
+	if w.err != nil {
+		return 0, w.err
+	}
+
+	if w.BlockSize == 0 {
+		return w.writeBlock(p, false)
+	}
+
+	w.inBuf = append(w.inBuf, p...)
+	var pos int
+	for pos = 0; pos+w.BlockSize <= len(w.inBuf) && w.err == nil; pos += w.BlockSize {
+		w.writeBlock(w.inBuf[pos:pos+w.BlockSize], false)
+	}
+	if pos > 0 {
+		n := copy(w.inBuf, w.inBuf[pos:])
+		w.inBuf = w.inBuf[:n]
+	}
+
+	return len(p), w.err
+}
+
+func (w *Writer) writeBlock(p []byte, lastBlock bool) (n int, err error) {
+	w.outBuf = w.outBuf[:0]
+	w.matches = w.MatchFinder.FindMatches(w.matches[:0], p)
+	w.outBuf = w.Encoder.Encode(w.outBuf, p, w.matches, lastBlock)
+	_, w.err = w.Dest.Write(w.outBuf)
+	return len(p), w.err
+}
+
+func (w *Writer) Close() error {
+	w.writeBlock(w.inBuf, true)
+	w.inBuf = w.inBuf[:0]
+	return w.err
+}
+
+func (w *Writer) Reset(newDest io.Writer) {
+	w.MatchFinder.Reset()
+	w.Encoder.Reset()
+	w.err = nil
+	w.inBuf = w.inBuf[:0]
+	w.outBuf = w.outBuf[:0]
+	w.matches = w.matches[:0]
+	w.Dest = newDest
+}

+ 53 - 0
vendor/github.com/andybalholm/brotli/matchfinder/textencoder.go

@@ -0,0 +1,53 @@
+package matchfinder
+
+import "fmt"
+
+// A TextEncoder is an Encoder that produces a human-readable representation of
+// the LZ77 compression. Matches are replaced with <Length,Distance> symbols.
+type TextEncoder struct{}
+
+func (t TextEncoder) Reset() {}
+
+func (t TextEncoder) Encode(dst []byte, src []byte, matches []Match, lastBlock bool) []byte {
+	pos := 0
+	for _, m := range matches {
+		if m.Unmatched > 0 {
+			dst = append(dst, src[pos:pos+m.Unmatched]...)
+			pos += m.Unmatched
+		}
+		if m.Length > 0 {
+			dst = append(dst, []byte(fmt.Sprintf("<%d,%d>", m.Length, m.Distance))...)
+			pos += m.Length
+		}
+	}
+	if pos < len(src) {
+		dst = append(dst, src[pos:]...)
+	}
+	return dst
+}
+
+// A NoMatchFinder implements MatchFinder, but doesn't find any matches.
+// It can be used to implement the equivalent of the standard library flate package's
+// HuffmanOnly setting.
+type NoMatchFinder struct{}
+
+func (n NoMatchFinder) Reset() {}
+
+func (n NoMatchFinder) FindMatches(dst []Match, src []byte) []Match {
+	return append(dst, Match{
+		Unmatched: len(src),
+	})
+}
+
+// AutoReset wraps a MatchFinder that can return references to data in previous
+// blocks, and calls Reset before each block. It is useful for (e.g.) using a
+// snappy Encoder with a MatchFinder designed for flate. (Snappy doesn't
+// support references between blocks.)
+type AutoReset struct {
+	MatchFinder
+}
+
+func (a AutoReset) FindMatches(dst []Match, src []byte) []Match {
+	a.Reset()
+	return a.MatchFinder.FindMatches(dst, src)
+}

+ 43 - 0
vendor/github.com/andybalholm/brotli/writer.go

@@ -3,6 +3,8 @@ package brotli
 import (
 	"errors"
 	"io"
+
+	"github.com/andybalholm/brotli/matchfinder"
 )
 
 const (
@@ -117,3 +119,44 @@ type nopCloser struct {
 }
 
 func (nopCloser) Close() error { return nil }
+
+// NewWriterV2 is like NewWriterLevel, but it uses the new implementation
+// based on the matchfinder package. It currently supports up to level 7;
+// if a higher level is specified, level 7 will be used.
+func NewWriterV2(dst io.Writer, level int) *matchfinder.Writer {
+	var mf matchfinder.MatchFinder
+	if level < 2 {
+		mf = matchfinder.M0{Lazy: level == 1}
+	} else {
+		hashLen := 6
+		if level >= 6 {
+			hashLen = 5
+		}
+		chainLen := 64
+		switch level {
+		case 2:
+			chainLen = 0
+		case 3:
+			chainLen = 1
+		case 4:
+			chainLen = 2
+		case 5:
+			chainLen = 4
+		case 6:
+			chainLen = 8
+		}
+		mf = &matchfinder.M4{
+			MaxDistance:     1 << 20,
+			ChainLength:     chainLen,
+			HashLen:         hashLen,
+			DistanceBitCost: 57,
+		}
+	}
+
+	return &matchfinder.Writer{
+		Dest:        dst,
+		MatchFinder: mf,
+		Encoder:     &Encoder{},
+		BlockSize:   1 << 16,
+	}
+}

+ 8 - 6
vendor/github.com/iris-contrib/middleware/cors/LICENSE → vendor/github.com/blang/semver/v4/LICENSE

@@ -1,15 +1,16 @@
-Copyright (c) 2014 Olivier Poitrey <rs@dailymotion.com>
-Copyright (c) 2018-2023 Gerasimos Maropoulos <kataras2006@hotmail.com>
+The MIT License
+
+Copyright (c) 2014 Benedikt Lang <github at benediktlang.de>
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
 in the Software without restriction, including without limitation the rights
 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is furnished
-to do so, subject to the following conditions:
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
 
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
 
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
@@ -18,3 +19,4 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 THE SOFTWARE.
+

+ 23 - 0
vendor/github.com/blang/semver/v4/json.go

@@ -0,0 +1,23 @@
+package semver
+
+import (
+	"encoding/json"
+)
+
+// MarshalJSON implements the encoding/json.Marshaler interface.
+func (v Version) MarshalJSON() ([]byte, error) {
+	return json.Marshal(v.String())
+}
+
+// UnmarshalJSON implements the encoding/json.Unmarshaler interface.
+func (v *Version) UnmarshalJSON(data []byte) (err error) {
+	var versionString string
+
+	if err = json.Unmarshal(data, &versionString); err != nil {
+		return
+	}
+
+	*v, err = Parse(versionString)
+
+	return
+}

+ 416 - 0
vendor/github.com/blang/semver/v4/range.go

@@ -0,0 +1,416 @@
+package semver
+
+import (
+	"fmt"
+	"strconv"
+	"strings"
+	"unicode"
+)
+
+type wildcardType int
+
+const (
+	noneWildcard  wildcardType = iota
+	majorWildcard wildcardType = 1
+	minorWildcard wildcardType = 2
+	patchWildcard wildcardType = 3
+)
+
+func wildcardTypefromInt(i int) wildcardType {
+	switch i {
+	case 1:
+		return majorWildcard
+	case 2:
+		return minorWildcard
+	case 3:
+		return patchWildcard
+	default:
+		return noneWildcard
+	}
+}
+
+type comparator func(Version, Version) bool
+
+var (
+	compEQ comparator = func(v1 Version, v2 Version) bool {
+		return v1.Compare(v2) == 0
+	}
+	compNE = func(v1 Version, v2 Version) bool {
+		return v1.Compare(v2) != 0
+	}
+	compGT = func(v1 Version, v2 Version) bool {
+		return v1.Compare(v2) == 1
+	}
+	compGE = func(v1 Version, v2 Version) bool {
+		return v1.Compare(v2) >= 0
+	}
+	compLT = func(v1 Version, v2 Version) bool {
+		return v1.Compare(v2) == -1
+	}
+	compLE = func(v1 Version, v2 Version) bool {
+		return v1.Compare(v2) <= 0
+	}
+)
+
+type versionRange struct {
+	v Version
+	c comparator
+}
+
+// rangeFunc creates a Range from the given versionRange.
+func (vr *versionRange) rangeFunc() Range {
+	return Range(func(v Version) bool {
+		return vr.c(v, vr.v)
+	})
+}
+
+// Range represents a range of versions.
+// A Range can be used to check if a Version satisfies it:
+//
+//     range, err := semver.ParseRange(">1.0.0 <2.0.0")
+//     range(semver.MustParse("1.1.1") // returns true
+type Range func(Version) bool
+
+// OR combines the existing Range with another Range using logical OR.
+func (rf Range) OR(f Range) Range {
+	return Range(func(v Version) bool {
+		return rf(v) || f(v)
+	})
+}
+
+// AND combines the existing Range with another Range using logical AND.
+func (rf Range) AND(f Range) Range {
+	return Range(func(v Version) bool {
+		return rf(v) && f(v)
+	})
+}
+
+// ParseRange parses a range and returns a Range.
+// If the range could not be parsed an error is returned.
+//
+// Valid ranges are:
+//   - "<1.0.0"
+//   - "<=1.0.0"
+//   - ">1.0.0"
+//   - ">=1.0.0"
+//   - "1.0.0", "=1.0.0", "==1.0.0"
+//   - "!1.0.0", "!=1.0.0"
+//
+// A Range can consist of multiple ranges separated by space:
+// Ranges can be linked by logical AND:
+//   - ">1.0.0 <2.0.0" would match between both ranges, so "1.1.1" and "1.8.7" but not "1.0.0" or "2.0.0"
+//   - ">1.0.0 <3.0.0 !2.0.3-beta.2" would match every version between 1.0.0 and 3.0.0 except 2.0.3-beta.2
+//
+// Ranges can also be linked by logical OR:
+//   - "<2.0.0 || >=3.0.0" would match "1.x.x" and "3.x.x" but not "2.x.x"
+//
+// AND has a higher precedence than OR. It's not possible to use brackets.
+//
+// Ranges can be combined by both AND and OR
+//
+//  - `>1.0.0 <2.0.0 || >3.0.0 !4.2.1` would match `1.2.3`, `1.9.9`, `3.1.1`, but not `4.2.1`, `2.1.1`
+func ParseRange(s string) (Range, error) {
+	parts := splitAndTrim(s)
+	orParts, err := splitORParts(parts)
+	if err != nil {
+		return nil, err
+	}
+	expandedParts, err := expandWildcardVersion(orParts)
+	if err != nil {
+		return nil, err
+	}
+	var orFn Range
+	for _, p := range expandedParts {
+		var andFn Range
+		for _, ap := range p {
+			opStr, vStr, err := splitComparatorVersion(ap)
+			if err != nil {
+				return nil, err
+			}
+			vr, err := buildVersionRange(opStr, vStr)
+			if err != nil {
+				return nil, fmt.Errorf("Could not parse Range %q: %s", ap, err)
+			}
+			rf := vr.rangeFunc()
+
+			// Set function
+			if andFn == nil {
+				andFn = rf
+			} else { // Combine with existing function
+				andFn = andFn.AND(rf)
+			}
+		}
+		if orFn == nil {
+			orFn = andFn
+		} else {
+			orFn = orFn.OR(andFn)
+		}
+
+	}
+	return orFn, nil
+}
+
+// splitORParts splits the already cleaned parts by '||'.
+// Checks for invalid positions of the operator and returns an
+// error if found.
+func splitORParts(parts []string) ([][]string, error) {
+	var ORparts [][]string
+	last := 0
+	for i, p := range parts {
+		if p == "||" {
+			if i == 0 {
+				return nil, fmt.Errorf("First element in range is '||'")
+			}
+			ORparts = append(ORparts, parts[last:i])
+			last = i + 1
+		}
+	}
+	if last == len(parts) {
+		return nil, fmt.Errorf("Last element in range is '||'")
+	}
+	ORparts = append(ORparts, parts[last:])
+	return ORparts, nil
+}
+
+// buildVersionRange takes a slice of 2: operator and version
+// and builds a versionRange, otherwise an error.
+func buildVersionRange(opStr, vStr string) (*versionRange, error) {
+	c := parseComparator(opStr)
+	if c == nil {
+		return nil, fmt.Errorf("Could not parse comparator %q in %q", opStr, strings.Join([]string{opStr, vStr}, ""))
+	}
+	v, err := Parse(vStr)
+	if err != nil {
+		return nil, fmt.Errorf("Could not parse version %q in %q: %s", vStr, strings.Join([]string{opStr, vStr}, ""), err)
+	}
+
+	return &versionRange{
+		v: v,
+		c: c,
+	}, nil
+
+}
+
+// inArray checks if a byte is contained in an array of bytes
+func inArray(s byte, list []byte) bool {
+	for _, el := range list {
+		if el == s {
+			return true
+		}
+	}
+	return false
+}
+
+// splitAndTrim splits a range string by spaces and cleans whitespaces
+func splitAndTrim(s string) (result []string) {
+	last := 0
+	var lastChar byte
+	excludeFromSplit := []byte{'>', '<', '='}
+	for i := 0; i < len(s); i++ {
+		if s[i] == ' ' && !inArray(lastChar, excludeFromSplit) {
+			if last < i-1 {
+				result = append(result, s[last:i])
+			}
+			last = i + 1
+		} else if s[i] != ' ' {
+			lastChar = s[i]
+		}
+	}
+	if last < len(s)-1 {
+		result = append(result, s[last:])
+	}
+
+	for i, v := range result {
+		result[i] = strings.Replace(v, " ", "", -1)
+	}
+
+	// parts := strings.Split(s, " ")
+	// for _, x := range parts {
+	// 	if s := strings.TrimSpace(x); len(s) != 0 {
+	// 		result = append(result, s)
+	// 	}
+	// }
+	return
+}
+
+// splitComparatorVersion splits the comparator from the version.
+// Input must be free of leading or trailing spaces.
+func splitComparatorVersion(s string) (string, string, error) {
+	i := strings.IndexFunc(s, unicode.IsDigit)
+	if i == -1 {
+		return "", "", fmt.Errorf("Could not get version from string: %q", s)
+	}
+	return strings.TrimSpace(s[0:i]), s[i:], nil
+}
+
+// getWildcardType will return the type of wildcard that the
+// passed version contains
+func getWildcardType(vStr string) wildcardType {
+	parts := strings.Split(vStr, ".")
+	nparts := len(parts)
+	wildcard := parts[nparts-1]
+
+	possibleWildcardType := wildcardTypefromInt(nparts)
+	if wildcard == "x" {
+		return possibleWildcardType
+	}
+
+	return noneWildcard
+}
+
+// createVersionFromWildcard will convert a wildcard version
+// into a regular version, replacing 'x's with '0's, handling
+// special cases like '1.x.x' and '1.x'
+func createVersionFromWildcard(vStr string) string {
+	// handle 1.x.x
+	vStr2 := strings.Replace(vStr, ".x.x", ".x", 1)
+	vStr2 = strings.Replace(vStr2, ".x", ".0", 1)
+	parts := strings.Split(vStr2, ".")
+
+	// handle 1.x
+	if len(parts) == 2 {
+		return vStr2 + ".0"
+	}
+
+	return vStr2
+}
+
+// incrementMajorVersion will increment the major version
+// of the passed version
+func incrementMajorVersion(vStr string) (string, error) {
+	parts := strings.Split(vStr, ".")
+	i, err := strconv.Atoi(parts[0])
+	if err != nil {
+		return "", err
+	}
+	parts[0] = strconv.Itoa(i + 1)
+
+	return strings.Join(parts, "."), nil
+}
+
+// incrementMajorVersion will increment the minor version
+// of the passed version
+func incrementMinorVersion(vStr string) (string, error) {
+	parts := strings.Split(vStr, ".")
+	i, err := strconv.Atoi(parts[1])
+	if err != nil {
+		return "", err
+	}
+	parts[1] = strconv.Itoa(i + 1)
+
+	return strings.Join(parts, "."), nil
+}
+
+// expandWildcardVersion will expand wildcards inside versions
+// following these rules:
+//
+// * when dealing with patch wildcards:
+// >= 1.2.x    will become    >= 1.2.0
+// <= 1.2.x    will become    <  1.3.0
+// >  1.2.x    will become    >= 1.3.0
+// <  1.2.x    will become    <  1.2.0
+// != 1.2.x    will become    <  1.2.0 >= 1.3.0
+//
+// * when dealing with minor wildcards:
+// >= 1.x      will become    >= 1.0.0
+// <= 1.x      will become    <  2.0.0
+// >  1.x      will become    >= 2.0.0
+// <  1.0      will become    <  1.0.0
+// != 1.x      will become    <  1.0.0 >= 2.0.0
+//
+// * when dealing with wildcards without
+// version operator:
+// 1.2.x       will become    >= 1.2.0 < 1.3.0
+// 1.x         will become    >= 1.0.0 < 2.0.0
+func expandWildcardVersion(parts [][]string) ([][]string, error) {
+	var expandedParts [][]string
+	for _, p := range parts {
+		var newParts []string
+		for _, ap := range p {
+			if strings.Contains(ap, "x") {
+				opStr, vStr, err := splitComparatorVersion(ap)
+				if err != nil {
+					return nil, err
+				}
+
+				versionWildcardType := getWildcardType(vStr)
+				flatVersion := createVersionFromWildcard(vStr)
+
+				var resultOperator string
+				var shouldIncrementVersion bool
+				switch opStr {
+				case ">":
+					resultOperator = ">="
+					shouldIncrementVersion = true
+				case ">=":
+					resultOperator = ">="
+				case "<":
+					resultOperator = "<"
+				case "<=":
+					resultOperator = "<"
+					shouldIncrementVersion = true
+				case "", "=", "==":
+					newParts = append(newParts, ">="+flatVersion)
+					resultOperator = "<"
+					shouldIncrementVersion = true
+				case "!=", "!":
+					newParts = append(newParts, "<"+flatVersion)
+					resultOperator = ">="
+					shouldIncrementVersion = true
+				}
+
+				var resultVersion string
+				if shouldIncrementVersion {
+					switch versionWildcardType {
+					case patchWildcard:
+						resultVersion, _ = incrementMinorVersion(flatVersion)
+					case minorWildcard:
+						resultVersion, _ = incrementMajorVersion(flatVersion)
+					}
+				} else {
+					resultVersion = flatVersion
+				}
+
+				ap = resultOperator + resultVersion
+			}
+			newParts = append(newParts, ap)
+		}
+		expandedParts = append(expandedParts, newParts)
+	}
+
+	return expandedParts, nil
+}
+
+func parseComparator(s string) comparator {
+	switch s {
+	case "==":
+		fallthrough
+	case "":
+		fallthrough
+	case "=":
+		return compEQ
+	case ">":
+		return compGT
+	case ">=":
+		return compGE
+	case "<":
+		return compLT
+	case "<=":
+		return compLE
+	case "!":
+		fallthrough
+	case "!=":
+		return compNE
+	}
+
+	return nil
+}
+
+// MustParseRange is like ParseRange but panics if the range cannot be parsed.
+func MustParseRange(s string) Range {
+	r, err := ParseRange(s)
+	if err != nil {
+		panic(`semver: ParseRange(` + s + `): ` + err.Error())
+	}
+	return r
+}

+ 476 - 0
vendor/github.com/blang/semver/v4/semver.go

@@ -0,0 +1,476 @@
+package semver
+
+import (
+	"errors"
+	"fmt"
+	"strconv"
+	"strings"
+)
+
+const (
+	numbers  string = "0123456789"
+	alphas          = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-"
+	alphanum        = alphas + numbers
+)
+
+// SpecVersion is the latest fully supported spec version of semver
+var SpecVersion = Version{
+	Major: 2,
+	Minor: 0,
+	Patch: 0,
+}
+
+// Version represents a semver compatible version
+type Version struct {
+	Major uint64
+	Minor uint64
+	Patch uint64
+	Pre   []PRVersion
+	Build []string //No Precedence
+}
+
+// Version to string
+func (v Version) String() string {
+	b := make([]byte, 0, 5)
+	b = strconv.AppendUint(b, v.Major, 10)
+	b = append(b, '.')
+	b = strconv.AppendUint(b, v.Minor, 10)
+	b = append(b, '.')
+	b = strconv.AppendUint(b, v.Patch, 10)
+
+	if len(v.Pre) > 0 {
+		b = append(b, '-')
+		b = append(b, v.Pre[0].String()...)
+
+		for _, pre := range v.Pre[1:] {
+			b = append(b, '.')
+			b = append(b, pre.String()...)
+		}
+	}
+
+	if len(v.Build) > 0 {
+		b = append(b, '+')
+		b = append(b, v.Build[0]...)
+
+		for _, build := range v.Build[1:] {
+			b = append(b, '.')
+			b = append(b, build...)
+		}
+	}
+
+	return string(b)
+}
+
+// FinalizeVersion discards prerelease and build number and only returns
+// major, minor and patch number.
+func (v Version) FinalizeVersion() string {
+	b := make([]byte, 0, 5)
+	b = strconv.AppendUint(b, v.Major, 10)
+	b = append(b, '.')
+	b = strconv.AppendUint(b, v.Minor, 10)
+	b = append(b, '.')
+	b = strconv.AppendUint(b, v.Patch, 10)
+	return string(b)
+}
+
+// Equals checks if v is equal to o.
+func (v Version) Equals(o Version) bool {
+	return (v.Compare(o) == 0)
+}
+
+// EQ checks if v is equal to o.
+func (v Version) EQ(o Version) bool {
+	return (v.Compare(o) == 0)
+}
+
+// NE checks if v is not equal to o.
+func (v Version) NE(o Version) bool {
+	return (v.Compare(o) != 0)
+}
+
+// GT checks if v is greater than o.
+func (v Version) GT(o Version) bool {
+	return (v.Compare(o) == 1)
+}
+
+// GTE checks if v is greater than or equal to o.
+func (v Version) GTE(o Version) bool {
+	return (v.Compare(o) >= 0)
+}
+
+// GE checks if v is greater than or equal to o.
+func (v Version) GE(o Version) bool {
+	return (v.Compare(o) >= 0)
+}
+
+// LT checks if v is less than o.
+func (v Version) LT(o Version) bool {
+	return (v.Compare(o) == -1)
+}
+
+// LTE checks if v is less than or equal to o.
+func (v Version) LTE(o Version) bool {
+	return (v.Compare(o) <= 0)
+}
+
+// LE checks if v is less than or equal to o.
+func (v Version) LE(o Version) bool {
+	return (v.Compare(o) <= 0)
+}
+
+// Compare compares Versions v to o:
+// -1 == v is less than o
+// 0 == v is equal to o
+// 1 == v is greater than o
+func (v Version) Compare(o Version) int {
+	if v.Major != o.Major {
+		if v.Major > o.Major {
+			return 1
+		}
+		return -1
+	}
+	if v.Minor != o.Minor {
+		if v.Minor > o.Minor {
+			return 1
+		}
+		return -1
+	}
+	if v.Patch != o.Patch {
+		if v.Patch > o.Patch {
+			return 1
+		}
+		return -1
+	}
+
+	// Quick comparison if a version has no prerelease versions
+	if len(v.Pre) == 0 && len(o.Pre) == 0 {
+		return 0
+	} else if len(v.Pre) == 0 && len(o.Pre) > 0 {
+		return 1
+	} else if len(v.Pre) > 0 && len(o.Pre) == 0 {
+		return -1
+	}
+
+	i := 0
+	for ; i < len(v.Pre) && i < len(o.Pre); i++ {
+		if comp := v.Pre[i].Compare(o.Pre[i]); comp == 0 {
+			continue
+		} else if comp == 1 {
+			return 1
+		} else {
+			return -1
+		}
+	}
+
+	// If all pr versions are the equal but one has further prversion, this one greater
+	if i == len(v.Pre) && i == len(o.Pre) {
+		return 0
+	} else if i == len(v.Pre) && i < len(o.Pre) {
+		return -1
+	} else {
+		return 1
+	}
+
+}
+
+// IncrementPatch increments the patch version
+func (v *Version) IncrementPatch() error {
+	v.Patch++
+	return nil
+}
+
+// IncrementMinor increments the minor version
+func (v *Version) IncrementMinor() error {
+	v.Minor++
+	v.Patch = 0
+	return nil
+}
+
+// IncrementMajor increments the major version
+func (v *Version) IncrementMajor() error {
+	v.Major++
+	v.Minor = 0
+	v.Patch = 0
+	return nil
+}
+
+// Validate validates v and returns error in case
+func (v Version) Validate() error {
+	// Major, Minor, Patch already validated using uint64
+
+	for _, pre := range v.Pre {
+		if !pre.IsNum { //Numeric prerelease versions already uint64
+			if len(pre.VersionStr) == 0 {
+				return fmt.Errorf("Prerelease can not be empty %q", pre.VersionStr)
+			}
+			if !containsOnly(pre.VersionStr, alphanum) {
+				return fmt.Errorf("Invalid character(s) found in prerelease %q", pre.VersionStr)
+			}
+		}
+	}
+
+	for _, build := range v.Build {
+		if len(build) == 0 {
+			return fmt.Errorf("Build meta data can not be empty %q", build)
+		}
+		if !containsOnly(build, alphanum) {
+			return fmt.Errorf("Invalid character(s) found in build meta data %q", build)
+		}
+	}
+
+	return nil
+}
+
+// New is an alias for Parse and returns a pointer, parses version string and returns a validated Version or error
+func New(s string) (*Version, error) {
+	v, err := Parse(s)
+	vp := &v
+	return vp, err
+}
+
+// Make is an alias for Parse, parses version string and returns a validated Version or error
+func Make(s string) (Version, error) {
+	return Parse(s)
+}
+
+// ParseTolerant allows for certain version specifications that do not strictly adhere to semver
+// specs to be parsed by this library. It does so by normalizing versions before passing them to
+// Parse(). It currently trims spaces, removes a "v" prefix, adds a 0 patch number to versions
+// with only major and minor components specified, and removes leading 0s.
+func ParseTolerant(s string) (Version, error) {
+	s = strings.TrimSpace(s)
+	s = strings.TrimPrefix(s, "v")
+
+	// Split into major.minor.(patch+pr+meta)
+	parts := strings.SplitN(s, ".", 3)
+	// Remove leading zeros.
+	for i, p := range parts {
+		if len(p) > 1 {
+			p = strings.TrimLeft(p, "0")
+			if len(p) == 0 || !strings.ContainsAny(p[0:1], "0123456789") {
+				p = "0" + p
+			}
+			parts[i] = p
+		}
+	}
+	// Fill up shortened versions.
+	if len(parts) < 3 {
+		if strings.ContainsAny(parts[len(parts)-1], "+-") {
+			return Version{}, errors.New("Short version cannot contain PreRelease/Build meta data")
+		}
+		for len(parts) < 3 {
+			parts = append(parts, "0")
+		}
+	}
+	s = strings.Join(parts, ".")
+
+	return Parse(s)
+}
+
+// Parse parses version string and returns a validated Version or error
+func Parse(s string) (Version, error) {
+	if len(s) == 0 {
+		return Version{}, errors.New("Version string empty")
+	}
+
+	// Split into major.minor.(patch+pr+meta)
+	parts := strings.SplitN(s, ".", 3)
+	if len(parts) != 3 {
+		return Version{}, errors.New("No Major.Minor.Patch elements found")
+	}
+
+	// Major
+	if !containsOnly(parts[0], numbers) {
+		return Version{}, fmt.Errorf("Invalid character(s) found in major number %q", parts[0])
+	}
+	if hasLeadingZeroes(parts[0]) {
+		return Version{}, fmt.Errorf("Major number must not contain leading zeroes %q", parts[0])
+	}
+	major, err := strconv.ParseUint(parts[0], 10, 64)
+	if err != nil {
+		return Version{}, err
+	}
+
+	// Minor
+	if !containsOnly(parts[1], numbers) {
+		return Version{}, fmt.Errorf("Invalid character(s) found in minor number %q", parts[1])
+	}
+	if hasLeadingZeroes(parts[1]) {
+		return Version{}, fmt.Errorf("Minor number must not contain leading zeroes %q", parts[1])
+	}
+	minor, err := strconv.ParseUint(parts[1], 10, 64)
+	if err != nil {
+		return Version{}, err
+	}
+
+	v := Version{}
+	v.Major = major
+	v.Minor = minor
+
+	var build, prerelease []string
+	patchStr := parts[2]
+
+	if buildIndex := strings.IndexRune(patchStr, '+'); buildIndex != -1 {
+		build = strings.Split(patchStr[buildIndex+1:], ".")
+		patchStr = patchStr[:buildIndex]
+	}
+
+	if preIndex := strings.IndexRune(patchStr, '-'); preIndex != -1 {
+		prerelease = strings.Split(patchStr[preIndex+1:], ".")
+		patchStr = patchStr[:preIndex]
+	}
+
+	if !containsOnly(patchStr, numbers) {
+		return Version{}, fmt.Errorf("Invalid character(s) found in patch number %q", patchStr)
+	}
+	if hasLeadingZeroes(patchStr) {
+		return Version{}, fmt.Errorf("Patch number must not contain leading zeroes %q", patchStr)
+	}
+	patch, err := strconv.ParseUint(patchStr, 10, 64)
+	if err != nil {
+		return Version{}, err
+	}
+
+	v.Patch = patch
+
+	// Prerelease
+	for _, prstr := range prerelease {
+		parsedPR, err := NewPRVersion(prstr)
+		if err != nil {
+			return Version{}, err
+		}
+		v.Pre = append(v.Pre, parsedPR)
+	}
+
+	// Build meta data
+	for _, str := range build {
+		if len(str) == 0 {
+			return Version{}, errors.New("Build meta data is empty")
+		}
+		if !containsOnly(str, alphanum) {
+			return Version{}, fmt.Errorf("Invalid character(s) found in build meta data %q", str)
+		}
+		v.Build = append(v.Build, str)
+	}
+
+	return v, nil
+}
+
+// MustParse is like Parse but panics if the version cannot be parsed.
+func MustParse(s string) Version {
+	v, err := Parse(s)
+	if err != nil {
+		panic(`semver: Parse(` + s + `): ` + err.Error())
+	}
+	return v
+}
+
+// PRVersion represents a PreRelease Version
+type PRVersion struct {
+	VersionStr string
+	VersionNum uint64
+	IsNum      bool
+}
+
+// NewPRVersion creates a new valid prerelease version
+func NewPRVersion(s string) (PRVersion, error) {
+	if len(s) == 0 {
+		return PRVersion{}, errors.New("Prerelease is empty")
+	}
+	v := PRVersion{}
+	if containsOnly(s, numbers) {
+		if hasLeadingZeroes(s) {
+			return PRVersion{}, fmt.Errorf("Numeric PreRelease version must not contain leading zeroes %q", s)
+		}
+		num, err := strconv.ParseUint(s, 10, 64)
+
+		// Might never be hit, but just in case
+		if err != nil {
+			return PRVersion{}, err
+		}
+		v.VersionNum = num
+		v.IsNum = true
+	} else if containsOnly(s, alphanum) {
+		v.VersionStr = s
+		v.IsNum = false
+	} else {
+		return PRVersion{}, fmt.Errorf("Invalid character(s) found in prerelease %q", s)
+	}
+	return v, nil
+}
+
+// IsNumeric checks if prerelease-version is numeric
+func (v PRVersion) IsNumeric() bool {
+	return v.IsNum
+}
+
+// Compare compares two PreRelease Versions v and o:
+// -1 == v is less than o
+// 0 == v is equal to o
+// 1 == v is greater than o
+func (v PRVersion) Compare(o PRVersion) int {
+	if v.IsNum && !o.IsNum {
+		return -1
+	} else if !v.IsNum && o.IsNum {
+		return 1
+	} else if v.IsNum && o.IsNum {
+		if v.VersionNum == o.VersionNum {
+			return 0
+		} else if v.VersionNum > o.VersionNum {
+			return 1
+		} else {
+			return -1
+		}
+	} else { // both are Alphas
+		if v.VersionStr == o.VersionStr {
+			return 0
+		} else if v.VersionStr > o.VersionStr {
+			return 1
+		} else {
+			return -1
+		}
+	}
+}
+
+// PreRelease version to string
+func (v PRVersion) String() string {
+	if v.IsNum {
+		return strconv.FormatUint(v.VersionNum, 10)
+	}
+	return v.VersionStr
+}
+
+func containsOnly(s string, set string) bool {
+	return strings.IndexFunc(s, func(r rune) bool {
+		return !strings.ContainsRune(set, r)
+	}) == -1
+}
+
+func hasLeadingZeroes(s string) bool {
+	return len(s) > 1 && s[0] == '0'
+}
+
+// NewBuildVersion creates a new valid build version
+func NewBuildVersion(s string) (string, error) {
+	if len(s) == 0 {
+		return "", errors.New("Buildversion is empty")
+	}
+	if !containsOnly(s, alphanum) {
+		return "", fmt.Errorf("Invalid character(s) found in build meta data %q", s)
+	}
+	return s, nil
+}
+
+// FinalizeVersion returns the major, minor and patch number only and discards
+// prerelease and build number.
+func FinalizeVersion(s string) (string, error) {
+	v, err := Parse(s)
+	if err != nil {
+		return "", err
+	}
+	v.Pre = nil
+	v.Build = nil
+
+	finalVer := v.String()
+	return finalVer, nil
+}

+ 28 - 0
vendor/github.com/blang/semver/v4/sort.go

@@ -0,0 +1,28 @@
+package semver
+
+import (
+	"sort"
+)
+
+// Versions represents multiple versions.
+type Versions []Version
+
+// Len returns length of version collection
+func (s Versions) Len() int {
+	return len(s)
+}
+
+// Swap swaps two versions inside the collection by its indices
+func (s Versions) Swap(i, j int) {
+	s[i], s[j] = s[j], s[i]
+}
+
+// Less checks if version at index i is less than version at index j
+func (s Versions) Less(i, j int) bool {
+	return s[i].LT(s[j])
+}
+
+// Sort sorts a slice of versions
+func Sort(versions []Version) {
+	sort.Sort(Versions(versions))
+}

+ 30 - 0
vendor/github.com/blang/semver/v4/sql.go

@@ -0,0 +1,30 @@
+package semver
+
+import (
+	"database/sql/driver"
+	"fmt"
+)
+
+// Scan implements the database/sql.Scanner interface.
+func (v *Version) Scan(src interface{}) (err error) {
+	var str string
+	switch src := src.(type) {
+	case string:
+		str = src
+	case []byte:
+		str = string(src)
+	default:
+		return fmt.Errorf("version.Scan: cannot convert %T to string", src)
+	}
+
+	if t, err := Parse(str); err == nil {
+		*v = t
+	}
+
+	return
+}
+
+// Value implements the database/sql/driver.Valuer interface.
+func (v Version) Value() (driver.Value, error) {
+	return v.String(), nil
+}

+ 8 - 1
vendor/github.com/gobwas/ws/dialer.go

@@ -87,6 +87,13 @@ type Dialer struct {
 	// land.
 	Header HandshakeHeader
 
+	// Host is an optional string that could be used to specify the host during
+	// HTTP upgrade request by setting 'Host' header.
+	//
+	// Default value is an empty string, which results in setting 'Host' header
+	// equal to the URL hostname given to Dialer.Dial().
+	Host string
+
 	// OnStatusError is the callback that will be called after receiving non
 	// "101 Continue" HTTP response status. It receives an io.Reader object
 	// representing server response bytes. That is, it gives ability to parse
@@ -310,7 +317,7 @@ func (d Dialer) Upgrade(conn io.ReadWriter, u *url.URL) (br *bufio.Reader, hs Ha
 	nonce := make([]byte, nonceSize)
 	initNonce(nonce)
 
-	httpWriteUpgradeRequest(bw, u, nonce, d.Protocols, d.Extensions, d.Header)
+	httpWriteUpgradeRequest(bw, u, nonce, d.Protocols, d.Extensions, d.Header, d.Host)
 	if err := bw.Flush(); err != nil {
 		return br, hs, err
 	}

+ 5 - 1
vendor/github.com/gobwas/ws/http.go

@@ -286,12 +286,16 @@ func httpWriteUpgradeRequest(
 	protocols []string,
 	extensions []httphead.Option,
 	header HandshakeHeader,
+	host string,
 ) {
 	bw.WriteString("GET ")
 	bw.WriteString(u.RequestURI())
 	bw.WriteString(" HTTP/1.1\r\n")
 
-	httpWriteHeader(bw, headerHost, u.Host)
+	if host == "" {
+		host = u.Host
+	}
+	httpWriteHeader(bw, headerHost, host)
 
 	httpWriteHeaderBts(bw, headerUpgrade, specHeaderValueUpgrade)
 	httpWriteHeaderBts(bw, headerConnection, specHeaderValueConnection)

+ 90 - 6
vendor/github.com/gobwas/ws/wsutil/reader.go

@@ -1,6 +1,7 @@
 package wsutil
 
 import (
+	"encoding/binary"
 	"errors"
 	"io"
 	"io/ioutil"
@@ -56,10 +57,12 @@ type Reader struct {
 	OnContinuation FrameHandlerFunc
 	OnIntermediate FrameHandlerFunc
 
-	opCode ws.OpCode        // Used to store message op code on fragmentation.
-	frame  io.Reader        // Used to as frame reader.
-	raw    io.LimitedReader // Used to discard frames without cipher.
-	utf8   UTF8Reader       // Used to check UTF8 sequences if CheckUTF8 is true.
+	opCode ws.OpCode                  // Used to store message op code on fragmentation.
+	frame  io.Reader                  // Used to as frame reader.
+	raw    io.LimitedReader           // Used to discard frames without cipher.
+	utf8   UTF8Reader                 // Used to check UTF8 sequences if CheckUTF8 is true.
+	tmp    [ws.MaxHeaderSize - 2]byte // Used for reading headers.
+	cr     *CipherReader              // Used by NextFrame() to unmask frame payload.
 }
 
 // NewReader creates new frame reader that reads from r keeping given state to
@@ -165,7 +168,7 @@ func (r *Reader) Discard() (err error) {
 // Note that next NextFrame() call must be done after receiving or discarding
 // all current message bytes.
 func (r *Reader) NextFrame() (hdr ws.Header, err error) {
-	hdr, err = ws.ReadHeader(r.Source)
+	hdr, err = r.readHeader(r.Source)
 	if err == io.EOF && r.fragmented() {
 		// If we are in fragmented state EOF means that is was totally
 		// unexpected.
@@ -196,7 +199,12 @@ func (r *Reader) NextFrame() (hdr ws.Header, err error) {
 
 	frame := io.Reader(&r.raw)
 	if hdr.Masked {
-		frame = NewCipherReader(frame, hdr.Mask)
+		if r.cr == nil {
+			r.cr = NewCipherReader(frame, hdr.Mask)
+		} else {
+			r.cr.Reset(frame, hdr.Mask)
+		}
+		frame = r.cr
 	}
 
 	for _, x := range r.Extensions {
@@ -261,6 +269,82 @@ func (r *Reader) reset() {
 	r.opCode = 0
 }
 
+// readHeader reads a frame header from in.
+func (r *Reader) readHeader(in io.Reader) (h ws.Header, err error) {
+	// Make slice of bytes with capacity 12 that could hold any header.
+	//
+	// The maximum header size is 14, but due to the 2 hop reads,
+	// after first hop that reads first 2 constant bytes, we could reuse 2 bytes.
+	// So 14 - 2 = 12.
+	bts := r.tmp[:2]
+
+	// Prepare to hold first 2 bytes to choose size of next read.
+	_, err = io.ReadFull(in, bts)
+	if err != nil {
+		return h, err
+	}
+	const bit0 = 0x80
+
+	h.Fin = bts[0]&bit0 != 0
+	h.Rsv = (bts[0] & 0x70) >> 4
+	h.OpCode = ws.OpCode(bts[0] & 0x0f)
+
+	var extra int
+
+	if bts[1]&bit0 != 0 {
+		h.Masked = true
+		extra += 4
+	}
+
+	length := bts[1] & 0x7f
+	switch {
+	case length < 126:
+		h.Length = int64(length)
+
+	case length == 126:
+		extra += 2
+
+	case length == 127:
+		extra += 8
+
+	default:
+		err = ws.ErrHeaderLengthUnexpected
+		return h, err
+	}
+
+	if extra == 0 {
+		return h, err
+	}
+
+	// Increase len of bts to extra bytes need to read.
+	// Overwrite first 2 bytes that was read before.
+	bts = bts[:extra]
+	_, err = io.ReadFull(in, bts)
+	if err != nil {
+		return h, err
+	}
+
+	switch {
+	case length == 126:
+		h.Length = int64(binary.BigEndian.Uint16(bts[:2]))
+		bts = bts[2:]
+
+	case length == 127:
+		if bts[0]&0x80 != 0 {
+			err = ws.ErrHeaderLengthMSB
+			return h, err
+		}
+		h.Length = int64(binary.BigEndian.Uint64(bts[:8]))
+		bts = bts[8:]
+	}
+
+	if h.Masked {
+		copy(h.Mask[:], bts)
+	}
+
+	return h, nil
+}
+
 // NextReader prepares next message read from r. It returns header that
 // describes the message and io.Reader to read message's payload. It returns
 // non-nil error when it is not possible to read message's initial frame.

+ 1 - 1
vendor/github.com/gomarkdown/markdown/README.md

@@ -226,7 +226,7 @@ implements the following extensions:
 - **Hard line breaks**. With this extension enabled newlines in the input
   translates into line breaks in the output. This extension is off by default.
 
-- **Non blocking space**. With this extension enabled spaces preceeded by a backslash
+- **Non blocking space**. With this extension enabled spaces preceded by a backslash
   in the input translates non-blocking spaces in the output. This extension is off by default.
 
 - **Smart quotes**. Smartypants-style punctuation substitution is

+ 1 - 1
vendor/github.com/gomarkdown/markdown/parser/inline.go

@@ -736,7 +736,7 @@ func leftAngle(p *Parser, data []byte, offset int) (int, ast.Node) {
 }
 
 // '\\' backslash escape
-var escapeChars = []byte("\\`*_{}[]()#+-.!:|&<>~^")
+var escapeChars = []byte("\\`*_{}[]()#+-.!:|&<>~^$")
 
 func escape(p *Parser, data []byte, offset int) (int, ast.Node) {
 	data = data[offset:]

+ 7 - 0
vendor/github.com/google/uuid/CHANGELOG.md

@@ -1,5 +1,12 @@
 # Changelog
 
+## [1.5.0](https://github.com/google/uuid/compare/v1.4.0...v1.5.0) (2023-12-12)
+
+
+### Features
+
+* Validate UUID without creating new UUID ([#141](https://github.com/google/uuid/issues/141)) ([9ee7366](https://github.com/google/uuid/commit/9ee7366e66c9ad96bab89139418a713dc584ae29))
+
 ## [1.4.0](https://github.com/google/uuid/compare/v1.3.1...v1.4.0) (2023-10-26)
 
 

+ 16 - 5
vendor/github.com/google/uuid/time.go

@@ -108,12 +108,23 @@ func setClockSequence(seq int) {
 }
 
 // Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in
-// uuid.  The time is only defined for version 1 and 2 UUIDs.
+// uuid.  The time is only defined for version 1, 2, 6 and 7 UUIDs.
 func (uuid UUID) Time() Time {
-	time := int64(binary.BigEndian.Uint32(uuid[0:4]))
-	time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32
-	time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48
-	return Time(time)
+	var t Time
+	switch uuid.Version() {
+	case 6:
+		time := binary.BigEndian.Uint64(uuid[:8]) // Ignore uuid[6] version b0110
+		t = Time(time)
+	case 7:
+		time := binary.BigEndian.Uint64(uuid[:8])
+		t = Time((time>>16)*10000 + g1582ns100)
+	default: // forward compatible
+		time := int64(binary.BigEndian.Uint32(uuid[0:4]))
+		time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32
+		time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48
+		t = Time(time)
+	}
+	return t
 }
 
 // ClockSequence returns the clock sequence encoded in uuid.

+ 53 - 0
vendor/github.com/google/uuid/uuid.go

@@ -186,6 +186,59 @@ func Must(uuid UUID, err error) UUID {
 	return uuid
 }
 
+// Validate returns an error if s is not a properly formatted UUID in one of the following formats:
+//   xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+//   urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
+//   xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+//   {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
+// It returns an error if the format is invalid, otherwise nil.
+func Validate(s string) error {
+	switch len(s) {
+	// Standard UUID format
+	case 36:
+
+	// UUID with "urn:uuid:" prefix
+	case 36 + 9:
+		if !strings.EqualFold(s[:9], "urn:uuid:") {
+			return fmt.Errorf("invalid urn prefix: %q", s[:9])
+		}
+		s = s[9:]
+
+	// UUID enclosed in braces
+	case 36 + 2:
+		if s[0] != '{' || s[len(s)-1] != '}' {
+			return fmt.Errorf("invalid bracketed UUID format")
+		}
+		s = s[1 : len(s)-1]
+
+	// UUID without hyphens
+	case 32:
+		for i := 0; i < len(s); i += 2 {
+			_, ok := xtob(s[i], s[i+1])
+			if !ok {
+				return errors.New("invalid UUID format")
+			}
+		}
+
+	default:
+		return invalidLengthError{len(s)}
+	}
+
+	// Check for standard UUID format
+	if len(s) == 36 {
+		if s[8] != '-' || s[13] != '-' || s[18] != '-' || s[23] != '-' {
+			return errors.New("invalid UUID format")
+		}
+		for _, x := range []int{0, 2, 4, 6, 9, 11, 14, 16, 19, 21, 24, 26, 28, 30, 32, 34} {
+			if _, ok := xtob(s[x], s[x+1]); !ok {
+				return errors.New("invalid UUID format")
+			}
+		}
+	}
+
+	return nil
+}
+
 // String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
 // , or "" if uuid is invalid.
 func (uuid UUID) String() string {

+ 56 - 0
vendor/github.com/google/uuid/version6.go

@@ -0,0 +1,56 @@
+// Copyright 2023 Google Inc.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package uuid
+
+import "encoding/binary"
+
+// UUID version 6 is a field-compatible version of UUIDv1, reordered for improved DB locality.
+// It is expected that UUIDv6 will primarily be used in contexts where there are existing v1 UUIDs.
+// Systems that do not involve legacy UUIDv1 SHOULD consider using UUIDv7 instead.
+//
+// see https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-03#uuidv6
+//
+// NewV6 returns a Version 6 UUID based on the current NodeID and clock
+// sequence, and the current time. If the NodeID has not been set by SetNodeID
+// or SetNodeInterface then it will be set automatically. If the NodeID cannot
+// be set NewV6 set NodeID is random bits automatically . If clock sequence has not been set by
+// SetClockSequence then it will be set automatically. If GetTime fails to
+// return the current NewV6 returns Nil and an error.
+func NewV6() (UUID, error) {
+	var uuid UUID
+	now, seq, err := GetTime()
+	if err != nil {
+		return uuid, err
+	}
+
+	/*
+	    0                   1                   2                   3
+	    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+	   |                           time_high                           |
+	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+	   |           time_mid            |      time_low_and_version     |
+	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+	   |clk_seq_hi_res |  clk_seq_low  |         node (0-1)            |
+	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+	   |                         node (2-5)                            |
+	   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+	*/
+
+	binary.BigEndian.PutUint64(uuid[0:], uint64(now))
+	binary.BigEndian.PutUint16(uuid[8:], seq)
+
+	uuid[6] = 0x60 | (uuid[6] & 0x0F)
+	uuid[8] = 0x80 | (uuid[8] & 0x3F)
+
+	nodeMu.Lock()
+	if nodeID == zeroID {
+		setNodeInterface("")
+	}
+	copy(uuid[10:], nodeID[:])
+	nodeMu.Unlock()
+
+	return uuid, nil
+}

+ 75 - 0
vendor/github.com/google/uuid/version7.go

@@ -0,0 +1,75 @@
+// Copyright 2023 Google Inc.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package uuid
+
+import (
+	"io"
+)
+
+// UUID version 7 features a time-ordered value field derived from the widely
+// implemented and well known Unix Epoch timestamp source,
+// the number of milliseconds seconds since midnight 1 Jan 1970 UTC, leap seconds excluded.
+// As well as improved entropy characteristics over versions 1 or 6.
+//
+// see https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-03#name-uuid-version-7
+//
+// Implementations SHOULD utilize UUID version 7 over UUID version 1 and 6 if possible.
+//
+// NewV7 returns a Version 7 UUID based on the current time(Unix Epoch).
+// Uses the randomness pool if it was enabled with EnableRandPool.
+// On error, NewV7 returns Nil and an error
+func NewV7() (UUID, error) {
+	uuid, err := NewRandom()
+	if err != nil {
+		return uuid, err
+	}
+	makeV7(uuid[:])
+	return uuid, nil
+}
+
+// NewV7FromReader returns a Version 7 UUID based on the current time(Unix Epoch).
+// it use NewRandomFromReader fill random bits.
+// On error, NewV7FromReader returns Nil and an error.
+func NewV7FromReader(r io.Reader) (UUID, error) {
+	uuid, err := NewRandomFromReader(r)
+	if err != nil {
+		return uuid, err
+	}
+
+	makeV7(uuid[:])
+	return uuid, nil
+}
+
+// makeV7 fill 48 bits time (uuid[0] - uuid[5]), set version b0111 (uuid[6])
+// uuid[8] already has the right version number (Variant is 10)
+// see function  NewV7 and NewV7FromReader
+func makeV7(uuid []byte) {
+	/*
+		 0                   1                   2                   3
+		 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+		+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+		|                           unix_ts_ms                          |
+		+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+		|          unix_ts_ms           |  ver  |       rand_a          |
+		+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+		|var|                        rand_b                             |
+		+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+		|                            rand_b                             |
+		+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+	*/
+	_ = uuid[15] // bounds check
+
+	t := timeNow().UnixMilli()
+
+	uuid[0] = byte(t >> 40)
+	uuid[1] = byte(t >> 32)
+	uuid[2] = byte(t >> 24)
+	uuid[3] = byte(t >> 16)
+	uuid[4] = byte(t >> 8)
+	uuid[5] = byte(t)
+
+	uuid[6] = 0x70 | (uuid[6] & 0x0F)
+	// uuid[8] has already has right version
+}

+ 20 - 0
vendor/github.com/gorilla/websocket/.editorconfig

@@ -0,0 +1,20 @@
+; https://editorconfig.org/
+
+root = true
+
+[*]
+insert_final_newline = true
+charset = utf-8
+trim_trailing_whitespace = true
+indent_style = space
+indent_size = 2
+
+[{Makefile,go.mod,go.sum,*.go,.gitmodules}]
+indent_style = tab
+indent_size = 4
+
+[*.md]
+indent_size = 4
+trim_trailing_whitespace = false
+
+eclint_indent_style = unset

+ 1 - 25
vendor/github.com/gorilla/websocket/.gitignore

@@ -1,25 +1 @@
-# Compiled Object files, Static and Dynamic libs (Shared Objects)
-*.o
-*.a
-*.so
-
-# Folders
-_obj
-_test
-
-# Architecture specific extensions/prefixes
-*.[568vq]
-[568vq].out
-
-*.cgo1.go
-*.cgo2.c
-_cgo_defun.c
-_cgo_gotypes.go
-_cgo_export.*
-
-_testmain.go
-
-*.exe
-
-.idea/
-*.iml
+coverage.coverprofile

+ 3 - 0
vendor/github.com/gorilla/websocket/.golangci.yml

@@ -0,0 +1,3 @@
+run:
+  skip-dirs:
+    - examples/*.go

+ 0 - 9
vendor/github.com/gorilla/websocket/AUTHORS

@@ -1,9 +0,0 @@
-# This is the official list of Gorilla WebSocket authors for copyright
-# purposes.
-#
-# Please keep the list sorted.
-
-Gary Burd <gary@beagledreams.com>
-Google LLC (https://opensource.google.com/)
-Joachim Bauch <mail@joachim-bauch.de>
-

+ 22 - 17
vendor/github.com/gorilla/websocket/LICENSE

@@ -1,22 +1,27 @@
-Copyright (c) 2013 The Gorilla WebSocket Authors. All rights reserved.
+Copyright (c) 2023 The Gorilla Authors. All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
+modification, are permitted provided that the following conditions are
+met:
 
-  Redistributions of source code must retain the above copyright notice, this
-  list of conditions and the following disclaimer.
+	 * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+	 * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+	 * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
 
-  Redistributions in binary form must reproduce the above copyright notice,
-  this list of conditions and the following disclaimer in the documentation
-  and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 34 - 0
vendor/github.com/gorilla/websocket/Makefile

@@ -0,0 +1,34 @@
+GO_LINT=$(shell which golangci-lint 2> /dev/null || echo '')
+GO_LINT_URI=github.com/golangci/golangci-lint/cmd/golangci-lint@latest
+
+GO_SEC=$(shell which gosec 2> /dev/null || echo '')
+GO_SEC_URI=github.com/securego/gosec/v2/cmd/gosec@latest
+
+GO_VULNCHECK=$(shell which govulncheck 2> /dev/null || echo '')
+GO_VULNCHECK_URI=golang.org/x/vuln/cmd/govulncheck@latest
+
+.PHONY: golangci-lint
+golangci-lint:
+	$(if $(GO_LINT), ,go install $(GO_LINT_URI))
+	@echo "##### Running golangci-lint"
+	golangci-lint run -v
+
+.PHONY: gosec
+gosec:
+	$(if $(GO_SEC), ,go install $(GO_SEC_URI))
+	@echo "##### Running gosec"
+	gosec -exclude-dir examples ./...
+
+.PHONY: govulncheck
+govulncheck:
+	$(if $(GO_VULNCHECK), ,go install $(GO_VULNCHECK_URI))
+	@echo "##### Running govulncheck"
+	govulncheck ./...
+
+.PHONY: verify
+verify: golangci-lint gosec govulncheck
+
+.PHONY: test
+test:
+	@echo "##### Running tests"
+	go test -race -cover -coverprofile=coverage.coverprofile -covermode=atomic -v ./...

+ 8 - 11
vendor/github.com/gorilla/websocket/README.md

@@ -1,17 +1,14 @@
-# Gorilla WebSocket
+# gorilla/websocket
 
-[![GoDoc](https://godoc.org/github.com/gorilla/websocket?status.svg)](https://godoc.org/github.com/gorilla/websocket)
-[![CircleCI](https://circleci.com/gh/gorilla/websocket.svg?style=svg)](https://circleci.com/gh/gorilla/websocket)
+![testing](https://github.com/gorilla/websocket/actions/workflows/test.yml/badge.svg)
+[![codecov](https://codecov.io/github/gorilla/websocket/branch/main/graph/badge.svg)](https://codecov.io/github/gorilla/websocket)
+[![godoc](https://godoc.org/github.com/gorilla/websocket?status.svg)](https://godoc.org/github.com/gorilla/websocket)
+[![sourcegraph](https://sourcegraph.com/github.com/gorilla/websocket/-/badge.svg)](https://sourcegraph.com/github.com/gorilla/websocket?badge)
 
-Gorilla WebSocket is a [Go](http://golang.org/) implementation of the
-[WebSocket](http://www.rfc-editor.org/rfc/rfc6455.txt) protocol.
+Gorilla WebSocket is a [Go](http://golang.org/) implementation of the [WebSocket](http://www.rfc-editor.org/rfc/rfc6455.txt) protocol.
 
+![Gorilla Logo](https://github.com/gorilla/.github/assets/53367916/d92caabf-98e0-473e-bfbf-ab554ba435e5)
 
----
-
-⚠️ **[The Gorilla WebSocket Package is looking for a new maintainer](https://github.com/gorilla/websocket/issues/370)**
-
----
 
 ### Documentation
 
@@ -20,6 +17,7 @@ Gorilla WebSocket is a [Go](http://golang.org/) implementation of the
 * [Command example](https://github.com/gorilla/websocket/tree/master/examples/command)
 * [Client and server example](https://github.com/gorilla/websocket/tree/master/examples/echo)
 * [File watch example](https://github.com/gorilla/websocket/tree/master/examples/filewatch)
+* [Write buffer pool example](https://github.com/gorilla/websocket/tree/master/examples/bufferpool)
 
 ### Status
 
@@ -36,4 +34,3 @@ package API is stable.
 The Gorilla WebSocket package passes the server tests in the [Autobahn Test
 Suite](https://github.com/crossbario/autobahn-testsuite) using the application in the [examples/autobahn
 subdirectory](https://github.com/gorilla/websocket/tree/master/examples/autobahn).
-

+ 33 - 11
vendor/github.com/gorilla/websocket/client.go

@@ -9,14 +9,18 @@ import (
 	"context"
 	"crypto/tls"
 	"errors"
+	"fmt"
 	"io"
-	"io/ioutil"
+	"log"
+
 	"net"
 	"net/http"
 	"net/http/httptrace"
 	"net/url"
 	"strings"
 	"time"
+
+	"golang.org/x/net/proxy"
 )
 
 // ErrBadHandshake is returned when the server response to opening handshake is
@@ -224,6 +228,7 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h
 			k == "Connection" ||
 			k == "Sec-Websocket-Key" ||
 			k == "Sec-Websocket-Version" ||
+			//#nosec G101 (CWE-798): Potential HTTP request smuggling via parameter pollution
 			k == "Sec-Websocket-Extensions" ||
 			(k == "Sec-Websocket-Protocol" && len(d.Subprotocols) > 0):
 			return nil, nil, errors.New("websocket: duplicate header not allowed: " + k)
@@ -289,7 +294,9 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h
 			}
 			err = c.SetDeadline(deadline)
 			if err != nil {
-				c.Close()
+				if err := c.Close(); err != nil {
+					log.Printf("websocket: failed to close network connection: %v", err)
+				}
 				return nil, err
 			}
 			return c, nil
@@ -303,7 +310,7 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h
 			return nil, nil, err
 		}
 		if proxyURL != nil {
-			dialer, err := proxy_FromURL(proxyURL, netDialerFunc(netDial))
+			dialer, err := proxy.FromURL(proxyURL, netDialerFunc(netDial))
 			if err != nil {
 				return nil, nil, err
 			}
@@ -318,18 +325,20 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h
 	}
 
 	netConn, err := netDial("tcp", hostPort)
+	if err != nil {
+		return nil, nil, err
+	}
 	if trace != nil && trace.GotConn != nil {
 		trace.GotConn(httptrace.GotConnInfo{
 			Conn: netConn,
 		})
 	}
-	if err != nil {
-		return nil, nil, err
-	}
 
 	defer func() {
 		if netConn != nil {
-			netConn.Close()
+			if err := netConn.Close(); err != nil {
+				log.Printf("websocket: failed to close network connection: %v", err)
+			}
 		}
 	}()
 
@@ -370,6 +379,17 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h
 
 	resp, err := http.ReadResponse(conn.br, req)
 	if err != nil {
+		if d.TLSClientConfig != nil {
+			for _, proto := range d.TLSClientConfig.NextProtos {
+				if proto != "http/1.1" {
+					return nil, nil, fmt.Errorf(
+						"websocket: protocol %q was given but is not supported;"+
+							"sharing tls.Config with net/http Transport can cause this error: %w",
+						proto, err,
+					)
+				}
+			}
+		}
 		return nil, nil, err
 	}
 
@@ -388,7 +408,7 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h
 		// debugging.
 		buf := make([]byte, 1024)
 		n, _ := io.ReadFull(resp.Body, buf)
-		resp.Body = ioutil.NopCloser(bytes.NewReader(buf[:n]))
+		resp.Body = io.NopCloser(bytes.NewReader(buf[:n]))
 		return nil, resp, ErrBadHandshake
 	}
 
@@ -406,17 +426,19 @@ func (d *Dialer) DialContext(ctx context.Context, urlStr string, requestHeader h
 		break
 	}
 
-	resp.Body = ioutil.NopCloser(bytes.NewReader([]byte{}))
+	resp.Body = io.NopCloser(bytes.NewReader([]byte{}))
 	conn.subprotocol = resp.Header.Get("Sec-Websocket-Protocol")
 
-	netConn.SetDeadline(time.Time{})
+	if err := netConn.SetDeadline(time.Time{}); err != nil {
+		return nil, nil, err
+	}
 	netConn = nil // to avoid close in defer.
 	return conn, resp, nil
 }
 
 func cloneTLSConfig(cfg *tls.Config) *tls.Config {
 	if cfg == nil {
-		return &tls.Config{}
+		return &tls.Config{MinVersion: tls.VersionTLS12}
 	}
 	return cfg.Clone()
 }

+ 7 - 2
vendor/github.com/gorilla/websocket/compression.go

@@ -8,6 +8,7 @@ import (
 	"compress/flate"
 	"errors"
 	"io"
+	"log"
 	"strings"
 	"sync"
 )
@@ -33,7 +34,9 @@ func decompressNoContextTakeover(r io.Reader) io.ReadCloser {
 		"\x01\x00\x00\xff\xff"
 
 	fr, _ := flateReaderPool.Get().(io.ReadCloser)
-	fr.(flate.Resetter).Reset(io.MultiReader(r, strings.NewReader(tail)), nil)
+	if err := fr.(flate.Resetter).Reset(io.MultiReader(r, strings.NewReader(tail)), nil); err != nil {
+		panic(err)
+	}
 	return &flateReadWrapper{fr}
 }
 
@@ -132,7 +135,9 @@ func (r *flateReadWrapper) Read(p []byte) (int, error) {
 		// Preemptively place the reader back in the pool. This helps with
 		// scenarios where the application does not call NextReader() soon after
 		// this final read.
-		r.Close()
+		if err := r.Close(); err != nil {
+			log.Printf("websocket: flateReadWrapper.Close() returned error: %v", err)
+		}
 	}
 	return n, err
 }

+ 60 - 23
vendor/github.com/gorilla/websocket/conn.go

@@ -6,11 +6,11 @@ package websocket
 
 import (
 	"bufio"
+	"crypto/rand"
 	"encoding/binary"
 	"errors"
 	"io"
-	"io/ioutil"
-	"math/rand"
+	"log"
 	"net"
 	"strconv"
 	"strings"
@@ -181,13 +181,20 @@ var (
 	errInvalidControlFrame = errors.New("websocket: invalid control frame")
 )
 
+// maskRand is an io.Reader for generating mask bytes. The reader is initialized
+// to crypto/rand Reader. Tests swap the reader to a math/rand reader for
+// reproducible results.
+var maskRand = rand.Reader
+
+// newMaskKey returns a new 32 bit value for masking client frames.
 func newMaskKey() [4]byte {
-	n := rand.Uint32()
-	return [4]byte{byte(n), byte(n >> 8), byte(n >> 16), byte(n >> 24)}
+	var k [4]byte
+	_, _ = io.ReadFull(maskRand, k[:])
+	return k
 }
 
 func hideTempErr(err error) error {
-	if e, ok := err.(net.Error); ok && e.Temporary() {
+	if e, ok := err.(net.Error); ok {
 		err = &netError{msg: e.Error(), timeout: e.Timeout()}
 	}
 	return err
@@ -372,7 +379,9 @@ func (c *Conn) read(n int) ([]byte, error) {
 	if err == io.EOF {
 		err = errUnexpectedEOF
 	}
-	c.br.Discard(len(p))
+	if _, err := c.br.Discard(len(p)); err != nil {
+		return p, err
+	}
 	return p, err
 }
 
@@ -387,7 +396,9 @@ func (c *Conn) write(frameType int, deadline time.Time, buf0, buf1 []byte) error
 		return err
 	}
 
-	c.conn.SetWriteDeadline(deadline)
+	if err := c.conn.SetWriteDeadline(deadline); err != nil {
+		return c.writeFatal(err)
+	}
 	if len(buf1) == 0 {
 		_, err = c.conn.Write(buf0)
 	} else {
@@ -397,7 +408,7 @@ func (c *Conn) write(frameType int, deadline time.Time, buf0, buf1 []byte) error
 		return c.writeFatal(err)
 	}
 	if frameType == CloseMessage {
-		c.writeFatal(ErrCloseSent)
+		_ = c.writeFatal(ErrCloseSent)
 	}
 	return nil
 }
@@ -438,7 +449,7 @@ func (c *Conn) WriteControl(messageType int, data []byte, deadline time.Time) er
 
 	d := 1000 * time.Hour
 	if !deadline.IsZero() {
-		d = deadline.Sub(time.Now())
+		d = time.Until(deadline)
 		if d < 0 {
 			return errWriteTimeout
 		}
@@ -460,13 +471,15 @@ func (c *Conn) WriteControl(messageType int, data []byte, deadline time.Time) er
 		return err
 	}
 
-	c.conn.SetWriteDeadline(deadline)
+	if err := c.conn.SetWriteDeadline(deadline); err != nil {
+		return c.writeFatal(err)
+	}
 	_, err = c.conn.Write(buf)
 	if err != nil {
 		return c.writeFatal(err)
 	}
 	if messageType == CloseMessage {
-		c.writeFatal(ErrCloseSent)
+		_ = c.writeFatal(ErrCloseSent)
 	}
 	return err
 }
@@ -477,7 +490,9 @@ func (c *Conn) beginMessage(mw *messageWriter, messageType int) error {
 	// probably better to return an error in this situation, but we cannot
 	// change this without breaking existing applications.
 	if c.writer != nil {
-		c.writer.Close()
+		if err := c.writer.Close(); err != nil {
+			log.Printf("websocket: discarding writer close error: %v", err)
+		}
 		c.writer = nil
 	}
 
@@ -630,7 +645,7 @@ func (w *messageWriter) flushFrame(final bool, extra []byte) error {
 	}
 
 	if final {
-		w.endMessage(errWriteClosed)
+		_ = w.endMessage(errWriteClosed)
 		return nil
 	}
 
@@ -795,7 +810,7 @@ func (c *Conn) advanceFrame() (int, error) {
 	// 1. Skip remainder of previous frame.
 
 	if c.readRemaining > 0 {
-		if _, err := io.CopyN(ioutil.Discard, c.br, c.readRemaining); err != nil {
+		if _, err := io.CopyN(io.Discard, c.br, c.readRemaining); err != nil {
 			return noFrame, err
 		}
 	}
@@ -817,7 +832,9 @@ func (c *Conn) advanceFrame() (int, error) {
 	rsv2 := p[0]&rsv2Bit != 0
 	rsv3 := p[0]&rsv3Bit != 0
 	mask := p[1]&maskBit != 0
-	c.setReadRemaining(int64(p[1] & 0x7f))
+	if err := c.setReadRemaining(int64(p[1] & 0x7f)); err != nil {
+		return noFrame, err
+	}
 
 	c.readDecompress = false
 	if rsv1 {
@@ -922,7 +939,9 @@ func (c *Conn) advanceFrame() (int, error) {
 		}
 
 		if c.readLimit > 0 && c.readLength > c.readLimit {
-			c.WriteControl(CloseMessage, FormatCloseMessage(CloseMessageTooBig, ""), time.Now().Add(writeWait))
+			if err := c.WriteControl(CloseMessage, FormatCloseMessage(CloseMessageTooBig, ""), time.Now().Add(writeWait)); err != nil {
+				return noFrame, err
+			}
 			return noFrame, ErrReadLimit
 		}
 
@@ -934,7 +953,9 @@ func (c *Conn) advanceFrame() (int, error) {
 	var payload []byte
 	if c.readRemaining > 0 {
 		payload, err = c.read(int(c.readRemaining))
-		c.setReadRemaining(0)
+		if err := c.setReadRemaining(0); err != nil {
+			return noFrame, err
+		}
 		if err != nil {
 			return noFrame, err
 		}
@@ -981,7 +1002,9 @@ func (c *Conn) handleProtocolError(message string) error {
 	if len(data) > maxControlFramePayloadSize {
 		data = data[:maxControlFramePayloadSize]
 	}
-	c.WriteControl(CloseMessage, data, time.Now().Add(writeWait))
+	if err := c.WriteControl(CloseMessage, data, time.Now().Add(writeWait)); err != nil {
+		return err
+	}
 	return errors.New("websocket: " + message)
 }
 
@@ -998,7 +1021,9 @@ func (c *Conn) handleProtocolError(message string) error {
 func (c *Conn) NextReader() (messageType int, r io.Reader, err error) {
 	// Close previous reader, only relevant for decompression.
 	if c.reader != nil {
-		c.reader.Close()
+		if err := c.reader.Close(); err != nil {
+			log.Printf("websocket: discarding reader close error: %v", err)
+		}
 		c.reader = nil
 	}
 
@@ -1054,7 +1079,9 @@ func (r *messageReader) Read(b []byte) (int, error) {
 			}
 			rem := c.readRemaining
 			rem -= int64(n)
-			c.setReadRemaining(rem)
+			if err := c.setReadRemaining(rem); err != nil {
+				return 0, err
+			}
 			if c.readRemaining > 0 && c.readErr == io.EOF {
 				c.readErr = errUnexpectedEOF
 			}
@@ -1094,7 +1121,7 @@ func (c *Conn) ReadMessage() (messageType int, p []byte, err error) {
 	if err != nil {
 		return messageType, nil, err
 	}
-	p, err = ioutil.ReadAll(r)
+	p, err = io.ReadAll(r)
 	return messageType, p, err
 }
 
@@ -1136,7 +1163,9 @@ func (c *Conn) SetCloseHandler(h func(code int, text string) error) {
 	if h == nil {
 		h = func(code int, text string) error {
 			message := FormatCloseMessage(code, "")
-			c.WriteControl(CloseMessage, message, time.Now().Add(writeWait))
+			if err := c.WriteControl(CloseMessage, message, time.Now().Add(writeWait)); err != nil {
+				return err
+			}
 			return nil
 		}
 	}
@@ -1161,7 +1190,7 @@ func (c *Conn) SetPingHandler(h func(appData string) error) {
 			err := c.WriteControl(PongMessage, []byte(message), time.Now().Add(writeWait))
 			if err == ErrCloseSent {
 				return nil
-			} else if e, ok := err.(net.Error); ok && e.Temporary() {
+			} else if _, ok := err.(net.Error); ok {
 				return nil
 			}
 			return err
@@ -1189,8 +1218,16 @@ func (c *Conn) SetPongHandler(h func(appData string) error) {
 	c.handlePong = h
 }
 
+// NetConn returns the underlying connection that is wrapped by c.
+// Note that writing to or reading from this connection directly will corrupt the
+// WebSocket connection.
+func (c *Conn) NetConn() net.Conn {
+	return c.conn
+}
+
 // UnderlyingConn returns the internal net.Conn. This can be used to further
 // modifications to connection specific flags.
+// Deprecated: Use the NetConn method.
 func (c *Conn) UnderlyingConn() net.Conn {
 	return c.conn
 }

+ 4 - 0
vendor/github.com/gorilla/websocket/mask.go

@@ -9,6 +9,7 @@ package websocket
 
 import "unsafe"
 
+// #nosec G103 -- (CWE-242) Has been audited
 const wordSize = int(unsafe.Sizeof(uintptr(0)))
 
 func maskBytes(key [4]byte, pos int, b []byte) int {
@@ -22,6 +23,7 @@ func maskBytes(key [4]byte, pos int, b []byte) int {
 	}
 
 	// Mask one byte at a time to word boundary.
+	//#nosec G103 -- (CWE-242) Has been audited
 	if n := int(uintptr(unsafe.Pointer(&b[0]))) % wordSize; n != 0 {
 		n = wordSize - n
 		for i := range b[:n] {
@@ -36,11 +38,13 @@ func maskBytes(key [4]byte, pos int, b []byte) int {
 	for i := range k {
 		k[i] = key[(pos+i)&3]
 	}
+	//#nosec G103 -- (CWE-242) Has been audited
 	kw := *(*uintptr)(unsafe.Pointer(&k))
 
 	// Mask one word at a time.
 	n := (len(b) / wordSize) * wordSize
 	for i := 0; i < n; i += wordSize {
+		//#nosec G103 -- (CWE-242) Has been audited
 		*(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&b[0])) + uintptr(i))) ^= kw
 	}
 

+ 13 - 4
vendor/github.com/gorilla/websocket/proxy.go

@@ -8,10 +8,13 @@ import (
 	"bufio"
 	"encoding/base64"
 	"errors"
+	"log"
 	"net"
 	"net/http"
 	"net/url"
 	"strings"
+
+	"golang.org/x/net/proxy"
 )
 
 type netDialerFunc func(network, addr string) (net.Conn, error)
@@ -21,7 +24,7 @@ func (fn netDialerFunc) Dial(network, addr string) (net.Conn, error) {
 }
 
 func init() {
-	proxy_RegisterDialerType("http", func(proxyURL *url.URL, forwardDialer proxy_Dialer) (proxy_Dialer, error) {
+	proxy.RegisterDialerType("http", func(proxyURL *url.URL, forwardDialer proxy.Dialer) (proxy.Dialer, error) {
 		return &httpProxyDialer{proxyURL: proxyURL, forwardDial: forwardDialer.Dial}, nil
 	})
 }
@@ -55,7 +58,9 @@ func (hpd *httpProxyDialer) Dial(network string, addr string) (net.Conn, error)
 	}
 
 	if err := connectReq.Write(conn); err != nil {
-		conn.Close()
+		if err := conn.Close(); err != nil {
+			log.Printf("httpProxyDialer: failed to close connection: %v", err)
+		}
 		return nil, err
 	}
 
@@ -64,12 +69,16 @@ func (hpd *httpProxyDialer) Dial(network string, addr string) (net.Conn, error)
 	br := bufio.NewReader(conn)
 	resp, err := http.ReadResponse(br, connectReq)
 	if err != nil {
-		conn.Close()
+		if err := conn.Close(); err != nil {
+			log.Printf("httpProxyDialer: failed to close connection: %v", err)
+		}
 		return nil, err
 	}
 
 	if resp.StatusCode != 200 {
-		conn.Close()
+		if err := conn.Close(); err != nil {
+			log.Printf("httpProxyDialer: failed to close connection: %v", err)
+		}
 		f := strings.SplitN(resp.Status, " ", 2)
 		return nil, errors.New(f[1])
 	}

+ 33 - 9
vendor/github.com/gorilla/websocket/server.go

@@ -8,6 +8,7 @@ import (
 	"bufio"
 	"errors"
 	"io"
+	"log"
 	"net/http"
 	"net/url"
 	"strings"
@@ -154,8 +155,8 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade
 	}
 
 	challengeKey := r.Header.Get("Sec-Websocket-Key")
-	if challengeKey == "" {
-		return u.returnError(w, r, http.StatusBadRequest, "websocket: not a websocket handshake: 'Sec-WebSocket-Key' header is missing or blank")
+	if !isValidChallengeKey(challengeKey) {
+		return u.returnError(w, r, http.StatusBadRequest, "websocket: not a websocket handshake: 'Sec-WebSocket-Key' header must be Base64 encoded value of 16-byte in length")
 	}
 
 	subprotocol := u.selectSubprotocol(r, responseHeader)
@@ -183,7 +184,9 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade
 	}
 
 	if brw.Reader.Buffered() > 0 {
-		netConn.Close()
+		if err := netConn.Close(); err != nil {
+			log.Printf("websocket: failed to close network connection: %v", err)
+		}
 		return nil, errors.New("websocket: client sent data before handshake is complete")
 	}
 
@@ -248,17 +251,34 @@ func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeade
 	p = append(p, "\r\n"...)
 
 	// Clear deadlines set by HTTP server.
-	netConn.SetDeadline(time.Time{})
+	if err := netConn.SetDeadline(time.Time{}); err != nil {
+		if err := netConn.Close(); err != nil {
+			log.Printf("websocket: failed to close network connection: %v", err)
+		}
+		return nil, err
+	}
 
 	if u.HandshakeTimeout > 0 {
-		netConn.SetWriteDeadline(time.Now().Add(u.HandshakeTimeout))
+		if err := netConn.SetWriteDeadline(time.Now().Add(u.HandshakeTimeout)); err != nil {
+			if err := netConn.Close(); err != nil {
+				log.Printf("websocket: failed to close network connection: %v", err)
+			}
+			return nil, err
+		}
 	}
 	if _, err = netConn.Write(p); err != nil {
-		netConn.Close()
+		if err := netConn.Close(); err != nil {
+			log.Printf("websocket: failed to close network connection: %v", err)
+		}
 		return nil, err
 	}
 	if u.HandshakeTimeout > 0 {
-		netConn.SetWriteDeadline(time.Time{})
+		if err := netConn.SetWriteDeadline(time.Time{}); err != nil {
+			if err := netConn.Close(); err != nil {
+				log.Printf("websocket: failed to close network connection: %v", err)
+			}
+			return nil, err
+		}
 	}
 
 	return c, nil
@@ -356,8 +376,12 @@ func bufioWriterBuffer(originalWriter io.Writer, bw *bufio.Writer) []byte {
 	// bufio.Writer's underlying writer.
 	var wh writeHook
 	bw.Reset(&wh)
-	bw.WriteByte(0)
-	bw.Flush()
+	if err := bw.WriteByte(0); err != nil {
+		panic(err)
+	}
+	if err := bw.Flush(); err != nil {
+		log.Printf("websocket: bufioWriterBuffer: Flush: %v", err)
+	}
 
 	bw.Reset(originalWriter)
 

+ 0 - 3
vendor/github.com/gorilla/websocket/tls_handshake.go

@@ -1,6 +1,3 @@
-//go:build go1.17
-// +build go1.17
-
 package websocket
 
 import (

+ 0 - 21
vendor/github.com/gorilla/websocket/tls_handshake_116.go

@@ -1,21 +0,0 @@
-//go:build !go1.17
-// +build !go1.17
-
-package websocket
-
-import (
-	"context"
-	"crypto/tls"
-)
-
-func doHandshake(ctx context.Context, tlsConn *tls.Conn, cfg *tls.Config) error {
-	if err := tlsConn.Handshake(); err != nil {
-		return err
-	}
-	if !cfg.InsecureSkipVerify {
-		if err := tlsConn.VerifyHostname(cfg.ServerName); err != nil {
-			return err
-		}
-	}
-	return nil
-}

+ 17 - 2
vendor/github.com/gorilla/websocket/util.go

@@ -6,7 +6,7 @@ package websocket
 
 import (
 	"crypto/rand"
-	"crypto/sha1"
+	"crypto/sha1" //#nosec G505 -- (CWE-327) https://datatracker.ietf.org/doc/html/rfc6455#page-54
 	"encoding/base64"
 	"io"
 	"net/http"
@@ -17,7 +17,7 @@ import (
 var keyGUID = []byte("258EAFA5-E914-47DA-95CA-C5AB0DC85B11")
 
 func computeAcceptKey(challengeKey string) string {
-	h := sha1.New()
+	h := sha1.New() //#nosec G401 -- (CWE-326) https://datatracker.ietf.org/doc/html/rfc6455#page-54
 	h.Write([]byte(challengeKey))
 	h.Write(keyGUID)
 	return base64.StdEncoding.EncodeToString(h.Sum(nil))
@@ -281,3 +281,18 @@ headers:
 	}
 	return result
 }
+
+// isValidChallengeKey checks if the argument meets RFC6455 specification.
+func isValidChallengeKey(s string) bool {
+	// From RFC6455:
+	//
+	// A |Sec-WebSocket-Key| header field with a base64-encoded (see
+	// Section 4 of [RFC4648]) value that, when decoded, is 16 bytes in
+	// length.
+
+	if s == "" {
+		return false
+	}
+	decoded, err := base64.StdEncoding.DecodeString(s)
+	return err == nil && len(decoded) == 16
+}

+ 0 - 473
vendor/github.com/gorilla/websocket/x_net_proxy.go

@@ -1,473 +0,0 @@
-// Code generated by golang.org/x/tools/cmd/bundle. DO NOT EDIT.
-//go:generate bundle -o x_net_proxy.go golang.org/x/net/proxy
-
-// Package proxy provides support for a variety of protocols to proxy network
-// data.
-//
-
-package websocket
-
-import (
-	"errors"
-	"io"
-	"net"
-	"net/url"
-	"os"
-	"strconv"
-	"strings"
-	"sync"
-)
-
-type proxy_direct struct{}
-
-// Direct is a direct proxy: one that makes network connections directly.
-var proxy_Direct = proxy_direct{}
-
-func (proxy_direct) Dial(network, addr string) (net.Conn, error) {
-	return net.Dial(network, addr)
-}
-
-// A PerHost directs connections to a default Dialer unless the host name
-// requested matches one of a number of exceptions.
-type proxy_PerHost struct {
-	def, bypass proxy_Dialer
-
-	bypassNetworks []*net.IPNet
-	bypassIPs      []net.IP
-	bypassZones    []string
-	bypassHosts    []string
-}
-
-// NewPerHost returns a PerHost Dialer that directs connections to either
-// defaultDialer or bypass, depending on whether the connection matches one of
-// the configured rules.
-func proxy_NewPerHost(defaultDialer, bypass proxy_Dialer) *proxy_PerHost {
-	return &proxy_PerHost{
-		def:    defaultDialer,
-		bypass: bypass,
-	}
-}
-
-// Dial connects to the address addr on the given network through either
-// defaultDialer or bypass.
-func (p *proxy_PerHost) Dial(network, addr string) (c net.Conn, err error) {
-	host, _, err := net.SplitHostPort(addr)
-	if err != nil {
-		return nil, err
-	}
-
-	return p.dialerForRequest(host).Dial(network, addr)
-}
-
-func (p *proxy_PerHost) dialerForRequest(host string) proxy_Dialer {
-	if ip := net.ParseIP(host); ip != nil {
-		for _, net := range p.bypassNetworks {
-			if net.Contains(ip) {
-				return p.bypass
-			}
-		}
-		for _, bypassIP := range p.bypassIPs {
-			if bypassIP.Equal(ip) {
-				return p.bypass
-			}
-		}
-		return p.def
-	}
-
-	for _, zone := range p.bypassZones {
-		if strings.HasSuffix(host, zone) {
-			return p.bypass
-		}
-		if host == zone[1:] {
-			// For a zone ".example.com", we match "example.com"
-			// too.
-			return p.bypass
-		}
-	}
-	for _, bypassHost := range p.bypassHosts {
-		if bypassHost == host {
-			return p.bypass
-		}
-	}
-	return p.def
-}
-
-// AddFromString parses a string that contains comma-separated values
-// specifying hosts that should use the bypass proxy. Each value is either an
-// IP address, a CIDR range, a zone (*.example.com) or a host name
-// (localhost). A best effort is made to parse the string and errors are
-// ignored.
-func (p *proxy_PerHost) AddFromString(s string) {
-	hosts := strings.Split(s, ",")
-	for _, host := range hosts {
-		host = strings.TrimSpace(host)
-		if len(host) == 0 {
-			continue
-		}
-		if strings.Contains(host, "/") {
-			// We assume that it's a CIDR address like 127.0.0.0/8
-			if _, net, err := net.ParseCIDR(host); err == nil {
-				p.AddNetwork(net)
-			}
-			continue
-		}
-		if ip := net.ParseIP(host); ip != nil {
-			p.AddIP(ip)
-			continue
-		}
-		if strings.HasPrefix(host, "*.") {
-			p.AddZone(host[1:])
-			continue
-		}
-		p.AddHost(host)
-	}
-}
-
-// AddIP specifies an IP address that will use the bypass proxy. Note that
-// this will only take effect if a literal IP address is dialed. A connection
-// to a named host will never match an IP.
-func (p *proxy_PerHost) AddIP(ip net.IP) {
-	p.bypassIPs = append(p.bypassIPs, ip)
-}
-
-// AddNetwork specifies an IP range that will use the bypass proxy. Note that
-// this will only take effect if a literal IP address is dialed. A connection
-// to a named host will never match.
-func (p *proxy_PerHost) AddNetwork(net *net.IPNet) {
-	p.bypassNetworks = append(p.bypassNetworks, net)
-}
-
-// AddZone specifies a DNS suffix that will use the bypass proxy. A zone of
-// "example.com" matches "example.com" and all of its subdomains.
-func (p *proxy_PerHost) AddZone(zone string) {
-	if strings.HasSuffix(zone, ".") {
-		zone = zone[:len(zone)-1]
-	}
-	if !strings.HasPrefix(zone, ".") {
-		zone = "." + zone
-	}
-	p.bypassZones = append(p.bypassZones, zone)
-}
-
-// AddHost specifies a host name that will use the bypass proxy.
-func (p *proxy_PerHost) AddHost(host string) {
-	if strings.HasSuffix(host, ".") {
-		host = host[:len(host)-1]
-	}
-	p.bypassHosts = append(p.bypassHosts, host)
-}
-
-// A Dialer is a means to establish a connection.
-type proxy_Dialer interface {
-	// Dial connects to the given address via the proxy.
-	Dial(network, addr string) (c net.Conn, err error)
-}
-
-// Auth contains authentication parameters that specific Dialers may require.
-type proxy_Auth struct {
-	User, Password string
-}
-
-// FromEnvironment returns the dialer specified by the proxy related variables in
-// the environment.
-func proxy_FromEnvironment() proxy_Dialer {
-	allProxy := proxy_allProxyEnv.Get()
-	if len(allProxy) == 0 {
-		return proxy_Direct
-	}
-
-	proxyURL, err := url.Parse(allProxy)
-	if err != nil {
-		return proxy_Direct
-	}
-	proxy, err := proxy_FromURL(proxyURL, proxy_Direct)
-	if err != nil {
-		return proxy_Direct
-	}
-
-	noProxy := proxy_noProxyEnv.Get()
-	if len(noProxy) == 0 {
-		return proxy
-	}
-
-	perHost := proxy_NewPerHost(proxy, proxy_Direct)
-	perHost.AddFromString(noProxy)
-	return perHost
-}
-
-// proxySchemes is a map from URL schemes to a function that creates a Dialer
-// from a URL with such a scheme.
-var proxy_proxySchemes map[string]func(*url.URL, proxy_Dialer) (proxy_Dialer, error)
-
-// RegisterDialerType takes a URL scheme and a function to generate Dialers from
-// a URL with that scheme and a forwarding Dialer. Registered schemes are used
-// by FromURL.
-func proxy_RegisterDialerType(scheme string, f func(*url.URL, proxy_Dialer) (proxy_Dialer, error)) {
-	if proxy_proxySchemes == nil {
-		proxy_proxySchemes = make(map[string]func(*url.URL, proxy_Dialer) (proxy_Dialer, error))
-	}
-	proxy_proxySchemes[scheme] = f
-}
-
-// FromURL returns a Dialer given a URL specification and an underlying
-// Dialer for it to make network requests.
-func proxy_FromURL(u *url.URL, forward proxy_Dialer) (proxy_Dialer, error) {
-	var auth *proxy_Auth
-	if u.User != nil {
-		auth = new(proxy_Auth)
-		auth.User = u.User.Username()
-		if p, ok := u.User.Password(); ok {
-			auth.Password = p
-		}
-	}
-
-	switch u.Scheme {
-	case "socks5":
-		return proxy_SOCKS5("tcp", u.Host, auth, forward)
-	}
-
-	// If the scheme doesn't match any of the built-in schemes, see if it
-	// was registered by another package.
-	if proxy_proxySchemes != nil {
-		if f, ok := proxy_proxySchemes[u.Scheme]; ok {
-			return f(u, forward)
-		}
-	}
-
-	return nil, errors.New("proxy: unknown scheme: " + u.Scheme)
-}
-
-var (
-	proxy_allProxyEnv = &proxy_envOnce{
-		names: []string{"ALL_PROXY", "all_proxy"},
-	}
-	proxy_noProxyEnv = &proxy_envOnce{
-		names: []string{"NO_PROXY", "no_proxy"},
-	}
-)
-
-// envOnce looks up an environment variable (optionally by multiple
-// names) once. It mitigates expensive lookups on some platforms
-// (e.g. Windows).
-// (Borrowed from net/http/transport.go)
-type proxy_envOnce struct {
-	names []string
-	once  sync.Once
-	val   string
-}
-
-func (e *proxy_envOnce) Get() string {
-	e.once.Do(e.init)
-	return e.val
-}
-
-func (e *proxy_envOnce) init() {
-	for _, n := range e.names {
-		e.val = os.Getenv(n)
-		if e.val != "" {
-			return
-		}
-	}
-}
-
-// SOCKS5 returns a Dialer that makes SOCKSv5 connections to the given address
-// with an optional username and password. See RFC 1928 and RFC 1929.
-func proxy_SOCKS5(network, addr string, auth *proxy_Auth, forward proxy_Dialer) (proxy_Dialer, error) {
-	s := &proxy_socks5{
-		network: network,
-		addr:    addr,
-		forward: forward,
-	}
-	if auth != nil {
-		s.user = auth.User
-		s.password = auth.Password
-	}
-
-	return s, nil
-}
-
-type proxy_socks5 struct {
-	user, password string
-	network, addr  string
-	forward        proxy_Dialer
-}
-
-const proxy_socks5Version = 5
-
-const (
-	proxy_socks5AuthNone     = 0
-	proxy_socks5AuthPassword = 2
-)
-
-const proxy_socks5Connect = 1
-
-const (
-	proxy_socks5IP4    = 1
-	proxy_socks5Domain = 3
-	proxy_socks5IP6    = 4
-)
-
-var proxy_socks5Errors = []string{
-	"",
-	"general failure",
-	"connection forbidden",
-	"network unreachable",
-	"host unreachable",
-	"connection refused",
-	"TTL expired",
-	"command not supported",
-	"address type not supported",
-}
-
-// Dial connects to the address addr on the given network via the SOCKS5 proxy.
-func (s *proxy_socks5) Dial(network, addr string) (net.Conn, error) {
-	switch network {
-	case "tcp", "tcp6", "tcp4":
-	default:
-		return nil, errors.New("proxy: no support for SOCKS5 proxy connections of type " + network)
-	}
-
-	conn, err := s.forward.Dial(s.network, s.addr)
-	if err != nil {
-		return nil, err
-	}
-	if err := s.connect(conn, addr); err != nil {
-		conn.Close()
-		return nil, err
-	}
-	return conn, nil
-}
-
-// connect takes an existing connection to a socks5 proxy server,
-// and commands the server to extend that connection to target,
-// which must be a canonical address with a host and port.
-func (s *proxy_socks5) connect(conn net.Conn, target string) error {
-	host, portStr, err := net.SplitHostPort(target)
-	if err != nil {
-		return err
-	}
-
-	port, err := strconv.Atoi(portStr)
-	if err != nil {
-		return errors.New("proxy: failed to parse port number: " + portStr)
-	}
-	if port < 1 || port > 0xffff {
-		return errors.New("proxy: port number out of range: " + portStr)
-	}
-
-	// the size here is just an estimate
-	buf := make([]byte, 0, 6+len(host))
-
-	buf = append(buf, proxy_socks5Version)
-	if len(s.user) > 0 && len(s.user) < 256 && len(s.password) < 256 {
-		buf = append(buf, 2 /* num auth methods */, proxy_socks5AuthNone, proxy_socks5AuthPassword)
-	} else {
-		buf = append(buf, 1 /* num auth methods */, proxy_socks5AuthNone)
-	}
-
-	if _, err := conn.Write(buf); err != nil {
-		return errors.New("proxy: failed to write greeting to SOCKS5 proxy at " + s.addr + ": " + err.Error())
-	}
-
-	if _, err := io.ReadFull(conn, buf[:2]); err != nil {
-		return errors.New("proxy: failed to read greeting from SOCKS5 proxy at " + s.addr + ": " + err.Error())
-	}
-	if buf[0] != 5 {
-		return errors.New("proxy: SOCKS5 proxy at " + s.addr + " has unexpected version " + strconv.Itoa(int(buf[0])))
-	}
-	if buf[1] == 0xff {
-		return errors.New("proxy: SOCKS5 proxy at " + s.addr + " requires authentication")
-	}
-
-	// See RFC 1929
-	if buf[1] == proxy_socks5AuthPassword {
-		buf = buf[:0]
-		buf = append(buf, 1 /* password protocol version */)
-		buf = append(buf, uint8(len(s.user)))
-		buf = append(buf, s.user...)
-		buf = append(buf, uint8(len(s.password)))
-		buf = append(buf, s.password...)
-
-		if _, err := conn.Write(buf); err != nil {
-			return errors.New("proxy: failed to write authentication request to SOCKS5 proxy at " + s.addr + ": " + err.Error())
-		}
-
-		if _, err := io.ReadFull(conn, buf[:2]); err != nil {
-			return errors.New("proxy: failed to read authentication reply from SOCKS5 proxy at " + s.addr + ": " + err.Error())
-		}
-
-		if buf[1] != 0 {
-			return errors.New("proxy: SOCKS5 proxy at " + s.addr + " rejected username/password")
-		}
-	}
-
-	buf = buf[:0]
-	buf = append(buf, proxy_socks5Version, proxy_socks5Connect, 0 /* reserved */)
-
-	if ip := net.ParseIP(host); ip != nil {
-		if ip4 := ip.To4(); ip4 != nil {
-			buf = append(buf, proxy_socks5IP4)
-			ip = ip4
-		} else {
-			buf = append(buf, proxy_socks5IP6)
-		}
-		buf = append(buf, ip...)
-	} else {
-		if len(host) > 255 {
-			return errors.New("proxy: destination host name too long: " + host)
-		}
-		buf = append(buf, proxy_socks5Domain)
-		buf = append(buf, byte(len(host)))
-		buf = append(buf, host...)
-	}
-	buf = append(buf, byte(port>>8), byte(port))
-
-	if _, err := conn.Write(buf); err != nil {
-		return errors.New("proxy: failed to write connect request to SOCKS5 proxy at " + s.addr + ": " + err.Error())
-	}
-
-	if _, err := io.ReadFull(conn, buf[:4]); err != nil {
-		return errors.New("proxy: failed to read connect reply from SOCKS5 proxy at " + s.addr + ": " + err.Error())
-	}
-
-	failure := "unknown error"
-	if int(buf[1]) < len(proxy_socks5Errors) {
-		failure = proxy_socks5Errors[buf[1]]
-	}
-
-	if len(failure) > 0 {
-		return errors.New("proxy: SOCKS5 proxy at " + s.addr + " failed to connect: " + failure)
-	}
-
-	bytesToDiscard := 0
-	switch buf[3] {
-	case proxy_socks5IP4:
-		bytesToDiscard = net.IPv4len
-	case proxy_socks5IP6:
-		bytesToDiscard = net.IPv6len
-	case proxy_socks5Domain:
-		_, err := io.ReadFull(conn, buf[:1])
-		if err != nil {
-			return errors.New("proxy: failed to read domain length from SOCKS5 proxy at " + s.addr + ": " + err.Error())
-		}
-		bytesToDiscard = int(buf[0])
-	default:
-		return errors.New("proxy: got unknown address type " + strconv.Itoa(int(buf[3])) + " from SOCKS5 proxy at " + s.addr)
-	}
-
-	if cap(buf) < bytesToDiscard {
-		buf = make([]byte, bytesToDiscard)
-	} else {
-		buf = buf[:bytesToDiscard]
-	}
-	if _, err := io.ReadFull(conn, buf); err != nil {
-		return errors.New("proxy: failed to read address from SOCKS5 proxy at " + s.addr + ": " + err.Error())
-	}
-
-	// Also need to discard the port number
-	if _, err := io.ReadFull(conn, buf[:2]); err != nil {
-		return errors.New("proxy: failed to read port from SOCKS5 proxy at " + s.addr + ": " + err.Error())
-	}
-
-	return nil
-}

+ 0 - 354
vendor/github.com/hashicorp/go-version/LICENSE

@@ -1,354 +0,0 @@
-Mozilla Public License, version 2.0
-
-1. Definitions
-
-1.1. “Contributor”
-
-     means each individual or legal entity that creates, contributes to the
-     creation of, or owns Covered Software.
-
-1.2. “Contributor Version”
-
-     means the combination of the Contributions of others (if any) used by a
-     Contributor and that particular Contributor’s Contribution.
-
-1.3. “Contribution”
-
-     means Covered Software of a particular Contributor.
-
-1.4. “Covered Software”
-
-     means Source Code Form to which the initial Contributor has attached the
-     notice in Exhibit A, the Executable Form of such Source Code Form, and
-     Modifications of such Source Code Form, in each case including portions
-     thereof.
-
-1.5. “Incompatible With Secondary Licenses”
-     means
-
-     a. that the initial Contributor has attached the notice described in
-        Exhibit B to the Covered Software; or
-
-     b. that the Covered Software was made available under the terms of version
-        1.1 or earlier of the License, but not also under the terms of a
-        Secondary License.
-
-1.6. “Executable Form”
-
-     means any form of the work other than Source Code Form.
-
-1.7. “Larger Work”
-
-     means a work that combines Covered Software with other material, in a separate
-     file or files, that is not Covered Software.
-
-1.8. “License”
-
-     means this document.
-
-1.9. “Licensable”
-
-     means having the right to grant, to the maximum extent possible, whether at the
-     time of the initial grant or subsequently, any and all of the rights conveyed by
-     this License.
-
-1.10. “Modifications”
-
-     means any of the following:
-
-     a. any file in Source Code Form that results from an addition to, deletion
-        from, or modification of the contents of Covered Software; or
-
-     b. any new file in Source Code Form that contains any Covered Software.
-
-1.11. “Patent Claims” of a Contributor
-
-      means any patent claim(s), including without limitation, method, process,
-      and apparatus claims, in any patent Licensable by such Contributor that
-      would be infringed, but for the grant of the License, by the making,
-      using, selling, offering for sale, having made, import, or transfer of
-      either its Contributions or its Contributor Version.
-
-1.12. “Secondary License”
-
-      means either the GNU General Public License, Version 2.0, the GNU Lesser
-      General Public License, Version 2.1, the GNU Affero General Public
-      License, Version 3.0, or any later versions of those licenses.
-
-1.13. “Source Code Form”
-
-      means the form of the work preferred for making modifications.
-
-1.14. “You” (or “Your”)
-
-      means an individual or a legal entity exercising rights under this
-      License. For legal entities, “You” includes any entity that controls, is
-      controlled by, or is under common control with You. For purposes of this
-      definition, “control” means (a) the power, direct or indirect, to cause
-      the direction or management of such entity, whether by contract or
-      otherwise, or (b) ownership of more than fifty percent (50%) of the
-      outstanding shares or beneficial ownership of such entity.
-
-
-2. License Grants and Conditions
-
-2.1. Grants
-
-     Each Contributor hereby grants You a world-wide, royalty-free,
-     non-exclusive license:
-
-     a. under intellectual property rights (other than patent or trademark)
-        Licensable by such Contributor to use, reproduce, make available,
-        modify, display, perform, distribute, and otherwise exploit its
-        Contributions, either on an unmodified basis, with Modifications, or as
-        part of a Larger Work; and
-
-     b. under Patent Claims of such Contributor to make, use, sell, offer for
-        sale, have made, import, and otherwise transfer either its Contributions
-        or its Contributor Version.
-
-2.2. Effective Date
-
-     The licenses granted in Section 2.1 with respect to any Contribution become
-     effective for each Contribution on the date the Contributor first distributes
-     such Contribution.
-
-2.3. Limitations on Grant Scope
-
-     The licenses granted in this Section 2 are the only rights granted under this
-     License. No additional rights or licenses will be implied from the distribution
-     or licensing of Covered Software under this License. Notwithstanding Section
-     2.1(b) above, no patent license is granted by a Contributor:
-
-     a. for any code that a Contributor has removed from Covered Software; or
-
-     b. for infringements caused by: (i) Your and any other third party’s
-        modifications of Covered Software, or (ii) the combination of its
-        Contributions with other software (except as part of its Contributor
-        Version); or
-
-     c. under Patent Claims infringed by Covered Software in the absence of its
-        Contributions.
-
-     This License does not grant any rights in the trademarks, service marks, or
-     logos of any Contributor (except as may be necessary to comply with the
-     notice requirements in Section 3.4).
-
-2.4. Subsequent Licenses
-
-     No Contributor makes additional grants as a result of Your choice to
-     distribute the Covered Software under a subsequent version of this License
-     (see Section 10.2) or under the terms of a Secondary License (if permitted
-     under the terms of Section 3.3).
-
-2.5. Representation
-
-     Each Contributor represents that the Contributor believes its Contributions
-     are its original creation(s) or it has sufficient rights to grant the
-     rights to its Contributions conveyed by this License.
-
-2.6. Fair Use
-
-     This License is not intended to limit any rights You have under applicable
-     copyright doctrines of fair use, fair dealing, or other equivalents.
-
-2.7. Conditions
-
-     Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted in
-     Section 2.1.
-
-
-3. Responsibilities
-
-3.1. Distribution of Source Form
-
-     All distribution of Covered Software in Source Code Form, including any
-     Modifications that You create or to which You contribute, must be under the
-     terms of this License. You must inform recipients that the Source Code Form
-     of the Covered Software is governed by the terms of this License, and how
-     they can obtain a copy of this License. You may not attempt to alter or
-     restrict the recipients’ rights in the Source Code Form.
-
-3.2. Distribution of Executable Form
-
-     If You distribute Covered Software in Executable Form then:
-
-     a. such Covered Software must also be made available in Source Code Form,
-        as described in Section 3.1, and You must inform recipients of the
-        Executable Form how they can obtain a copy of such Source Code Form by
-        reasonable means in a timely manner, at a charge no more than the cost
-        of distribution to the recipient; and
-
-     b. You may distribute such Executable Form under the terms of this License,
-        or sublicense it under different terms, provided that the license for
-        the Executable Form does not attempt to limit or alter the recipients’
-        rights in the Source Code Form under this License.
-
-3.3. Distribution of a Larger Work
-
-     You may create and distribute a Larger Work under terms of Your choice,
-     provided that You also comply with the requirements of this License for the
-     Covered Software. If the Larger Work is a combination of Covered Software
-     with a work governed by one or more Secondary Licenses, and the Covered
-     Software is not Incompatible With Secondary Licenses, this License permits
-     You to additionally distribute such Covered Software under the terms of
-     such Secondary License(s), so that the recipient of the Larger Work may, at
-     their option, further distribute the Covered Software under the terms of
-     either this License or such Secondary License(s).
-
-3.4. Notices
-
-     You may not remove or alter the substance of any license notices (including
-     copyright notices, patent notices, disclaimers of warranty, or limitations
-     of liability) contained within the Source Code Form of the Covered
-     Software, except that You may alter any license notices to the extent
-     required to remedy known factual inaccuracies.
-
-3.5. Application of Additional Terms
-
-     You may choose to offer, and to charge a fee for, warranty, support,
-     indemnity or liability obligations to one or more recipients of Covered
-     Software. However, You may do so only on Your own behalf, and not on behalf
-     of any Contributor. You must make it absolutely clear that any such
-     warranty, support, indemnity, or liability obligation is offered by You
-     alone, and You hereby agree to indemnify every Contributor for any
-     liability incurred by such Contributor as a result of warranty, support,
-     indemnity or liability terms You offer. You may include additional
-     disclaimers of warranty and limitations of liability specific to any
-     jurisdiction.
-
-4. Inability to Comply Due to Statute or Regulation
-
-   If it is impossible for You to comply with any of the terms of this License
-   with respect to some or all of the Covered Software due to statute, judicial
-   order, or regulation then You must: (a) comply with the terms of this License
-   to the maximum extent possible; and (b) describe the limitations and the code
-   they affect. Such description must be placed in a text file included with all
-   distributions of the Covered Software under this License. Except to the
-   extent prohibited by statute or regulation, such description must be
-   sufficiently detailed for a recipient of ordinary skill to be able to
-   understand it.
-
-5. Termination
-
-5.1. The rights granted under this License will terminate automatically if You
-     fail to comply with any of its terms. However, if You become compliant,
-     then the rights granted under this License from a particular Contributor
-     are reinstated (a) provisionally, unless and until such Contributor
-     explicitly and finally terminates Your grants, and (b) on an ongoing basis,
-     if such Contributor fails to notify You of the non-compliance by some
-     reasonable means prior to 60 days after You have come back into compliance.
-     Moreover, Your grants from a particular Contributor are reinstated on an
-     ongoing basis if such Contributor notifies You of the non-compliance by
-     some reasonable means, this is the first time You have received notice of
-     non-compliance with this License from such Contributor, and You become
-     compliant prior to 30 days after Your receipt of the notice.
-
-5.2. If You initiate litigation against any entity by asserting a patent
-     infringement claim (excluding declaratory judgment actions, counter-claims,
-     and cross-claims) alleging that a Contributor Version directly or
-     indirectly infringes any patent, then the rights granted to You by any and
-     all Contributors for the Covered Software under Section 2.1 of this License
-     shall terminate.
-
-5.3. In the event of termination under Sections 5.1 or 5.2 above, all end user
-     license agreements (excluding distributors and resellers) which have been
-     validly granted by You or Your distributors under this License prior to
-     termination shall survive termination.
-
-6. Disclaimer of Warranty
-
-   Covered Software is provided under this License on an “as is” basis, without
-   warranty of any kind, either expressed, implied, or statutory, including,
-   without limitation, warranties that the Covered Software is free of defects,
-   merchantable, fit for a particular purpose or non-infringing. The entire
-   risk as to the quality and performance of the Covered Software is with You.
-   Should any Covered Software prove defective in any respect, You (not any
-   Contributor) assume the cost of any necessary servicing, repair, or
-   correction. This disclaimer of warranty constitutes an essential part of this
-   License. No use of  any Covered Software is authorized under this License
-   except under this disclaimer.
-
-7. Limitation of Liability
-
-   Under no circumstances and under no legal theory, whether tort (including
-   negligence), contract, or otherwise, shall any Contributor, or anyone who
-   distributes Covered Software as permitted above, be liable to You for any
-   direct, indirect, special, incidental, or consequential damages of any
-   character including, without limitation, damages for lost profits, loss of
-   goodwill, work stoppage, computer failure or malfunction, or any and all
-   other commercial damages or losses, even if such party shall have been
-   informed of the possibility of such damages. This limitation of liability
-   shall not apply to liability for death or personal injury resulting from such
-   party’s negligence to the extent applicable law prohibits such limitation.
-   Some jurisdictions do not allow the exclusion or limitation of incidental or
-   consequential damages, so this exclusion and limitation may not apply to You.
-
-8. Litigation
-
-   Any litigation relating to this License may be brought only in the courts of
-   a jurisdiction where the defendant maintains its principal place of business
-   and such litigation shall be governed by laws of that jurisdiction, without
-   reference to its conflict-of-law provisions. Nothing in this Section shall
-   prevent a party’s ability to bring cross-claims or counter-claims.
-
-9. Miscellaneous
-
-   This License represents the complete agreement concerning the subject matter
-   hereof. If any provision of this License is held to be unenforceable, such
-   provision shall be reformed only to the extent necessary to make it
-   enforceable. Any law or regulation which provides that the language of a
-   contract shall be construed against the drafter shall not be used to construe
-   this License against a Contributor.
-
-
-10. Versions of the License
-
-10.1. New Versions
-
-      Mozilla Foundation is the license steward. Except as provided in Section
-      10.3, no one other than the license steward has the right to modify or
-      publish new versions of this License. Each version will be given a
-      distinguishing version number.
-
-10.2. Effect of New Versions
-
-      You may distribute the Covered Software under the terms of the version of
-      the License under which You originally received the Covered Software, or
-      under the terms of any subsequent version published by the license
-      steward.
-
-10.3. Modified Versions
-
-      If you create software not governed by this License, and you want to
-      create a new license for such software, you may create and use a modified
-      version of this License if you rename the license and remove any
-      references to the name of the license steward (except to note that such
-      modified license differs from this License).
-
-10.4. Distributing Source Code Form that is Incompatible With Secondary Licenses
-      If You choose to distribute Source Code Form that is Incompatible With
-      Secondary Licenses under the terms of this version of the License, the
-      notice described in Exhibit B of this License must be attached.
-
-Exhibit A - Source Code Form License Notice
-
-      This Source Code Form is subject to the
-      terms of the Mozilla Public License, v.
-      2.0. If a copy of the MPL was not
-      distributed with this file, You can
-      obtain one at
-      http://mozilla.org/MPL/2.0/.
-
-If it is not possible or desirable to put the notice in a particular file, then
-You may include the notice in a location (such as a LICENSE file in a relevant
-directory) where a recipient would be likely to look for such a notice.
-
-You may add additional accurate notices of copyright ownership.
-
-Exhibit B - “Incompatible With Secondary Licenses” Notice
-
-      This Source Code Form is “Incompatible
-      With Secondary Licenses”, as defined by
-      the Mozilla Public License, v. 2.0.
-

+ 0 - 66
vendor/github.com/hashicorp/go-version/README.md

@@ -1,66 +0,0 @@
-# Versioning Library for Go
-[![Build Status](https://circleci.com/gh/hashicorp/go-version/tree/master.svg?style=svg)](https://circleci.com/gh/hashicorp/go-version/tree/master)
-[![GoDoc](https://godoc.org/github.com/hashicorp/go-version?status.svg)](https://godoc.org/github.com/hashicorp/go-version)
-
-go-version is a library for parsing versions and version constraints,
-and verifying versions against a set of constraints. go-version
-can sort a collection of versions properly, handles prerelease/beta
-versions, can increment versions, etc.
-
-Versions used with go-version must follow [SemVer](http://semver.org/).
-
-## Installation and Usage
-
-Package documentation can be found on
-[GoDoc](http://godoc.org/github.com/hashicorp/go-version).
-
-Installation can be done with a normal `go get`:
-
-```
-$ go get github.com/hashicorp/go-version
-```
-
-#### Version Parsing and Comparison
-
-```go
-v1, err := version.NewVersion("1.2")
-v2, err := version.NewVersion("1.5+metadata")
-
-// Comparison example. There is also GreaterThan, Equal, and just
-// a simple Compare that returns an int allowing easy >=, <=, etc.
-if v1.LessThan(v2) {
-    fmt.Printf("%s is less than %s", v1, v2)
-}
-```
-
-#### Version Constraints
-
-```go
-v1, err := version.NewVersion("1.2")
-
-// Constraints example.
-constraints, err := version.NewConstraint(">= 1.0, < 1.4")
-if constraints.Check(v1) {
-	fmt.Printf("%s satisfies constraints %s", v1, constraints)
-}
-```
-
-#### Version Sorting
-
-```go
-versionsRaw := []string{"1.1", "0.7.1", "1.4-beta", "1.4", "2"}
-versions := make([]*version.Version, len(versionsRaw))
-for i, raw := range versionsRaw {
-    v, _ := version.NewVersion(raw)
-    versions[i] = v
-}
-
-// After this, the versions are properly sorted
-sort.Sort(version.Collection(versions))
-```
-
-## Issues and Contributing
-
-If you find an issue with this library, please report an issue. If you'd
-like, we welcome any contributions. Fork this library and submit a pull
-request.

+ 0 - 204
vendor/github.com/hashicorp/go-version/constraint.go

@@ -1,204 +0,0 @@
-package version
-
-import (
-	"fmt"
-	"reflect"
-	"regexp"
-	"strings"
-)
-
-// Constraint represents a single constraint for a version, such as
-// ">= 1.0".
-type Constraint struct {
-	f        constraintFunc
-	check    *Version
-	original string
-}
-
-// Constraints is a slice of constraints. We make a custom type so that
-// we can add methods to it.
-type Constraints []*Constraint
-
-type constraintFunc func(v, c *Version) bool
-
-var constraintOperators map[string]constraintFunc
-
-var constraintRegexp *regexp.Regexp
-
-func init() {
-	constraintOperators = map[string]constraintFunc{
-		"":   constraintEqual,
-		"=":  constraintEqual,
-		"!=": constraintNotEqual,
-		">":  constraintGreaterThan,
-		"<":  constraintLessThan,
-		">=": constraintGreaterThanEqual,
-		"<=": constraintLessThanEqual,
-		"~>": constraintPessimistic,
-	}
-
-	ops := make([]string, 0, len(constraintOperators))
-	for k := range constraintOperators {
-		ops = append(ops, regexp.QuoteMeta(k))
-	}
-
-	constraintRegexp = regexp.MustCompile(fmt.Sprintf(
-		`^\s*(%s)\s*(%s)\s*$`,
-		strings.Join(ops, "|"),
-		VersionRegexpRaw))
-}
-
-// NewConstraint will parse one or more constraints from the given
-// constraint string. The string must be a comma-separated list of
-// constraints.
-func NewConstraint(v string) (Constraints, error) {
-	vs := strings.Split(v, ",")
-	result := make([]*Constraint, len(vs))
-	for i, single := range vs {
-		c, err := parseSingle(single)
-		if err != nil {
-			return nil, err
-		}
-
-		result[i] = c
-	}
-
-	return Constraints(result), nil
-}
-
-// Check tests if a version satisfies all the constraints.
-func (cs Constraints) Check(v *Version) bool {
-	for _, c := range cs {
-		if !c.Check(v) {
-			return false
-		}
-	}
-
-	return true
-}
-
-// Returns the string format of the constraints
-func (cs Constraints) String() string {
-	csStr := make([]string, len(cs))
-	for i, c := range cs {
-		csStr[i] = c.String()
-	}
-
-	return strings.Join(csStr, ",")
-}
-
-// Check tests if a constraint is validated by the given version.
-func (c *Constraint) Check(v *Version) bool {
-	return c.f(v, c.check)
-}
-
-func (c *Constraint) String() string {
-	return c.original
-}
-
-func parseSingle(v string) (*Constraint, error) {
-	matches := constraintRegexp.FindStringSubmatch(v)
-	if matches == nil {
-		return nil, fmt.Errorf("Malformed constraint: %s", v)
-	}
-
-	check, err := NewVersion(matches[2])
-	if err != nil {
-		return nil, err
-	}
-
-	return &Constraint{
-		f:        constraintOperators[matches[1]],
-		check:    check,
-		original: v,
-	}, nil
-}
-
-func prereleaseCheck(v, c *Version) bool {
-	switch vPre, cPre := v.Prerelease() != "", c.Prerelease() != ""; {
-	case cPre && vPre:
-		// A constraint with a pre-release can only match a pre-release version
-		// with the same base segments.
-		return reflect.DeepEqual(c.Segments64(), v.Segments64())
-
-	case !cPre && vPre:
-		// A constraint without a pre-release can only match a version without a
-		// pre-release.
-		return false
-
-	case cPre && !vPre:
-		// OK, except with the pessimistic operator
-	case !cPre && !vPre:
-		// OK
-	}
-	return true
-}
-
-//-------------------------------------------------------------------
-// Constraint functions
-//-------------------------------------------------------------------
-
-func constraintEqual(v, c *Version) bool {
-	return v.Equal(c)
-}
-
-func constraintNotEqual(v, c *Version) bool {
-	return !v.Equal(c)
-}
-
-func constraintGreaterThan(v, c *Version) bool {
-	return prereleaseCheck(v, c) && v.Compare(c) == 1
-}
-
-func constraintLessThan(v, c *Version) bool {
-	return prereleaseCheck(v, c) && v.Compare(c) == -1
-}
-
-func constraintGreaterThanEqual(v, c *Version) bool {
-	return prereleaseCheck(v, c) && v.Compare(c) >= 0
-}
-
-func constraintLessThanEqual(v, c *Version) bool {
-	return prereleaseCheck(v, c) && v.Compare(c) <= 0
-}
-
-func constraintPessimistic(v, c *Version) bool {
-	// Using a pessimistic constraint with a pre-release, restricts versions to pre-releases
-	if !prereleaseCheck(v, c) || (c.Prerelease() != "" && v.Prerelease() == "") {
-		return false
-	}
-
-	// If the version being checked is naturally less than the constraint, then there
-	// is no way for the version to be valid against the constraint
-	if v.LessThan(c) {
-		return false
-	}
-	// We'll use this more than once, so grab the length now so it's a little cleaner
-	// to write the later checks
-	cs := len(c.segments)
-
-	// If the version being checked has less specificity than the constraint, then there
-	// is no way for the version to be valid against the constraint
-	if cs > len(v.segments) {
-		return false
-	}
-
-	// Check the segments in the constraint against those in the version. If the version
-	// being checked, at any point, does not have the same values in each index of the
-	// constraints segments, then it cannot be valid against the constraint.
-	for i := 0; i < c.si-1; i++ {
-		if v.segments[i] != c.segments[i] {
-			return false
-		}
-	}
-
-	// Check the last part of the segment in the constraint. If the version segment at
-	// this index is less than the constraints segment at this index, then it cannot
-	// be valid against the constraint
-	if c.segments[cs-1] > v.segments[cs-1] {
-		return false
-	}
-
-	// If nothing has rejected the version by now, it's valid
-	return true
-}

+ 0 - 384
vendor/github.com/hashicorp/go-version/version.go

@@ -1,384 +0,0 @@
-package version
-
-import (
-	"bytes"
-	"fmt"
-	"reflect"
-	"regexp"
-	"strconv"
-	"strings"
-)
-
-// The compiled regular expression used to test the validity of a version.
-var (
-	versionRegexp *regexp.Regexp
-	semverRegexp  *regexp.Regexp
-)
-
-// The raw regular expression string used for testing the validity
-// of a version.
-const (
-	VersionRegexpRaw string = `v?([0-9]+(\.[0-9]+)*?)` +
-		`(-([0-9]+[0-9A-Za-z\-~]*(\.[0-9A-Za-z\-~]+)*)|(-?([A-Za-z\-~]+[0-9A-Za-z\-~]*(\.[0-9A-Za-z\-~]+)*)))?` +
-		`(\+([0-9A-Za-z\-~]+(\.[0-9A-Za-z\-~]+)*))?` +
-		`?`
-
-	// SemverRegexpRaw requires a separator between version and prerelease
-	SemverRegexpRaw string = `v?([0-9]+(\.[0-9]+)*?)` +
-		`(-([0-9]+[0-9A-Za-z\-~]*(\.[0-9A-Za-z\-~]+)*)|(-([A-Za-z\-~]+[0-9A-Za-z\-~]*(\.[0-9A-Za-z\-~]+)*)))?` +
-		`(\+([0-9A-Za-z\-~]+(\.[0-9A-Za-z\-~]+)*))?` +
-		`?`
-)
-
-// Version represents a single version.
-type Version struct {
-	metadata string
-	pre      string
-	segments []int64
-	si       int
-	original string
-}
-
-func init() {
-	versionRegexp = regexp.MustCompile("^" + VersionRegexpRaw + "$")
-	semverRegexp = regexp.MustCompile("^" + SemverRegexpRaw + "$")
-}
-
-// NewVersion parses the given version and returns a new
-// Version.
-func NewVersion(v string) (*Version, error) {
-	return newVersion(v, versionRegexp)
-}
-
-// NewSemver parses the given version and returns a new
-// Version that adheres strictly to SemVer specs
-// https://semver.org/
-func NewSemver(v string) (*Version, error) {
-	return newVersion(v, semverRegexp)
-}
-
-func newVersion(v string, pattern *regexp.Regexp) (*Version, error) {
-	matches := pattern.FindStringSubmatch(v)
-	if matches == nil {
-		return nil, fmt.Errorf("Malformed version: %s", v)
-	}
-	segmentsStr := strings.Split(matches[1], ".")
-	segments := make([]int64, len(segmentsStr))
-	si := 0
-	for i, str := range segmentsStr {
-		val, err := strconv.ParseInt(str, 10, 64)
-		if err != nil {
-			return nil, fmt.Errorf(
-				"Error parsing version: %s", err)
-		}
-
-		segments[i] = int64(val)
-		si++
-	}
-
-	// Even though we could support more than three segments, if we
-	// got less than three, pad it with 0s. This is to cover the basic
-	// default usecase of semver, which is MAJOR.MINOR.PATCH at the minimum
-	for i := len(segments); i < 3; i++ {
-		segments = append(segments, 0)
-	}
-
-	pre := matches[7]
-	if pre == "" {
-		pre = matches[4]
-	}
-
-	return &Version{
-		metadata: matches[10],
-		pre:      pre,
-		segments: segments,
-		si:       si,
-		original: v,
-	}, nil
-}
-
-// Must is a helper that wraps a call to a function returning (*Version, error)
-// and panics if error is non-nil.
-func Must(v *Version, err error) *Version {
-	if err != nil {
-		panic(err)
-	}
-
-	return v
-}
-
-// Compare compares this version to another version. This
-// returns -1, 0, or 1 if this version is smaller, equal,
-// or larger than the other version, respectively.
-//
-// If you want boolean results, use the LessThan, Equal,
-// GreaterThan, GreaterThanOrEqual or LessThanOrEqual methods.
-func (v *Version) Compare(other *Version) int {
-	// A quick, efficient equality check
-	if v.String() == other.String() {
-		return 0
-	}
-
-	segmentsSelf := v.Segments64()
-	segmentsOther := other.Segments64()
-
-	// If the segments are the same, we must compare on prerelease info
-	if reflect.DeepEqual(segmentsSelf, segmentsOther) {
-		preSelf := v.Prerelease()
-		preOther := other.Prerelease()
-		if preSelf == "" && preOther == "" {
-			return 0
-		}
-		if preSelf == "" {
-			return 1
-		}
-		if preOther == "" {
-			return -1
-		}
-
-		return comparePrereleases(preSelf, preOther)
-	}
-
-	// Get the highest specificity (hS), or if they're equal, just use segmentSelf length
-	lenSelf := len(segmentsSelf)
-	lenOther := len(segmentsOther)
-	hS := lenSelf
-	if lenSelf < lenOther {
-		hS = lenOther
-	}
-	// Compare the segments
-	// Because a constraint could have more/less specificity than the version it's
-	// checking, we need to account for a lopsided or jagged comparison
-	for i := 0; i < hS; i++ {
-		if i > lenSelf-1 {
-			// This means Self had the lower specificity
-			// Check to see if the remaining segments in Other are all zeros
-			if !allZero(segmentsOther[i:]) {
-				// if not, it means that Other has to be greater than Self
-				return -1
-			}
-			break
-		} else if i > lenOther-1 {
-			// this means Other had the lower specificity
-			// Check to see if the remaining segments in Self are all zeros -
-			if !allZero(segmentsSelf[i:]) {
-				//if not, it means that Self has to be greater than Other
-				return 1
-			}
-			break
-		}
-		lhs := segmentsSelf[i]
-		rhs := segmentsOther[i]
-		if lhs == rhs {
-			continue
-		} else if lhs < rhs {
-			return -1
-		}
-		// Otherwis, rhs was > lhs, they're not equal
-		return 1
-	}
-
-	// if we got this far, they're equal
-	return 0
-}
-
-func allZero(segs []int64) bool {
-	for _, s := range segs {
-		if s != 0 {
-			return false
-		}
-	}
-	return true
-}
-
-func comparePart(preSelf string, preOther string) int {
-	if preSelf == preOther {
-		return 0
-	}
-
-	var selfInt int64
-	selfNumeric := true
-	selfInt, err := strconv.ParseInt(preSelf, 10, 64)
-	if err != nil {
-		selfNumeric = false
-	}
-
-	var otherInt int64
-	otherNumeric := true
-	otherInt, err = strconv.ParseInt(preOther, 10, 64)
-	if err != nil {
-		otherNumeric = false
-	}
-
-	// if a part is empty, we use the other to decide
-	if preSelf == "" {
-		if otherNumeric {
-			return -1
-		}
-		return 1
-	}
-
-	if preOther == "" {
-		if selfNumeric {
-			return 1
-		}
-		return -1
-	}
-
-	if selfNumeric && !otherNumeric {
-		return -1
-	} else if !selfNumeric && otherNumeric {
-		return 1
-	} else if !selfNumeric && !otherNumeric && preSelf > preOther {
-		return 1
-	} else if selfInt > otherInt {
-		return 1
-	}
-
-	return -1
-}
-
-func comparePrereleases(v string, other string) int {
-	// the same pre release!
-	if v == other {
-		return 0
-	}
-
-	// split both pre releases for analyse their parts
-	selfPreReleaseMeta := strings.Split(v, ".")
-	otherPreReleaseMeta := strings.Split(other, ".")
-
-	selfPreReleaseLen := len(selfPreReleaseMeta)
-	otherPreReleaseLen := len(otherPreReleaseMeta)
-
-	biggestLen := otherPreReleaseLen
-	if selfPreReleaseLen > otherPreReleaseLen {
-		biggestLen = selfPreReleaseLen
-	}
-
-	// loop for parts to find the first difference
-	for i := 0; i < biggestLen; i = i + 1 {
-		partSelfPre := ""
-		if i < selfPreReleaseLen {
-			partSelfPre = selfPreReleaseMeta[i]
-		}
-
-		partOtherPre := ""
-		if i < otherPreReleaseLen {
-			partOtherPre = otherPreReleaseMeta[i]
-		}
-
-		compare := comparePart(partSelfPre, partOtherPre)
-		// if parts are equals, continue the loop
-		if compare != 0 {
-			return compare
-		}
-	}
-
-	return 0
-}
-
-// Equal tests if two versions are equal.
-func (v *Version) Equal(o *Version) bool {
-	if v == nil || o == nil {
-		return v == o
-	}
-
-	return v.Compare(o) == 0
-}
-
-// GreaterThan tests if this version is greater than another version.
-func (v *Version) GreaterThan(o *Version) bool {
-	return v.Compare(o) > 0
-}
-
-// GreaterThanOrEqual tests if this version is greater than or equal to another version.
-func (v *Version) GreaterThanOrEqual(o *Version) bool {
-	return v.Compare(o) >= 0
-}
-
-// LessThan tests if this version is less than another version.
-func (v *Version) LessThan(o *Version) bool {
-	return v.Compare(o) < 0
-}
-
-// LessThanOrEqual tests if this version is less than or equal to another version.
-func (v *Version) LessThanOrEqual(o *Version) bool {
-	return v.Compare(o) <= 0
-}
-
-// Metadata returns any metadata that was part of the version
-// string.
-//
-// Metadata is anything that comes after the "+" in the version.
-// For example, with "1.2.3+beta", the metadata is "beta".
-func (v *Version) Metadata() string {
-	return v.metadata
-}
-
-// Prerelease returns any prerelease data that is part of the version,
-// or blank if there is no prerelease data.
-//
-// Prerelease information is anything that comes after the "-" in the
-// version (but before any metadata). For example, with "1.2.3-beta",
-// the prerelease information is "beta".
-func (v *Version) Prerelease() string {
-	return v.pre
-}
-
-// Segments returns the numeric segments of the version as a slice of ints.
-//
-// This excludes any metadata or pre-release information. For example,
-// for a version "1.2.3-beta", segments will return a slice of
-// 1, 2, 3.
-func (v *Version) Segments() []int {
-	segmentSlice := make([]int, len(v.segments))
-	for i, v := range v.segments {
-		segmentSlice[i] = int(v)
-	}
-	return segmentSlice
-}
-
-// Segments64 returns the numeric segments of the version as a slice of int64s.
-//
-// This excludes any metadata or pre-release information. For example,
-// for a version "1.2.3-beta", segments will return a slice of
-// 1, 2, 3.
-func (v *Version) Segments64() []int64 {
-	result := make([]int64, len(v.segments))
-	copy(result, v.segments)
-	return result
-}
-
-// String returns the full version string included pre-release
-// and metadata information.
-//
-// This value is rebuilt according to the parsed segments and other
-// information. Therefore, ambiguities in the version string such as
-// prefixed zeroes (1.04.0 => 1.4.0), `v` prefix (v1.0.0 => 1.0.0), and
-// missing parts (1.0 => 1.0.0) will be made into a canonicalized form
-// as shown in the parenthesized examples.
-func (v *Version) String() string {
-	var buf bytes.Buffer
-	fmtParts := make([]string, len(v.segments))
-	for i, s := range v.segments {
-		// We can ignore err here since we've pre-parsed the values in segments
-		str := strconv.FormatInt(s, 10)
-		fmtParts[i] = str
-	}
-	fmt.Fprintf(&buf, strings.Join(fmtParts, "."))
-	if v.pre != "" {
-		fmt.Fprintf(&buf, "-%s", v.pre)
-	}
-	if v.metadata != "" {
-		fmt.Fprintf(&buf, "+%s", v.metadata)
-	}
-
-	return buf.String()
-}
-
-// Original returns the original parsed version as-is, including any
-// potential whitespace, `v` prefix, etc.
-func (v *Version) Original() string {
-	return v.original
-}

+ 0 - 17
vendor/github.com/hashicorp/go-version/version_collection.go

@@ -1,17 +0,0 @@
-package version
-
-// Collection is a type that implements the sort.Interface interface
-// so that versions can be sorted.
-type Collection []*Version
-
-func (v Collection) Len() int {
-	return len(v)
-}
-
-func (v Collection) Less(i, j int) bool {
-	return v[i].LessThan(v[j])
-}
-
-func (v Collection) Swap(i, j int) {
-	v[i], v[j] = v[j], v[i]
-}

+ 0 - 379
vendor/github.com/iris-contrib/middleware/cors/cors.go

@@ -1,379 +0,0 @@
-package cors
-
-import (
-	"log"
-	"net/http"
-	"os"
-	"strconv"
-	"strings"
-
-	"github.com/kataras/iris/v12"
-	"github.com/kataras/iris/v12/context"
-)
-
-func init() {
-	context.SetHandlerName("github.com/iris-contrib/middleware/cors.*", "iris-contrib.cors")
-}
-
-// Options is a configuration container to setup the CORS middleware.
-type Options struct {
-	// AllowedOrigins is a list of origins a cross-domain request can be executed from.
-	// If the special "*" value is present in the list, all origins will be allowed.
-	// An origin may contain a wildcard (*) to replace 0 or more characters
-	// (i.e.: http://*.domain.com). Usage of wildcards implies a small performance penalty.
-	// Only one wildcard can be used per origin.
-	// Default value is ["*"]
-	AllowedOrigins []string
-	// AllowOriginFunc is a custom function to validate the origin. It take the origin
-	// as argument and returns true if allowed or false otherwise. If this option is
-	// set, the content of AllowedOrigins is ignored.
-	AllowOriginFunc func(origin string) bool
-	// AllowedMethods is a list of methods the client is allowed to use with
-	// cross-domain requests. Default value is simple methods (HEAD, GET and POST).
-	AllowedMethods []string
-	// AllowedHeaders is list of non simple headers the client is allowed to use with
-	// cross-domain requests.
-	// If the special "*" value is present in the list, all headers will be allowed.
-	// Default value is [] but "Origin" is always appended to the list.
-	AllowedHeaders []string
-	// ExposedHeaders indicates which headers are safe to expose to the API of a CORS
-	// API specification
-	ExposedHeaders []string
-	// MaxAge indicates how long (in seconds) the results of a preflight request
-	// can be cached
-	MaxAge int
-	// AllowCredentials indicates whether the request can include user credentials like
-	// cookies, HTTP authentication or client side SSL certificates.
-	AllowCredentials bool
-	// OptionsPassthrough instructs preflight to let other potential next handlers to
-	// process the OPTIONS method. Turn this on if your application handles OPTIONS.
-	OptionsPassthrough bool
-	// Debugging flag adds additional output to debug server side CORS issues
-	Debug bool
-}
-
-// Cors http handler
-type Cors struct {
-	// Debug logger
-	Log *log.Logger
-	// Normalized list of plain allowed origins
-	allowedOrigins []string
-	// List of allowed origins containing wildcards
-	allowedWOrigins []wildcard
-	// Optional origin validator function
-	allowOriginFunc func(origin string) bool
-	// Normalized list of allowed headers
-	allowedHeaders []string
-	// Normalized list of allowed methods
-	allowedMethods []string
-	// Normalized list of exposed headers
-	exposedHeaders []string
-	maxAge         int
-	// Set to true when allowed origins contains a "*"
-	allowedOriginsAll bool
-	// Set to true when allowed headers contains a "*"
-	allowedHeadersAll bool
-	allowCredentials  bool
-	optionPassthrough bool
-}
-
-// New creates a new Cors handler with the provided options.
-// Use the Application.UseRouter method to register it globally,
-// this is the best option as it enables all the middleware's features.
-// Or to register it per group of routes use:
-// the Party.AllowMethods(iris.MethodOptions) and Party.Use methods instead.
-func New(options Options) iris.Handler {
-	c := &Cors{
-		exposedHeaders:    convert(options.ExposedHeaders, http.CanonicalHeaderKey),
-		allowOriginFunc:   options.AllowOriginFunc,
-		allowCredentials:  options.AllowCredentials,
-		maxAge:            options.MaxAge,
-		optionPassthrough: options.OptionsPassthrough,
-	}
-	if options.Debug {
-		c.Log = log.New(os.Stdout, "[cors] ", log.LstdFlags)
-	}
-
-	// Normalize options
-	// Note: for origins and methods matching, the spec requires a case-sensitive matching.
-	// As it may error prone, we chose to ignore the spec here.
-
-	// Allowed Origins
-	if len(options.AllowedOrigins) == 0 {
-		if options.AllowOriginFunc == nil {
-			// Default is all origins
-			c.allowedOriginsAll = true
-		}
-	} else {
-		c.allowedOrigins = []string{}
-		c.allowedWOrigins = []wildcard{}
-		for _, origin := range options.AllowedOrigins {
-			// Normalize
-			origin = strings.ToLower(origin)
-			if origin == "*" {
-				// If "*" is present in the list, turn the whole list into a match all
-				c.allowedOriginsAll = true
-				c.allowedOrigins = nil
-				c.allowedWOrigins = nil
-				break
-			} else if i := strings.IndexByte(origin, '*'); i >= 0 {
-				// Split the origin in two: start and end string without the *
-				w := wildcard{origin[0:i], origin[i+1:]}
-				c.allowedWOrigins = append(c.allowedWOrigins, w)
-			} else {
-				c.allowedOrigins = append(c.allowedOrigins, origin)
-			}
-		}
-	}
-
-	// Allowed Headers
-	if len(options.AllowedHeaders) == 0 {
-		// Use sensible defaults
-		c.allowedHeaders = []string{"Origin", "Accept", "Content-Type", "X-Requested-With"}
-	} else {
-		// Origin is always appended as some browsers will always request for this header at preflight
-		c.allowedHeaders = convert(append(options.AllowedHeaders, "Origin"), http.CanonicalHeaderKey)
-		for _, h := range options.AllowedHeaders {
-			if h == "*" {
-				c.allowedHeadersAll = true
-				c.allowedHeaders = nil
-				break
-			}
-		}
-	}
-
-	// Allowed Methods
-	if len(options.AllowedMethods) == 0 {
-		// Default is spec's "simple" methods
-		c.allowedMethods = []string{"GET", "POST", "HEAD"}
-	} else {
-		c.allowedMethods = convert(options.AllowedMethods, strings.ToUpper)
-	}
-
-	return c.Serve
-}
-
-// Default creates a new Cors handler with default options.
-func Default() iris.Handler {
-	return New(Options{})
-}
-
-// AllowAll create a new Cors handler with permissive configuration allowing all
-// origins with all standard methods with any header and credentials.
-func AllowAll() iris.Handler {
-	return New(Options{
-		AllowedOrigins:   []string{"*"},
-		AllowedMethods:   []string{"HEAD", "GET", "POST", "PUT", "PATCH", "DELETE"},
-		AllowedHeaders:   []string{"*"},
-		AllowCredentials: true,
-	})
-}
-
-// Serve apply the CORS specification on the request, and add relevant CORS headers
-// as necessary.
-func (c *Cors) Serve(ctx iris.Context) {
-	if ctx.Method() == http.MethodOptions && ctx.GetHeader("Access-Control-Request-Method") != "" {
-		c.logf("Serve: Preflight request")
-		c.handlePreflight(ctx)
-		if c.optionPassthrough { // handle the options by routes.
-			ctx.Next()
-			return
-		}
-
-		if !ctx.IsStopped() {
-			// just 200.
-			ctx.StatusCode(http.StatusOK)
-			ctx.StopExecution()
-		}
-
-		return
-	}
-
-	c.logf("Serve: Actual request")
-	c.handleActualRequest(ctx)
-	ctx.Next()
-}
-
-// handlePreflight handles pre-flight CORS requests
-func (c *Cors) handlePreflight(ctx iris.Context) {
-	origin := ctx.GetHeader("Origin")
-
-	if ctx.Method() != http.MethodOptions {
-		c.logf("  Preflight aborted: %s!=OPTIONS", ctx.Method())
-		//
-		ctx.StopWithStatus(iris.StatusForbidden)
-		//
-		return
-	}
-	// Always set Vary headers.
-	ctx.Header("Vary", "Origin, Access-Control-Request-Method, Access-Control-Request-Headers")
-
-	if origin == "" {
-		c.logf("  Preflight aborted: empty origin")
-		return
-	}
-	if !c.isOriginAllowed(origin) {
-		c.logf("  Preflight aborted: origin '%s' not allowed", origin)
-		//
-		ctx.StopWithStatus(iris.StatusForbidden)
-		//
-		return
-	}
-
-	reqMethod := ctx.GetHeader("Access-Control-Request-Method")
-	if !c.isMethodAllowed(reqMethod) {
-		c.logf("  Preflight aborted: method '%s' not allowed", reqMethod)
-		//
-		ctx.StopWithStatus(iris.StatusForbidden)
-		//
-		return
-	}
-	reqHeaders := parseHeaderList(ctx.GetHeader("Access-Control-Request-Headers"))
-	if !c.areHeadersAllowed(reqHeaders) {
-		c.logf("  Preflight aborted: headers '%v' not allowed", reqHeaders)
-		//
-		ctx.StopWithStatus(iris.StatusForbidden)
-		//
-		return
-	}
-	if c.allowedOriginsAll && !c.allowCredentials {
-		ctx.Header("Access-Control-Allow-Origin", "*")
-	} else {
-		ctx.Header("Access-Control-Allow-Origin", origin)
-	}
-	// Spec says: Since the list of methods can be unbounded, simply returning the method indicated
-	// by Access-Control-Request-Method (if supported) can be enough
-	ctx.Header("Access-Control-Allow-Methods", strings.ToUpper(reqMethod))
-	if len(reqHeaders) > 0 {
-		// Spec says: Since the list of headers can be unbounded, simply returning supported headers
-		// from Access-Control-Request-Headers can be enough
-		ctx.Header("Access-Control-Allow-Headers", strings.Join(reqHeaders, ", "))
-	}
-	if c.allowCredentials {
-		ctx.Header("Access-Control-Allow-Credentials", "true")
-	}
-	if c.maxAge > 0 {
-		ctx.Header("Access-Control-Max-Age", strconv.Itoa(c.maxAge))
-	}
-	c.logf("  Preflight response headers: %v", ctx.ResponseWriter().Header())
-}
-
-// handleActualRequest handles simple cross-origin requests, actual request or redirects
-func (c *Cors) handleActualRequest(ctx iris.Context) {
-	origin := ctx.GetHeader("Origin")
-
-	if ctx.Method() == http.MethodOptions {
-		c.logf("  Actual request no headers added: method == %s", ctx.Method())
-		//
-		ctx.StopWithStatus(iris.StatusMethodNotAllowed)
-		//
-		return
-	}
-	// Always set Vary, see https://github.com/rs/cors/issues/10
-	ctx.ResponseWriter().Header().Add("Vary", "Origin")
-	if origin == "" && !c.allowedOriginsAll {
-		c.logf("  Actual request no headers added: missing origin")
-		return
-	}
-
-	if !c.isOriginAllowed(origin) {
-		c.logf("  Actual request no headers added: origin '%s' not allowed", origin)
-		//
-		ctx.StopWithStatus(iris.StatusForbidden)
-		//
-		return
-	}
-
-	// Note that spec does define a way to specifically disallow a simple method like GET or
-	// POST. Access-Control-Allow-Methods is only used for pre-flight requests and the
-	// spec doesn't instruct to check the allowed methods for simple cross-origin requests.
-	// We think it's a nice feature to be able to have control on those methods though.
-	if !c.isMethodAllowed(ctx.Method()) {
-		c.logf("  Actual request no headers added: method '%s' not allowed", ctx.Method())
-		ctx.StopWithStatus(iris.StatusForbidden)
-		return
-	}
-	if c.allowedOriginsAll && !c.allowCredentials {
-		ctx.Header("Access-Control-Allow-Origin", "*")
-	} else {
-		ctx.Header("Access-Control-Allow-Origin", origin)
-	}
-	if len(c.exposedHeaders) > 0 {
-		ctx.Header("Access-Control-Expose-Headers", strings.Join(c.exposedHeaders, ", "))
-	}
-	if c.allowCredentials {
-		ctx.Header("Access-Control-Allow-Credentials", "true")
-	}
-	c.logf("  Actual response added headers: %v", ctx.ResponseWriter().Header())
-}
-
-// convenience method. checks if debugging is turned on before printing
-func (c *Cors) logf(format string, a ...interface{}) {
-	if c.Log != nil {
-		c.Log.Printf(format, a...)
-	}
-}
-
-// isOriginAllowed checks if a given origin is allowed to perform cross-domain requests
-// on the endpoint
-func (c *Cors) isOriginAllowed(origin string) bool {
-	if c.allowOriginFunc != nil {
-		return c.allowOriginFunc(origin)
-	}
-	if c.allowedOriginsAll {
-		return true
-	}
-	origin = strings.ToLower(origin)
-	for _, o := range c.allowedOrigins {
-		if o == origin {
-			return true
-		}
-	}
-	for _, w := range c.allowedWOrigins {
-		if w.match(origin) {
-			return true
-		}
-	}
-	return false
-}
-
-// isMethodAllowed checks if a given method can be used as part of a cross-domain request
-// on the endpoing
-func (c *Cors) isMethodAllowed(method string) bool {
-	if len(c.allowedMethods) == 0 {
-		// If no method allowed, always return false, even for preflight request
-		return false
-	}
-	method = strings.ToUpper(method)
-	if method == http.MethodOptions {
-		// Always allow preflight requests
-		return true
-	}
-	for _, m := range c.allowedMethods {
-		if m == method {
-			return true
-		}
-	}
-	return false
-}
-
-// areHeadersAllowed checks if a given list of headers are allowed to used within
-// a cross-domain request.
-func (c *Cors) areHeadersAllowed(requestedHeaders []string) bool {
-	if c.allowedHeadersAll || len(requestedHeaders) == 0 {
-		return true
-	}
-	for _, header := range requestedHeaders {
-		header = http.CanonicalHeaderKey(header)
-		found := false
-		for _, h := range c.allowedHeaders {
-			if h == header {
-				found = true
-			}
-		}
-		if !found {
-			return false
-		}
-	}
-	return true
-}

+ 0 - 70
vendor/github.com/iris-contrib/middleware/cors/util.go

@@ -1,70 +0,0 @@
-package cors
-
-import "strings"
-
-const toLower = 'a' - 'A'
-
-type converter func(string) string
-
-type wildcard struct {
-	prefix string
-	suffix string
-}
-
-func (w wildcard) match(s string) bool {
-	return len(s) >= len(w.prefix+w.suffix) && strings.HasPrefix(s, w.prefix) && strings.HasSuffix(s, w.suffix)
-}
-
-// convert converts a list of string using the passed converter function
-func convert(s []string, c converter) []string {
-	out := []string{}
-	for _, i := range s {
-		out = append(out, c(i))
-	}
-	return out
-}
-
-// parseHeaderList tokenize + normalize a string containing a list of headers
-func parseHeaderList(headerList string) []string {
-	l := len(headerList)
-	h := make([]byte, 0, l)
-	upper := true
-	// Estimate the number headers in order to allocate the right splice size
-	t := 0
-	for i := 0; i < l; i++ {
-		if headerList[i] == ',' {
-			t++
-		}
-	}
-	headers := make([]string, 0, t)
-	for i := 0; i < l; i++ {
-		b := headerList[i]
-		if b >= 'a' && b <= 'z' {
-			if upper {
-				h = append(h, b-toLower)
-			} else {
-				h = append(h, b)
-			}
-		} else if b >= 'A' && b <= 'Z' {
-			if !upper {
-				h = append(h, b+toLower)
-			} else {
-				h = append(h, b)
-			}
-		} else if b == '-' || b == '_' || (b >= '0' && b <= '9') {
-			h = append(h, b)
-		}
-
-		if b == ' ' || b == ',' || i == l-1 {
-			if len(h) > 0 {
-				// Flush the found header
-				headers = append(headers, string(h))
-				h = h[:0]
-				upper = true
-			}
-		} else {
-			upper = b == '-' || b == '_'
-		}
-	}
-	return headers
-}

+ 0 - 22
vendor/github.com/kataras/iris/mvc/reflect.go

@@ -1,22 +0,0 @@
-package mvc
-
-import (
-	"reflect"
-)
-
-var baseControllerTyp = reflect.TypeOf((*BaseController)(nil)).Elem()
-
-func isBaseController(ctrlTyp reflect.Type) bool {
-	return ctrlTyp.Implements(baseControllerTyp)
-}
-
-// indirectType returns the value of a pointer-type "typ".
-// If "typ" is a pointer, array, chan, map or slice it returns its Elem,
-// otherwise returns the typ as it's.
-func indirectType(typ reflect.Type) reflect.Type {
-	switch typ.Kind() {
-	case reflect.Ptr, reflect.Array, reflect.Chan, reflect.Map, reflect.Slice:
-		return typ.Elem()
-	}
-	return typ
-}

+ 43 - 0
vendor/github.com/kataras/iris/v12/HISTORY.md

@@ -19,10 +19,53 @@ Developers are not forced to upgrade if they don't really need it. Upgrade whene
 
 **How to upgrade**: Open your command-line and execute this command: `go get github.com/kataras/iris/v12@latest` and `go mod tidy -compat=1.21`.
 
+
 # Next
 
 Changes apply to `main` branch.
 
+# Thu, 18 Jan 2024 | v12.2.10
+
+- Simplify the `/core/host` subpackage and remove its `DeferFlow` and `RestoreFlow` methods.
+- Fix internal `trimHandlerName` and other minor stuff.
+- New `iris.NonBlocking()` configuration option to run the server without blocking the main routine, `Application.Wait(context.Context) error` method can be used to block and wait for the server to be up and running. Example:
+
+```go
+func main() {
+    app := iris.New()
+    app.Get("/", func(ctx iris.Context) {
+        ctx.Writef("Hello, %s!", "World")
+    })
+
+    app.Listen(":8080", iris.NonBlocking(), iris.WithoutServerError(iris.ErrServerClosed))
+
+    ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
+    defer cancel()
+
+    if err := app.Wait(ctx); err != nil {
+        log.Fatal(err)
+    }
+
+    // [Server is up and running now, you may continue with other functions below].
+}
+```
+
+- Add `x/mathx.RoundToInteger` math helper function.
+
+# Wed, 10 Jan 2024 | v12.2.9
+
+- Add `x/errors.RecoveryHandler` package-level function.
+- Add `x/errors.Validation` package-level function to add one or more validations for the request payload before a service call of the below methods.
+- Add `x/errors.Handler`, `CreateHandler`, `NoContentHandler`, `NoContentOrNotModifiedHandler` and `ListHandler` ready-to-use handlers for service method calls to Iris Handler.
+- Add `x/errors.List` package-level function to support `ListObjects(ctx context.Context, opts pagination.ListOptions, f Filter) ([]Object, int64, error)` type of service calls.
+- Simplify how validation errors on `/x/errors` package works. A new `x/errors/validation` sub-package added to make your life easier (using the powerful Generics feature).
+- Add `x/errors.OK`, `Create`, `NoContent` and `NoContentOrNotModified` package-level generic functions as custom service method caller helpers. Example can be found [here](_examples/routing/http-wire-errors/service/main.go).
+- Add `x/errors.ReadPayload`, `ReadQuery`, `ReadPaginationOptions`, `Handle`, `HandleCreate`, `HandleCreateResponse`, `HandleUpdate` and `HandleDelete` package-level functions as helpers for common actions.
+- Add `x/jsonx.GetSimpleDateRange(date, jsonx.WeekRange, time.Monday, time.Sunday)` which returns all dates between the given range and start/end weekday values for WeekRange.
+- Add `x/timex.GetMonthDays` and `x/timex.GetMonthEnd` functions.
+- Add `iris.CookieDomain` and `iris.CookieOverride` cookie options to handle [#2309](https://github.com/kataras/iris/issues/2309).
+- New `x/errors.ErrorCodeName.MapErrorFunc`, `MapErrors`, `Wrap` methods and `x/errors.HandleError` package-level function.
+
 # Sun, 05 Nov 2023 | v12.2.8
 
 - A new way to customize the handler's parameter among with the `hero` and `mvc` packages. New `iris.NewContextWrapper` and

+ 1 - 1
vendor/github.com/kataras/iris/v12/LICENSE

@@ -1,6 +1,6 @@
 BSD 3-Clause License
 
-Copyright (c) 2016-2023, Gerasimos (Makis) Maropoulos
+Copyright (c) 2016-2024, Gerasimos (Makis) Maropoulos
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without

+ 103 - 75
vendor/github.com/kataras/iris/v12/README.md

@@ -6,7 +6,7 @@ Try the official [Iris Command Line Interface](https://github.com/kataras/iris-c
 
 # <a href="https://iris-go.com"><img src="https://iris-go.com/images/logo-new-lq-45.png"></a> Iris Web Framework <a href="README_GR.md"><img width="20px" src="https://iris-go.com/images/flag-greece.svg" /> <a href="README_JA.md"><img width="20px" height="20px" src="https://iris-go.com/images/flag-japan.svg" /></a> </a> <a href="README_FR.md"><img width="20px" src="https://iris-go.com/images/flag-france.svg" /></a> <a href="README_ZH_HANT.md"><img width="20px" src="https://iris-go.com/images/flag-taiwan.svg" /></a> <a href="README_ZH_HANS.md"><img width="20px" src="https://iris-go.com/images/flag-china.svg" /></a> <a href="README_ES.md"><img width="20px" src="https://iris-go.com/images/flag-spain.png" /></a> <a href="README_FA.md"><img width="20px" src="https://iris-go.com/images/flag-iran.svg" /></a> <a href="README_RU.md"><img width="20px" src="https://iris-go.com/images/flag-russia.svg" /></a> <a href="README_KO.md"><img width="20px" src="https://iris-go.com/images/flag-south-korea.svg?v=12" /></a> <a href="README_PT_BR.md"><img width="20px" height="20px" src="https://iris-go.com/images/flag-brazil.svg" /></a> <a href="README_VN.md"><img width="20px" height="20px" src="https://iris-go.com/images/flag-vietnam.svg" /></a>
 
-[![build status](https://img.shields.io/github/actions/workflow/status/kataras/iris/ci.yml?branch=main&style=for-the-badge)](https://github.com/kataras/iris/actions/workflows/ci.yml) [![view examples](https://img.shields.io/badge/examples%20-285-a83adf.svg?style=for-the-badge&logo=go)](https://github.com/kataras/iris/tree/main/_examples) [![chat](https://img.shields.io/gitter/room/iris_go/community.svg?color=cc2b5e&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community) <!--[![FOSSA Status](https://img.shields.io/badge/LICENSE%20SCAN-PASSING❤️-CD2956?style=for-the-badge&logo=fossa)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkataras%2Firis?ref=badge_shield)--> [![donate](https://img.shields.io/badge/support-Iris-blue.svg?style=for-the-badge&logo=paypal)](https://iris-go.com/donate) <!--[![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)--><!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://pkg.go.dev/github.com/kataras/iris/v12@v12.2.8)--> <!-- [![release](https://img.shields.io/badge/release%20-v12.0-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases) -->
+[![build status](https://img.shields.io/github/actions/workflow/status/kataras/iris/ci.yml?branch=main&style=for-the-badge)](https://github.com/kataras/iris/actions/workflows/ci.yml) [![view examples](https://img.shields.io/badge/examples%20-285-a83adf.svg?style=for-the-badge&logo=go)](https://github.com/kataras/iris/tree/main/_examples) [![chat](https://img.shields.io/gitter/room/iris_go/community.svg?color=cc2b5e&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community) <!--[![FOSSA Status](https://img.shields.io/badge/LICENSE%20SCAN-PASSING❤️-CD2956?style=for-the-badge&logo=fossa)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkataras%2Firis?ref=badge_shield)--> [![donate](https://img.shields.io/badge/support-Iris-blue.svg?style=for-the-badge&logo=paypal)](https://iris-go.com/donate) <!--[![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)--><!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://pkg.go.dev/github.com/kataras/iris/v12@v)--> <!-- [![release](https://img.shields.io/badge/release%20-v12.0-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases) -->
 
 Iris is a fast, simple yet fully featured and very efficient web framework for Go.
 
@@ -208,17 +208,13 @@ Some of the features Iris offers:
 With your help, we can improve Open Source web development for everyone!
 
 <p>
-  <a href="https://github.com/github"><img src="https://avatars1.githubusercontent.com/u/9919?v=4" alt="github" title="github" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/getsentry"><img src="https://avatars1.githubusercontent.com/u/1396951?v=4" alt="getsentry" title="getsentry" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/github"><img src="https://avatars1.githubusercontent.com/u/9919?v=4" alt="github" title="github" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/lensesio"><img src="https://avatars1.githubusercontent.com/u/11728472?v=4" alt="lensesio" title="lensesio" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/thepunterbot"><img src="https://avatars1.githubusercontent.com/u/111136029?v=4" alt="thepunterbot" title="thepunterbot" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/jnelle"><img src="https://avatars1.githubusercontent.com/u/36324542?v=4" alt="jnelle" title="jnelle" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/PaddyFrenchman"><img src="https://avatars1.githubusercontent.com/u/55139902?v=4" alt="PaddyFrenchman" title="PaddyFrenchman" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/beytullahakyuz"><img src="https://avatars1.githubusercontent.com/u/10866179?v=4" alt="beytullahakyuz" title="beytullahakyuz" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/gloudx"><img src="https://avatars1.githubusercontent.com/u/6920756?v=4" alt="gloudx" title="gloudx" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/iuliancarnaru"><img src="https://avatars1.githubusercontent.com/u/35683015?v=4" alt="iuliancarnaru" title="iuliancarnaru" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/lemuelroberto"><img src="https://avatars1.githubusercontent.com/u/322159?v=4" alt="lemuelroberto" title="lemuelroberto" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/linuxluigi"><img src="https://avatars1.githubusercontent.com/u/8136842?v=4" alt="linuxluigi" title="linuxluigi" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/tstangenberg"><img src="https://avatars1.githubusercontent.com/u/736160?v=4" alt="tstangenberg" title="tstangenberg" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/cuong48d"><img src="https://avatars1.githubusercontent.com/u/456049?v=4" alt="cuong48d" title="cuong48d" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/rubyangxg"><img src="https://avatars1.githubusercontent.com/u/3069914?v=4" alt="rubyangxg" title="rubyangxg" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/draFWM"><img src="https://avatars1.githubusercontent.com/u/5765340?v=4" alt="draFWM" title="draFWM" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/gf3"><img src="https://avatars1.githubusercontent.com/u/18397?v=4" alt="gf3" title="gf3" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/trading-peter"><img src="https://avatars1.githubusercontent.com/u/11567985?v=4" alt="trading-peter" title="trading-peter" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
@@ -230,16 +226,19 @@ With your help, we can improve Open Source web development for everyone!
   <a href="https://github.com/Remydeme"><img src="https://avatars1.githubusercontent.com/u/22757039?v=4" alt="Remydeme" title="Remydeme" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/celsosz"><img src="https://avatars1.githubusercontent.com/u/3466493?v=4" alt="celsosz" title="celsosz" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/linxcoder"><img src="https://avatars1.githubusercontent.com/u/1050802?v=4" alt="linxcoder" title="linxcoder" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/jnelle"><img src="https://avatars1.githubusercontent.com/u/36324542?v=4" alt="jnelle" title="jnelle" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/TechMaster"><img src="https://avatars1.githubusercontent.com/u/1491686?v=4" alt="TechMaster" title="TechMaster" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/janwebdev"><img src="https://avatars1.githubusercontent.com/u/6725905?v=4" alt="janwebdev" title="janwebdev" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/altafino"><img src="https://avatars1.githubusercontent.com/u/24539467?v=4" alt="altafino" title="altafino" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/jakoubek"><img src="https://avatars1.githubusercontent.com/u/179566?v=4" alt="jakoubek" title="jakoubek" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/alekperos"><img src="https://avatars1.githubusercontent.com/u/683938?v=4" alt="alekperos" title="alekperos" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/day0ng"><img src="https://avatars1.githubusercontent.com/u/15760418?v=4" alt="day0ng" title="day0ng" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/hengestone"><img src="https://avatars1.githubusercontent.com/u/362587?v=4" alt="hengestone" title="hengestone" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/thomasfr"><img src="https://avatars1.githubusercontent.com/u/287432?v=4" alt="thomasfr" title="thomasfr" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/CetinBasoz"><img src="https://avatars1.githubusercontent.com/u/3152637?v=4" alt="CetinBasoz" title="CetinBasoz" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/International"><img src="https://avatars1.githubusercontent.com/u/1022918?v=4" alt="International" title="International" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/Juanses"><img src="https://avatars1.githubusercontent.com/u/6137970?v=4" alt="Juanses" title="Juanses" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/SometimesMage"><img src="https://avatars1.githubusercontent.com/u/1435257?v=4" alt="SometimesMage" title="SometimesMage" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/ansrivas"><img src="https://avatars1.githubusercontent.com/u/1695056?v=4" alt="ansrivas" title="ansrivas" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/ekobayong"><img src="https://avatars1.githubusercontent.com/u/878170?v=4" alt="ekobayong" title="ekobayong" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/lexrus"><img src="https://avatars1.githubusercontent.com/u/219689?v=4" alt="lexrus" title="lexrus" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
@@ -247,16 +246,22 @@ With your help, we can improve Open Source web development for everyone!
   <a href="https://github.com/madhu72"><img src="https://avatars1.githubusercontent.com/u/10324127?v=4" alt="madhu72" title="madhu72" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/se77en"><img src="https://avatars1.githubusercontent.com/u/1468284?v=4" alt="se77en" title="se77en" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/vincent-li"><img src="https://avatars1.githubusercontent.com/u/765470?v=4" alt="vincent-li" title="vincent-li" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/njeff3"><img src="https://avatars1.githubusercontent.com/u/9838120?v=4" alt="njeff3" title="njeff3" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/ixalender"><img src="https://avatars1.githubusercontent.com/u/877376?v=4" alt="ixalender" title="ixalender" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/mubariz-ahmed"><img src="https://avatars1.githubusercontent.com/u/18215455?v=4" alt="mubariz-ahmed" title="mubariz-ahmed" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/Cesar"><img src="https://avatars1.githubusercontent.com/u/1581870?v=4" alt="Cesar" title="Cesar" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/DavidShaw"><img src="https://avatars1.githubusercontent.com/u/356970?v=4" alt="DavidShaw" title="DavidShaw" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/sascha11110"><img src="https://avatars1.githubusercontent.com/u/15168372?v=4" alt="sascha11110" title="sascha11110" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/clichi2002"><img src="https://avatars1.githubusercontent.com/u/5856121?v=4" alt="clichi2002" title="clichi2002" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/derReineke"><img src="https://avatars1.githubusercontent.com/u/35681013?v=4" alt="derReineke" title="derReineke" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/Sirisap22"><img src="https://avatars1.githubusercontent.com/u/58851659?v=4" alt="Sirisap22" title="Sirisap22" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/primadi"><img src="https://avatars1.githubusercontent.com/u/7625413?v=4" alt="primadi" title="primadi" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/agoncecelia"><img src="https://avatars1.githubusercontent.com/u/10442924?v=4" alt="agoncecelia" title="agoncecelia" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/antonio-pedrazzini"><img src="https://avatars1.githubusercontent.com/u/83503326?v=4" alt="antonio-pedrazzini" title="antonio-pedrazzini" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/chrisliang12"><img src="https://avatars1.githubusercontent.com/u/97201988?v=4" alt="chrisliang12" title="chrisliang12" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/zyu"><img src="https://avatars1.githubusercontent.com/u/807397?v=4" alt="zyu" title="zyu" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/hobysmith"><img src="https://avatars1.githubusercontent.com/u/6063391?v=4" alt="hobysmith" title="hobysmith" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/clacroix"><img src="https://avatars1.githubusercontent.com/u/611064?v=4" alt="clacroix" title="clacroix" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/njeff3"><img src="https://avatars1.githubusercontent.com/u/9838120?v=4" alt="njeff3" title="njeff3" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/ixalender"><img src="https://avatars1.githubusercontent.com/u/877376?v=4" alt="ixalender" title="ixalender" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/mubariz-ahmed"><img src="https://avatars1.githubusercontent.com/u/18215455?v=4" alt="mubariz-ahmed" title="mubariz-ahmed" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/Cesar"><img src="https://avatars1.githubusercontent.com/u/1581870?v=4" alt="Cesar" title="Cesar" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/DavidShaw"><img src="https://avatars1.githubusercontent.com/u/356970?v=4" alt="DavidShaw" title="DavidShaw" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/th31nitiate"><img src="https://avatars1.githubusercontent.com/u/14749635?v=4" alt="th31nitiate" title="th31nitiate" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/stgrosshh"><img src="https://avatars1.githubusercontent.com/u/8356082?v=4" alt="stgrosshh" title="stgrosshh" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/rodrigoghm"><img src="https://avatars1.githubusercontent.com/u/66917643?v=4" alt="rodrigoghm" title="rodrigoghm" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
@@ -266,19 +271,25 @@ With your help, we can improve Open Source web development for everyone!
   <a href="https://github.com/Little-YangYang"><img src="https://avatars1.githubusercontent.com/u/10755202?v=4" alt="Little-YangYang" title="Little-YangYang" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/Major2828"><img src="https://avatars1.githubusercontent.com/u/19783402?v=4" alt="Major2828" title="Major2828" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/MatejLach"><img src="https://avatars1.githubusercontent.com/u/531930?v=4" alt="MatejLach" title="MatejLach" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/agoncecelia"><img src="https://avatars1.githubusercontent.com/u/10442924?v=4" alt="agoncecelia" title="agoncecelia" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/amritpal042"><img src="https://avatars1.githubusercontent.com/u/60704162?v=4" alt="amritpal042" title="amritpal042" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/andrefiorot"><img src="https://avatars1.githubusercontent.com/u/13743098?v=4" alt="andrefiorot" title="andrefiorot" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/boomhut"><img src="https://avatars1.githubusercontent.com/u/56619040?v=4" alt="boomhut" title="boomhut" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/coderperu"><img src="https://avatars1.githubusercontent.com/u/68706957?v=4" alt="coderperu" title="coderperu" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/hobysmith"><img src="https://avatars1.githubusercontent.com/u/6063391?v=4" alt="hobysmith" title="hobysmith" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/clacroix"><img src="https://avatars1.githubusercontent.com/u/611064?v=4" alt="clacroix" title="clacroix" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/cshum"><img src="https://avatars1.githubusercontent.com/u/293790?v=4" alt="cshum" title="cshum" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/dtrifonov"><img src="https://avatars1.githubusercontent.com/u/1520118?v=4" alt="dtrifonov" title="dtrifonov" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/geordee"><img src="https://avatars1.githubusercontent.com/u/83303?v=4" alt="geordee" title="geordee" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/guanting112"><img src="https://avatars1.githubusercontent.com/u/11306350?v=4" alt="guanting112" title="guanting112" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/iantuan"><img src="https://avatars1.githubusercontent.com/u/4869968?v=4" alt="iantuan" title="iantuan" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/ichenhe"><img src="https://avatars1.githubusercontent.com/u/10266066?v=4" alt="ichenhe" title="ichenhe" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/angelaahhu"><img src="https://avatars1.githubusercontent.com/u/128401549?v=4" alt="angelaahhu" title="angelaahhu" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/anhxuanpham"><img src="https://avatars1.githubusercontent.com/u/101174797?v=4" alt="anhxuanpham" title="anhxuanpham" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/annieruci"><img src="https://avatars1.githubusercontent.com/u/49377699?v=4" alt="annieruci" title="annieruci" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/antoniejiao"><img src="https://avatars1.githubusercontent.com/u/17450960?v=4" alt="antoniejiao" title="antoniejiao" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/artman328"><img src="https://avatars1.githubusercontent.com/u/5415792?v=4" alt="artman328" title="artman328" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/b2cbd"><img src="https://avatars1.githubusercontent.com/u/6870050?v=4" alt="b2cbd" title="b2cbd" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/baoch254"><img src="https://avatars1.githubusercontent.com/u/74555344?v=4" alt="baoch254" title="baoch254" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/icibiri"><img src="https://avatars1.githubusercontent.com/u/32684966?v=4" alt="icibiri" title="icibiri" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/jewe11er"><img src="https://avatars1.githubusercontent.com/u/47153959?v=4" alt="jewe11er" title="jewe11er" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/jfloresremar"><img src="https://avatars1.githubusercontent.com/u/10441071?v=4" alt="jfloresremar" title="jfloresremar" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/jingtianfeng"><img src="https://avatars1.githubusercontent.com/u/19503202?v=4" alt="jingtianfeng" title="jingtianfeng" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/kilarusravankumar"><img src="https://avatars1.githubusercontent.com/u/13055113?v=4" alt="kilarusravankumar" title="kilarusravankumar" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
@@ -294,12 +305,14 @@ With your help, we can improve Open Source web development for everyone!
   <a href="https://github.com/narven"><img src="https://avatars1.githubusercontent.com/u/123594?v=4" alt="narven" title="narven" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/odas0r"><img src="https://avatars1.githubusercontent.com/u/32167770?v=4" alt="odas0r" title="odas0r" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/olaf-lexemo"><img src="https://avatars1.githubusercontent.com/u/51406599?v=4" alt="olaf-lexemo" title="olaf-lexemo" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/pitexplore"><img src="https://avatars1.githubusercontent.com/u/11956562?v=4" alt="pitexplore" title="pitexplore" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/pr123"><img src="https://avatars1.githubusercontent.com/u/23333176?v=4" alt="pr123" title="pr123" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/rsousacode"><img src="https://avatars1.githubusercontent.com/u/34067397?v=4" alt="rsousacode" title="rsousacode" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/sankethpb"><img src="https://avatars1.githubusercontent.com/u/16034868?v=4" alt="sankethpb" title="sankethpb" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/saz59"><img src="https://avatars1.githubusercontent.com/u/9706793?v=4" alt="saz59" title="saz59" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/shadowfiga"><img src="https://avatars1.githubusercontent.com/u/42721390?v=4" alt="shadowfiga" title="shadowfiga" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/siriushaha"><img src="https://avatars1.githubusercontent.com/u/7924311?v=4" alt="siriushaha" title="siriushaha" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/bastengao"><img src="https://avatars1.githubusercontent.com/u/785335?v=4" alt="bastengao" title="bastengao" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/skurtz97"><img src="https://avatars1.githubusercontent.com/u/71720714?v=4" alt="skurtz97" title="skurtz97" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/srinivasganti"><img src="https://avatars1.githubusercontent.com/u/2057165?v=4" alt="srinivasganti" title="srinivasganti" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/syrm"><img src="https://avatars1.githubusercontent.com/u/155406?v=4" alt="syrm" title="syrm" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
@@ -315,6 +328,11 @@ With your help, we can improve Open Source web development for everyone!
   <a href="https://github.com/francisstephan"><img src="https://avatars1.githubusercontent.com/u/15109897?v=4" alt="francisstephan" title="francisstephan" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/pixelheresy"><img src="https://avatars1.githubusercontent.com/u/2491944?v=4" alt="pixelheresy" title="pixelheresy" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/rcapraro"><img src="https://avatars1.githubusercontent.com/u/245490?v=4" alt="rcapraro" title="rcapraro" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/beytullahakyuz"><img src="https://avatars1.githubusercontent.com/u/10866179?v=4" alt="beytullahakyuz" title="beytullahakyuz" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/bjoroen"><img src="https://avatars1.githubusercontent.com/u/31513139?v=4" alt="bjoroen" title="bjoroen" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/blackHoleNgc1277"><img src="https://avatars1.githubusercontent.com/u/41342763?v=4" alt="blackHoleNgc1277" title="blackHoleNgc1277" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/bunnycodego"><img src="https://avatars1.githubusercontent.com/u/81451316?v=4" alt="bunnycodego" title="bunnycodego" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/carlos-enginner"><img src="https://avatars1.githubusercontent.com/u/59775876?v=4" alt="carlos-enginner" title="carlos-enginner" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/soiestad"><img src="https://avatars1.githubusercontent.com/u/9642036?v=4" alt="soiestad" title="soiestad" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/thanasolykos"><img src="https://avatars1.githubusercontent.com/u/35801329?v=4" alt="thanasolykos" title="thanasolykos" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/ukitzmann"><img src="https://avatars1.githubusercontent.com/u/153834?v=4" alt="ukitzmann" title="ukitzmann" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
@@ -325,15 +343,40 @@ With your help, we can improve Open Source web development for everyone!
   <a href="https://github.com/spazzymoto"><img src="https://avatars1.githubusercontent.com/u/2951012?v=4" alt="spazzymoto" title="spazzymoto" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/victorgrey"><img src="https://avatars1.githubusercontent.com/u/207128?v=4" alt="victorgrey" title="victorgrey" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/ArishSultan"><img src="https://avatars1.githubusercontent.com/u/31086233?v=4" alt="ArishSultan" title="ArishSultan" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/EliYip"><img src="https://avatars1.githubusercontent.com/u/40079533?v=4" alt="EliYip" title="EliYip" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/ehayun"><img src="https://avatars1.githubusercontent.com/u/39870648?v=4" alt="ehayun" title="ehayun" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/chrismalek"><img src="https://avatars1.githubusercontent.com/u/9403?v=4" alt="chrismalek" title="chrismalek" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/civicwar"><img src="https://avatars1.githubusercontent.com/u/1858104?v=4" alt="civicwar" title="civicwar" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/cnzhangquan"><img src="https://avatars1.githubusercontent.com/u/5462876?v=4" alt="cnzhangquan" title="cnzhangquan" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/danlanxiaohei"><img src="https://avatars1.githubusercontent.com/u/3272530?v=4" alt="danlanxiaohei" title="danlanxiaohei" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/dfaugusto"><img src="https://avatars1.githubusercontent.com/u/1554920?v=4" alt="dfaugusto" title="dfaugusto" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/dkzhang"><img src="https://avatars1.githubusercontent.com/u/1091431?v=4" alt="dkzhang" title="dkzhang" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/dloprodu"><img src="https://avatars1.githubusercontent.com/u/664947?v=4" alt="dloprodu" title="dloprodu" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/donam-givita"><img src="https://avatars1.githubusercontent.com/u/107529604?v=4" alt="donam-givita" title="donam-givita" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/dph0899"><img src="https://avatars1.githubusercontent.com/u/124650663?v=4" alt="dph0899" title="dph0899" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/ec0629"><img src="https://avatars1.githubusercontent.com/u/7861125?v=4" alt="ec0629" title="ec0629" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/edwindna2"><img src="https://avatars1.githubusercontent.com/u/5441354?v=4" alt="edwindna2" title="edwindna2" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/ekofedriyanto"><img src="https://avatars1.githubusercontent.com/u/1669439?v=4" alt="ekofedriyanto" title="ekofedriyanto" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/eli-yip"><img src="https://avatars1.githubusercontent.com/u/40079533?v=4" alt="eli-yip" title="eli-yip" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/eljefedelrodeodeljefe"><img src="https://avatars1.githubusercontent.com/u/3899684?v=4" alt="eljefedelrodeodeljefe" title="eljefedelrodeodeljefe" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/fenriz07"><img src="https://avatars1.githubusercontent.com/u/9199380?v=4" alt="fenriz07" title="fenriz07" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/ffelipelimao"><img src="https://avatars1.githubusercontent.com/u/28612817?v=4" alt="ffelipelimao" title="ffelipelimao" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/frenchmajesty"><img src="https://avatars1.githubusercontent.com/u/24761660?v=4" alt="frenchmajesty" title="frenchmajesty" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/gastropulgite"><img src="https://avatars1.githubusercontent.com/u/85067528?v=4" alt="gastropulgite" title="gastropulgite" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/geGao123"><img src="https://avatars1.githubusercontent.com/u/6398228?v=4" alt="geGao123" title="geGao123" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/globalflea"><img src="https://avatars1.githubusercontent.com/u/127675?v=4" alt="globalflea" title="globalflea" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/gloudx"><img src="https://avatars1.githubusercontent.com/u/6920756?v=4" alt="gloudx" title="gloudx" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/gnosthi"><img src="https://avatars1.githubusercontent.com/u/17650528?v=4" alt="gnosthi" title="gnosthi" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/goten002"><img src="https://avatars1.githubusercontent.com/u/5025060?v=4" alt="goten002" title="goten002" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/guanzi008"><img src="https://avatars1.githubusercontent.com/u/20619190?v=4" alt="guanzi008" title="guanzi008" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/kukaki"><img src="https://avatars1.githubusercontent.com/u/4849535?v=4" alt="kukaki" title="kukaki" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/oshirokazuhide"><img src="https://avatars1.githubusercontent.com/u/89958891?v=4" alt="oshirokazuhide" title="oshirokazuhide" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/t6tg"><img src="https://avatars1.githubusercontent.com/u/33445861?v=4" alt="t6tg" title="t6tg" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/15189573255"><img src="https://avatars1.githubusercontent.com/u/18551476?v=4" alt="15189573255" title="15189573255" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/AnatolyUA"><img src="https://avatars1.githubusercontent.com/u/1446703?v=4" alt="AnatolyUA" title="AnatolyUA" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/AwsIT"><img src="https://avatars1.githubusercontent.com/u/40926862?v=4" alt="AwsIT" title="AwsIT" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/BlackHole1"><img src="https://avatars1.githubusercontent.com/u/8198408?v=4" alt="BlackHole1" title="BlackHole1" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/FernandoLangOFC"><img src="https://avatars1.githubusercontent.com/u/84889316?v=4" alt="FernandoLangOFC" title="FernandoLangOFC" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/Flammable-Duck"><img src="https://avatars1.githubusercontent.com/u/59183206?v=4" alt="Flammable-Duck" title="Flammable-Duck" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/Hongjian0619"><img src="https://avatars1.githubusercontent.com/u/25712119?v=4" alt="Hongjian0619" title="Hongjian0619" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/JoeD"><img src="https://avatars1.githubusercontent.com/u/247821?v=4" alt="JoeD" title="JoeD" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/Jude-X"><img src="https://avatars1.githubusercontent.com/u/66228813?v=4" alt="Jude-X" title="Jude-X" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
@@ -341,14 +384,15 @@ With your help, we can improve Open Source web development for everyone!
   <a href="https://github.com/KevinZhouRafael"><img src="https://avatars1.githubusercontent.com/u/16298046?v=4" alt="KevinZhouRafael" title="KevinZhouRafael" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/KrishManohar"><img src="https://avatars1.githubusercontent.com/u/1992857?v=4" alt="KrishManohar" title="KrishManohar" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/Laotanling"><img src="https://avatars1.githubusercontent.com/u/28570289?v=4" alt="Laotanling" title="Laotanling" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/pitexplore"><img src="https://avatars1.githubusercontent.com/u/11956562?v=4" alt="pitexplore" title="pitexplore" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/Longf99999"><img src="https://avatars1.githubusercontent.com/u/21210800?v=4" alt="Longf99999" title="Longf99999" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/Lyansun"><img src="https://avatars1.githubusercontent.com/u/17959642?v=4" alt="Lyansun" title="Lyansun" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/MihaiPopescu1985"><img src="https://avatars1.githubusercontent.com/u/34679869?v=4" alt="MihaiPopescu1985" title="MihaiPopescu1985" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/Mohammed8960"><img src="https://avatars1.githubusercontent.com/u/5219371?v=4" alt="Mohammed8960" title="Mohammed8960" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/NA"><img src="https://avatars1.githubusercontent.com/u/1600?v=4" alt="NA" title="NA" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/Neulhan"><img src="https://avatars1.githubusercontent.com/u/52434903?v=4" alt="Neulhan" title="Neulhan" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/NguyenPhuoc"><img src="https://avatars1.githubusercontent.com/u/11747677?v=4" alt="NguyenPhuoc" title="NguyenPhuoc" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/Oka00"><img src="https://avatars1.githubusercontent.com/u/72302007?v=4" alt="Oka00" title="Oka00" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/PaddyFrenchman"><img src="https://avatars1.githubusercontent.com/u/55139902?v=4" alt="PaddyFrenchman" title="PaddyFrenchman" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/RainerGevers"><img src="https://avatars1.githubusercontent.com/u/32453861?v=4" alt="RainerGevers" title="RainerGevers" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/Ramblestsad"><img src="https://avatars1.githubusercontent.com/u/45003009?v=4" alt="Ramblestsad" title="Ramblestsad" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/SamuelNeves"><img src="https://avatars1.githubusercontent.com/u/10797137?v=4" alt="SamuelNeves" title="SamuelNeves" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
@@ -364,51 +408,24 @@ With your help, we can improve Open Source web development for everyone!
   <a href="https://github.com/agent3bood"><img src="https://avatars1.githubusercontent.com/u/771902?v=4" alt="agent3bood" title="agent3bood" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/alessandromarotta"><img src="https://avatars1.githubusercontent.com/u/17084152?v=4" alt="alessandromarotta" title="alessandromarotta" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/algoflows"><img src="https://avatars1.githubusercontent.com/u/65465380?v=4" alt="algoflows" title="algoflows" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/angelaahhu"><img src="https://avatars1.githubusercontent.com/u/128401549?v=4" alt="angelaahhu" title="angelaahhu" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/anhxuanpham"><img src="https://avatars1.githubusercontent.com/u/101174797?v=4" alt="anhxuanpham" title="anhxuanpham" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/annieruci"><img src="https://avatars1.githubusercontent.com/u/49377699?v=4" alt="annieruci" title="annieruci" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/antoniejiao"><img src="https://avatars1.githubusercontent.com/u/17450960?v=4" alt="antoniejiao" title="antoniejiao" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/artman328"><img src="https://avatars1.githubusercontent.com/u/5415792?v=4" alt="artman328" title="artman328" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/b2cbd"><img src="https://avatars1.githubusercontent.com/u/6870050?v=4" alt="b2cbd" title="b2cbd" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/baoch254"><img src="https://avatars1.githubusercontent.com/u/74555344?v=4" alt="baoch254" title="baoch254" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/bastengao"><img src="https://avatars1.githubusercontent.com/u/785335?v=4" alt="bastengao" title="bastengao" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/bjoroen"><img src="https://avatars1.githubusercontent.com/u/31513139?v=4" alt="bjoroen" title="bjoroen" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/blackHoleNgc1277"><img src="https://avatars1.githubusercontent.com/u/41342763?v=4" alt="blackHoleNgc1277" title="blackHoleNgc1277" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/bunnycodego"><img src="https://avatars1.githubusercontent.com/u/81451316?v=4" alt="bunnycodego" title="bunnycodego" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/carlos-enginner"><img src="https://avatars1.githubusercontent.com/u/59775876?v=4" alt="carlos-enginner" title="carlos-enginner" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/chrisliang12"><img src="https://avatars1.githubusercontent.com/u/97201988?v=4" alt="chrisliang12" title="chrisliang12" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/civicwar"><img src="https://avatars1.githubusercontent.com/u/1858104?v=4" alt="civicwar" title="civicwar" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/cnzhangquan"><img src="https://avatars1.githubusercontent.com/u/5462876?v=4" alt="cnzhangquan" title="cnzhangquan" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/danlanxiaohei"><img src="https://avatars1.githubusercontent.com/u/3272530?v=4" alt="danlanxiaohei" title="danlanxiaohei" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/dfaugusto"><img src="https://avatars1.githubusercontent.com/u/1554920?v=4" alt="dfaugusto" title="dfaugusto" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/dkzhang"><img src="https://avatars1.githubusercontent.com/u/1091431?v=4" alt="dkzhang" title="dkzhang" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/dloprodu"><img src="https://avatars1.githubusercontent.com/u/664947?v=4" alt="dloprodu" title="dloprodu" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/donam-givita"><img src="https://avatars1.githubusercontent.com/u/107529604?v=4" alt="donam-givita" title="donam-givita" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/dph0899"><img src="https://avatars1.githubusercontent.com/u/124650663?v=4" alt="dph0899" title="dph0899" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/ec0629"><img src="https://avatars1.githubusercontent.com/u/7861125?v=4" alt="ec0629" title="ec0629" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/edwindna2"><img src="https://avatars1.githubusercontent.com/u/5441354?v=4" alt="edwindna2" title="edwindna2" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/ekofedriyanto"><img src="https://avatars1.githubusercontent.com/u/1669439?v=4" alt="ekofedriyanto" title="ekofedriyanto" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/fenriz07"><img src="https://avatars1.githubusercontent.com/u/9199380?v=4" alt="fenriz07" title="fenriz07" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/ffelipelimao"><img src="https://avatars1.githubusercontent.com/u/28612817?v=4" alt="ffelipelimao" title="ffelipelimao" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/frenchmajesty"><img src="https://avatars1.githubusercontent.com/u/24761660?v=4" alt="frenchmajesty" title="frenchmajesty" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/gastropulgite"><img src="https://avatars1.githubusercontent.com/u/85067528?v=4" alt="gastropulgite" title="gastropulgite" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/geGao123"><img src="https://avatars1.githubusercontent.com/u/6398228?v=4" alt="geGao123" title="geGao123" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/globalflea"><img src="https://avatars1.githubusercontent.com/u/127675?v=4" alt="globalflea" title="globalflea" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/gnosthi"><img src="https://avatars1.githubusercontent.com/u/17650528?v=4" alt="gnosthi" title="gnosthi" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/goten002"><img src="https://avatars1.githubusercontent.com/u/5025060?v=4" alt="goten002" title="goten002" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/guanzi008"><img src="https://avatars1.githubusercontent.com/u/20619190?v=4" alt="guanzi008" title="guanzi008" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/hdezoscar93"><img src="https://avatars1.githubusercontent.com/u/21270107?v=4" alt="hdezoscar93" title="hdezoscar93" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/hieungm"><img src="https://avatars1.githubusercontent.com/u/85067528?v=4" alt="hieungm" title="hieungm" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/hieunmg"><img src="https://avatars1.githubusercontent.com/u/85067528?v=4" alt="hieunmg" title="hieunmg" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/homerious"><img src="https://avatars1.githubusercontent.com/u/22523525?v=4" alt="homerious" title="homerious" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/CSRaghunandan"><img src="https://avatars1.githubusercontent.com/u/5226809?v=4" alt="CSRaghunandan" title="CSRaghunandan" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/hzxd"><img src="https://avatars1.githubusercontent.com/u/3376231?v=4" alt="hzxd" title="hzxd" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/iuliancarnaru"><img src="https://avatars1.githubusercontent.com/u/35683015?v=4" alt="iuliancarnaru" title="iuliancarnaru" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/iysaleh"><img src="https://avatars1.githubusercontent.com/u/13583253?v=4" alt="iysaleh" title="iysaleh" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/jackptoke"><img src="https://avatars1.githubusercontent.com/u/54049012?v=4" alt="jackptoke" title="jackptoke" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/jackysywk"><img src="https://avatars1.githubusercontent.com/u/61909173?v=4" alt="jackysywk" title="jackysywk" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/jeff2go"><img src="https://avatars1.githubusercontent.com/u/6629280?v=4" alt="jeff2go" title="jeff2go" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/jeremiahyan"><img src="https://avatars1.githubusercontent.com/u/2705359?v=4" alt="jeremiahyan" title="jeremiahyan" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/joelywz"><img src="https://avatars1.githubusercontent.com/u/43310636?v=4" alt="joelywz" title="joelywz" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/kamolcu"><img src="https://avatars1.githubusercontent.com/u/5095235?v=4" alt="kamolcu" title="kamolcu" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/kana99"><img src="https://avatars1.githubusercontent.com/u/3714069?v=4" alt="kana99" title="kana99" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/kattaprasanth"><img src="https://avatars1.githubusercontent.com/u/13375911?v=4" alt="kattaprasanth" title="kattaprasanth" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/keeio"><img src="https://avatars1.githubusercontent.com/u/147525?v=4" alt="keeio" title="keeio" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/GeorgeFourikis"><img src="https://avatars1.githubusercontent.com/u/17906313?v=4" alt="GeorgeFourikis" title="GeorgeFourikis" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/keymanye"><img src="https://avatars1.githubusercontent.com/u/9495010?v=4" alt="keymanye" title="keymanye" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/khasanovrs"><img src="https://avatars1.githubusercontent.com/u/6076966?v=4" alt="khasanovrs" title="khasanovrs" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/kkdaypenny"><img src="https://avatars1.githubusercontent.com/u/47559431?v=4" alt="kkdaypenny" title="kkdaypenny" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
@@ -418,8 +435,13 @@ With your help, we can improve Open Source web development for everyone!
   <a href="https://github.com/kostasvk"><img src="https://avatars1.githubusercontent.com/u/8888490?v=4" alt="kostasvk" title="kostasvk" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/lafayetteDan"><img src="https://avatars1.githubusercontent.com/u/26064396?v=4" alt="lafayetteDan" title="lafayetteDan" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/leki75"><img src="https://avatars1.githubusercontent.com/u/9675379?v=4" alt="leki75" title="leki75" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/L-M-Sherlock"><img src="https://avatars1.githubusercontent.com/u/32575846?v=4" alt="L-M-Sherlock" title="L-M-Sherlock" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/claudemuller"><img src="https://avatars1.githubusercontent.com/u/8104894?v=4" alt="claudemuller" title="claudemuller" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/edsongley"><img src="https://avatars1.githubusercontent.com/u/35545454?v=4" alt="edsongley" title="edsongley" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/lemuelroberto"><img src="https://avatars1.githubusercontent.com/u/322159?v=4" alt="lemuelroberto" title="lemuelroberto" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/liheyuan"><img src="https://avatars1.githubusercontent.com/u/776423?v=4" alt="liheyuan" title="liheyuan" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/lingyingtan"><img src="https://avatars1.githubusercontent.com/u/15610136?v=4" alt="lingyingtan" title="lingyingtan" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/linuxluigi"><img src="https://avatars1.githubusercontent.com/u/8136842?v=4" alt="linuxluigi" title="linuxluigi" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/lipatti"><img src="https://avatars1.githubusercontent.com/u/38935867?v=4" alt="lipatti" title="lipatti" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/maikelcoke"><img src="https://avatars1.githubusercontent.com/u/51384?v=4" alt="maikelcoke" title="maikelcoke" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/marek-kuticka"><img src="https://avatars1.githubusercontent.com/u/1578756?v=4" alt="marek-kuticka" title="marek-kuticka" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
@@ -433,6 +455,8 @@ With your help, we can improve Open Source web development for everyone!
   <a href="https://github.com/mtrense"><img src="https://avatars1.githubusercontent.com/u/1008285?v=4" alt="mtrense" title="mtrense" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/mukunhao"><img src="https://avatars1.githubusercontent.com/u/45845255?v=4" alt="mukunhao" title="mukunhao" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/mulyawansentosa"><img src="https://avatars1.githubusercontent.com/u/29946673?v=4" alt="mulyawansentosa" title="mulyawansentosa" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/evan"><img src="https://avatars1.githubusercontent.com/u/210?v=4" alt="evan" title="evan" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/grassshrimp"><img src="https://avatars1.githubusercontent.com/u/3070576?v=4" alt="grassshrimp" title="grassshrimp" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/nasoma"><img src="https://avatars1.githubusercontent.com/u/19878418?v=4" alt="nasoma" title="nasoma" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/ngseiyu"><img src="https://avatars1.githubusercontent.com/u/44496936?v=4" alt="ngseiyu" title="ngseiyu" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/nikharsaxena"><img src="https://avatars1.githubusercontent.com/u/8684362?v=4" alt="nikharsaxena" title="nikharsaxena" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
@@ -441,9 +465,9 @@ With your help, we can improve Open Source web development for everyone!
   <a href="https://github.com/ozfive"><img src="https://avatars1.githubusercontent.com/u/4494266?v=4" alt="ozfive" title="ozfive" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/paulxu21"><img src="https://avatars1.githubusercontent.com/u/6261758?v=4" alt="paulxu21" title="paulxu21" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/pesquive"><img src="https://avatars1.githubusercontent.com/u/6610140?v=4" alt="pesquive" title="pesquive" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/petros9282"><img src="https://avatars1.githubusercontent.com/u/3861890?v=4" alt="petros9282" title="petros9282" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/phil535"><img src="https://avatars1.githubusercontent.com/u/7596830?v=4" alt="phil535" title="phil535" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/pitt134"><img src="https://avatars1.githubusercontent.com/u/13091629?v=4" alt="pitt134" title="pitt134" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/pookiepats"><img src="https://avatars1.githubusercontent.com/u/57677891?v=4" alt="pookiepats" title="pookiepats" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/qiepeipei"><img src="https://avatars1.githubusercontent.com/u/16110628?v=4" alt="qiepeipei" title="qiepeipei" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/qiuzhanghua"><img src="https://avatars1.githubusercontent.com/u/478393?v=4" alt="qiuzhanghua" title="qiuzhanghua" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/rapita"><img src="https://avatars1.githubusercontent.com/u/22305375?v=4" alt="rapita" title="rapita" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
@@ -452,16 +476,14 @@ With your help, we can improve Open Source web development for everyone!
   <a href="https://github.com/remopavithran"><img src="https://avatars1.githubusercontent.com/u/50388068?v=4" alt="remopavithran" title="remopavithran" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/rfunix"><img src="https://avatars1.githubusercontent.com/u/6026357?v=4" alt="rfunix" title="rfunix" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/rhernandez-itemsoft"><img src="https://avatars1.githubusercontent.com/u/4327356?v=4" alt="rhernandez-itemsoft" title="rhernandez-itemsoft" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/opusmagna"><img src="https://avatars1.githubusercontent.com/u/33766678?v=4" alt="opusmagna" title="opusmagna" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/b4zz4r"><img src="https://avatars1.githubusercontent.com/u/7438782?v=4" alt="b4zz4r" title="b4zz4r" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/bobmcallan"><img src="https://avatars1.githubusercontent.com/u/8773580?v=4" alt="bobmcallan" title="bobmcallan" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/fangli"><img src="https://avatars1.githubusercontent.com/u/3032639?v=4" alt="fangli" title="fangli" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/galois-tnp"><img src="https://avatars1.githubusercontent.com/u/41128011?v=4" alt="galois-tnp" title="galois-tnp" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/geoshan"><img src="https://avatars1.githubusercontent.com/u/10161131?v=4" alt="geoshan" title="geoshan" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/juanxme"><img src="https://avatars1.githubusercontent.com/u/661043?v=4" alt="juanxme" title="juanxme" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/nguyentamvinhlong"><img src="https://avatars1.githubusercontent.com/u/1875916?v=4" alt="nguyentamvinhlong" title="nguyentamvinhlong" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/rikoriswandha"><img src="https://avatars1.githubusercontent.com/u/2549929?v=4" alt="rikoriswandha" title="rikoriswandha" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/hazmi-e205"><img src="https://avatars1.githubusercontent.com/u/12555465?v=4" alt="hazmi-e205" title="hazmi-e205" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/jtgoral"><img src="https://avatars1.githubusercontent.com/u/19780595?v=4" alt="jtgoral" title="jtgoral" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/ky2s"><img src="https://avatars1.githubusercontent.com/u/19502125?v=4" alt="ky2s" title="ky2s" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/lauweliam"><img src="https://avatars1.githubusercontent.com/u/4064517?v=4" alt="lauweliam" title="lauweliam" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/risallaw"><img src="https://avatars1.githubusercontent.com/u/15353146?v=4" alt="risallaw" title="risallaw" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/robivictor"><img src="https://avatars1.githubusercontent.com/u/761041?v=4" alt="robivictor" title="robivictor" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/rubiagatra"><img src="https://avatars1.githubusercontent.com/u/7299491?v=4" alt="rubiagatra" title="rubiagatra" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/rxrw"><img src="https://avatars1.githubusercontent.com/u/9566402?v=4" alt="rxrw" title="rxrw" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/saleebm"><img src="https://avatars1.githubusercontent.com/u/34875122?v=4" alt="saleebm" title="saleebm" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/sbenimeli"><img src="https://avatars1.githubusercontent.com/u/46652122?v=4" alt="sbenimeli" title="sbenimeli" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
@@ -471,6 +493,7 @@ With your help, we can improve Open Source web development for everyone!
   <a href="https://github.com/su1gen"><img src="https://avatars1.githubusercontent.com/u/86298730?v=4" alt="su1gen" title="su1gen" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/sukiejosh"><img src="https://avatars1.githubusercontent.com/u/44656210?v=4" alt="sukiejosh" title="sukiejosh" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/svirmi"><img src="https://avatars1.githubusercontent.com/u/52601346?v=4" alt="svirmi" title="svirmi" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/terjelafton"><img src="https://avatars1.githubusercontent.com/u/12574755?v=4" alt="terjelafton" title="terjelafton" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/thiennguyen93"><img src="https://avatars1.githubusercontent.com/u/60094052?v=4" alt="thiennguyen93" title="thiennguyen93" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/unixedia"><img src="https://avatars1.githubusercontent.com/u/70646128?v=4" alt="unixedia" title="unixedia" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/vadgun"><img src="https://avatars1.githubusercontent.com/u/22282464?v=4" alt="vadgun" title="vadgun" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
@@ -481,13 +504,17 @@ With your help, we can improve Open Source web development for everyone!
   <a href="https://github.com/vuhoanglam"><img src="https://avatars1.githubusercontent.com/u/59502855?v=4" alt="vuhoanglam" title="vuhoanglam" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/walter-wang"><img src="https://avatars1.githubusercontent.com/u/7950295?v=4" alt="walter-wang" title="walter-wang" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/wixregiga"><img src="https://avatars1.githubusercontent.com/u/30182903?v=4" alt="wixregiga" title="wixregiga" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/xPoppa"><img src="https://avatars1.githubusercontent.com/u/119574198?v=4" alt="xPoppa" title="xPoppa" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/yesudeep"><img src="https://avatars1.githubusercontent.com/u/3874?v=4" alt="yesudeep" title="yesudeep" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/ymonk"><img src="https://avatars1.githubusercontent.com/u/13493968?v=4" alt="ymonk" title="ymonk" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/yonson2"><img src="https://avatars1.githubusercontent.com/u/1192599?v=4" alt="yonson2" title="yonson2" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/yusong-offx"><img src="https://avatars1.githubusercontent.com/u/75306828?v=4" alt="yusong-offx" title="yusong-offx" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/zhenggangpku"><img src="https://avatars1.githubusercontent.com/u/18161030?v=4" alt="zhenggangpku" title="zhenggangpku" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/SergeShin"><img src="https://avatars1.githubusercontent.com/u/402395?v=4" alt="SergeShin" title="SergeShin" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/-"><img src="https://avatars1.githubusercontent.com/u/75544?v=4" alt="-" title="-" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/BelmonduS"><img src="https://avatars1.githubusercontent.com/u/159350?v=4" alt="BelmonduS" title="BelmonduS" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/Diewald"><img src="https://avatars1.githubusercontent.com/u/6187336?v=4" alt="Diewald" title="Diewald" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/cty4ka"><img src="https://avatars1.githubusercontent.com/u/29261879?v=4" alt="cty4ka" title="cty4ka" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/martinjanda"><img src="https://avatars1.githubusercontent.com/u/122393?v=4" alt="martinjanda" title="martinjanda" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/martinlindhe"><img src="https://avatars1.githubusercontent.com/u/181531?v=4" alt="martinlindhe" title="martinlindhe" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/mdamschen"><img src="https://avatars1.githubusercontent.com/u/40914728?v=4" alt="mdamschen" title="mdamschen" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
@@ -510,37 +537,38 @@ With your help, we can improve Open Source web development for everyone!
   <a href="https://github.com/statik"><img src="https://avatars1.githubusercontent.com/u/983?v=4" alt="statik" title="statik" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/supersherm5"><img src="https://avatars1.githubusercontent.com/u/7953550?v=4" alt="supersherm5" title="supersherm5" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/thejones"><img src="https://avatars1.githubusercontent.com/u/682850?v=4" alt="thejones" title="thejones" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/CSRaghunandan"><img src="https://avatars1.githubusercontent.com/u/5226809?v=4" alt="CSRaghunandan" title="CSRaghunandan" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/GeorgeFourikis"><img src="https://avatars1.githubusercontent.com/u/17906313?v=4" alt="GeorgeFourikis" title="GeorgeFourikis" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/L-M-Sherlock"><img src="https://avatars1.githubusercontent.com/u/32575846?v=4" alt="L-M-Sherlock" title="L-M-Sherlock" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/claudemuller"><img src="https://avatars1.githubusercontent.com/u/8104894?v=4" alt="claudemuller" title="claudemuller" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/edsongley"><img src="https://avatars1.githubusercontent.com/u/35545454?v=4" alt="edsongley" title="edsongley" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/vcruzato"><img src="https://avatars1.githubusercontent.com/u/3864151?v=4" alt="vcruzato" title="vcruzato" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/evan"><img src="https://avatars1.githubusercontent.com/u/210?v=4" alt="evan" title="evan" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/grassshrimp"><img src="https://avatars1.githubusercontent.com/u/3070576?v=4" alt="grassshrimp" title="grassshrimp" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/hazmi-e205"><img src="https://avatars1.githubusercontent.com/u/12555465?v=4" alt="hazmi-e205" title="hazmi-e205" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/jtgoral"><img src="https://avatars1.githubusercontent.com/u/19780595?v=4" alt="jtgoral" title="jtgoral" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/ky2s"><img src="https://avatars1.githubusercontent.com/u/19502125?v=4" alt="ky2s" title="ky2s" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
-  <a href="https://github.com/lauweliam"><img src="https://avatars1.githubusercontent.com/u/4064517?v=4" alt="lauweliam" title="lauweliam" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/letmestudy"><img src="https://avatars1.githubusercontent.com/u/31943708?v=4" alt="letmestudy" title="letmestudy" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/mblandr"><img src="https://avatars1.githubusercontent.com/u/42862020?v=4" alt="mblandr" title="mblandr" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/midhubalan"><img src="https://avatars1.githubusercontent.com/u/13059634?v=4" alt="midhubalan" title="midhubalan" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/ndimorle"><img src="https://avatars1.githubusercontent.com/u/76732415?v=4" alt="ndimorle" title="ndimorle" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/rosales-stephanie"><img src="https://avatars1.githubusercontent.com/u/43592017?v=4" alt="rosales-stephanie" title="rosales-stephanie" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/shyyawn"><img src="https://avatars1.githubusercontent.com/u/6064438?v=4" alt="shyyawn" title="shyyawn" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/vcruzato"><img src="https://avatars1.githubusercontent.com/u/3864151?v=4" alt="vcruzato" title="vcruzato" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/wangbl11"><img src="https://avatars1.githubusercontent.com/u/14358532?v=4" alt="wangbl11" title="wangbl11" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/wofka72"><img src="https://avatars1.githubusercontent.com/u/10855340?v=4" alt="wofka72" title="wofka72" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/yoru74"><img src="https://avatars1.githubusercontent.com/u/7745866?v=4" alt="yoru74" title="yoru74" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/xsokev"><img src="https://avatars1.githubusercontent.com/u/28113?v=4" alt="xsokev" title="xsokev" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/oleang"><img src="https://avatars1.githubusercontent.com/u/142615?v=4" alt="oleang" title="oleang" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/michalsz"><img src="https://avatars1.githubusercontent.com/u/187477?v=4" alt="michalsz" title="michalsz" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/michaelsmanley"><img src="https://avatars1.githubusercontent.com/u/93241?v=4" alt="michaelsmanley" title="michaelsmanley" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/Curtman"><img src="https://avatars1.githubusercontent.com/u/543481?v=4" alt="Curtman" title="Curtman" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/SridarDhandapani"><img src="https://avatars1.githubusercontent.com/u/18103118?v=4" alt="SridarDhandapani" title="SridarDhandapani" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/opusmagna"><img src="https://avatars1.githubusercontent.com/u/33766678?v=4" alt="opusmagna" title="opusmagna" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/ShahramMebashar"><img src="https://avatars1.githubusercontent.com/u/25268287?v=4" alt="ShahramMebashar" title="ShahramMebashar" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/b4zz4r"><img src="https://avatars1.githubusercontent.com/u/7438782?v=4" alt="b4zz4r" title="b4zz4r" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/bobmcallan"><img src="https://avatars1.githubusercontent.com/u/8773580?v=4" alt="bobmcallan" title="bobmcallan" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/fangli"><img src="https://avatars1.githubusercontent.com/u/3032639?v=4" alt="fangli" title="fangli" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/galois-tnp"><img src="https://avatars1.githubusercontent.com/u/41128011?v=4" alt="galois-tnp" title="galois-tnp" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/geoshan"><img src="https://avatars1.githubusercontent.com/u/10161131?v=4" alt="geoshan" title="geoshan" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/juanxme"><img src="https://avatars1.githubusercontent.com/u/661043?v=4" alt="juanxme" title="juanxme" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/nguyentamvinhlong"><img src="https://avatars1.githubusercontent.com/u/1875916?v=4" alt="nguyentamvinhlong" title="nguyentamvinhlong" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/pomland-94"><img src="https://avatars1.githubusercontent.com/u/96850116?v=4" alt="pomland-94" title="pomland-94" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/tejzpr"><img src="https://avatars1.githubusercontent.com/u/2813811?v=4" alt="tejzpr" title="tejzpr" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/theantichris"><img src="https://avatars1.githubusercontent.com/u/1486502?v=4" alt="theantichris" title="theantichris" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/tuxaanand"><img src="https://avatars1.githubusercontent.com/u/9750371?v=4" alt="tuxaanand" title="tuxaanand" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/raphael-brand"><img src="https://avatars1.githubusercontent.com/u/4279168?v=4" alt="raphael-brand" title="raphael-brand" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/willypuzzle"><img src="https://avatars1.githubusercontent.com/u/18305386?v=4" alt="willypuzzle" title="willypuzzle" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
+  <a href="https://github.com/malcolm-white-dti"><img src="https://avatars1.githubusercontent.com/u/109724322?v=4" alt="malcolm-white-dti" title="malcolm-white-dti" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/HieuLsw"><img src="https://avatars1.githubusercontent.com/u/1675478?v=4" alt="HieuLsw" title="HieuLsw" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/carlosmoran092"><img src="https://avatars1.githubusercontent.com/u/10361754?v=4" alt="carlosmoran092" title="carlosmoran092" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
   <a href="https://github.com/yangxianglong"><img src="https://avatars1.githubusercontent.com/u/55280276?v=4" alt="yangxianglong" title="yangxianglong" width="75" height="75" style="width:75px;max-width:75px;height:75px" /></a>
@@ -558,7 +586,7 @@ The only requirement is the [Go Programming Language](https://go.dev/dl/).
 $ mkdir myapp
 $ cd myapp
 $ go mod init myapp
-$ go get github.com/kataras/iris/v12@latest # or @v12.2.8
+$ go get github.com/kataras/iris/v12@latest # or @v
 ```
 
 <details><summary>Install on existing project</summary>
@@ -571,7 +599,7 @@ $ go get github.com/kataras/iris/v12@latest
 **Run**
 
 ```sh
-$ go mod tidy -compat=1.20 # -compat="1.20" for windows.
+$ go mod tidy -compat=1.21 # -compat="1.21" for windows.
 $ go run .
 ```
 

+ 2 - 2
vendor/github.com/kataras/iris/v12/README_ES.md

@@ -1,6 +1,6 @@
 # Iris Web Framework
 
-[![build status](https://img.shields.io/github/actions/workflow/status/kataras/iris/ci.yml?branch=main&style=for-the-badge)](https://github.com/kataras/iris/actions/workflows/ci.yml) [![FOSSA Status](https://img.shields.io/badge/LICENSE%20SCAN-PASSING❤️-CD2956?style=for-the-badge&logo=fossa)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkataras%2Firis?ref=badge_shield)<!--[![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)--><!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://pkg.go.dev/github.com/kataras/iris/v12@v12.2.8)--> [![view examples](https://img.shields.io/badge/learn%20by-examples-0C8EC5.svg?style=for-the-badge&logo=go)](https://github.com/kataras/iris/tree/main/_examples) [![chat](https://img.shields.io/gitter/room/iris_go/community.svg?color=7E18DD&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community)<!--[![donate on PayPal](https://img.shields.io/badge/support-PayPal-blue.svg?style=for-the-badge)](https://iris-go.com/donate)--><!-- [![release](https://img.shields.io/badge/release%20-v12.0-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases) -->
+[![build status](https://img.shields.io/github/actions/workflow/status/kataras/iris/ci.yml?branch=main&style=for-the-badge)](https://github.com/kataras/iris/actions/workflows/ci.yml) [![FOSSA Status](https://img.shields.io/badge/LICENSE%20SCAN-PASSING❤️-CD2956?style=for-the-badge&logo=fossa)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkataras%2Firis?ref=badge_shield)<!--[![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)--><!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://pkg.go.dev/github.com/kataras/iris/v12@v12.2.10)--> [![view examples](https://img.shields.io/badge/learn%20by-examples-0C8EC5.svg?style=for-the-badge&logo=go)](https://github.com/kataras/iris/tree/main/_examples) [![chat](https://img.shields.io/gitter/room/iris_go/community.svg?color=7E18DD&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community)<!--[![donate on PayPal](https://img.shields.io/badge/support-PayPal-blue.svg?style=for-the-badge)](https://iris-go.com/donate)--><!-- [![release](https://img.shields.io/badge/release%20-v12.0-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases) -->
 
 Iris es un framework web rápido, simple pero con muchas funcionalidades y muy eficiente para Go. Proporciona una base bellamente expresiva y fácil de usar para su próximo sitio web o API.
 
@@ -49,7 +49,7 @@ $ go run ejemplo.go
 
 Iris contiene un extenso y completo **[wiki](https://www.iris-go.com/#ebookDonateForm)** que facilita comenzar con el framework.
 
-Para obtener una documentación técnica más detallada, puede dirigirse a nuestros [godocs](https://pkg.go.dev/github.com/kataras/iris/v12@v12.2.8). Y para código ejecutable siempre puede visitar el subdirectorio del repositorio [\_examples](_examples/).
+Para obtener una documentación técnica más detallada, puede dirigirse a nuestros [godocs](https://pkg.go.dev/github.com/kataras/iris/v12@v). Y para código ejecutable siempre puede visitar el subdirectorio del repositorio [\_examples](_examples/).
 
 ### ¿Te gusta leer mientras viajas?
 

+ 2 - 2
vendor/github.com/kataras/iris/v12/README_FA.md

@@ -10,7 +10,7 @@
 
 # Iris Web Framework
     
-[![build status](https://img.shields.io/github/actions/workflow/status/kataras/iris/ci.yml?branch=main&style=for-the-badge)](https://github.com/kataras/iris/actions/workflows/ci.yml) [![FOSSA Status](https://img.shields.io/badge/LICENSE%20SCAN-PASSING❤️-CD2956?style=for-the-badge&logo=fossa)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkataras%2Firis?ref=badge_shield)<!--[![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)--><!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://pkg.go.dev/github.com/kataras/iris/v12@v12.2.8)--> [![view examples](https://img.shields.io/badge/learn%20by-examples-0C8EC5.svg?style=for-the-badge&logo=go)](https://github.com/kataras/iris/tree/main/_examples) [![chat](https://img.shields.io/gitter/room/iris_go/community.svg?color=7E18DD&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community)<!--[![donate on PayPal](https://img.shields.io/badge/support-PayPal-blue.svg?style=for-the-badge)](https://iris-go.com/donate)--><!-- [![release](https://img.shields.io/badge/release%20-v12.0-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases) -->
+[![build status](https://img.shields.io/github/actions/workflow/status/kataras/iris/ci.yml?branch=main&style=for-the-badge)](https://github.com/kataras/iris/actions/workflows/ci.yml) [![FOSSA Status](https://img.shields.io/badge/LICENSE%20SCAN-PASSING❤️-CD2956?style=for-the-badge&logo=fossa)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkataras%2Firis?ref=badge_shield)<!--[![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)--><!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://pkg.go.dev/github.com/kataras/iris/v12@v)--> [![view examples](https://img.shields.io/badge/learn%20by-examples-0C8EC5.svg?style=for-the-badge&logo=go)](https://github.com/kataras/iris/tree/main/_examples) [![chat](https://img.shields.io/gitter/room/iris_go/community.svg?color=7E18DD&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community)<!--[![donate on PayPal](https://img.shields.io/badge/support-PayPal-blue.svg?style=for-the-badge)](https://iris-go.com/donate)--><!-- [![release](https://img.shields.io/badge/release%20-v12.0-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases) -->
     
 آیریس یک چارچوب وب پر سرعت ، ساده و در عین حال کاملاً برجسته و بسیار کارآمد برای Go است.
 </div>
@@ -137,7 +137,7 @@ func (c *userController) PutBy(id uint64, req request) response {
 $ mkdir myapp
 $ cd myapp
 $ go mod init myapp
-$ go get github.com/kataras/iris/v12@latest # or @v12.2.8
+$ go get github.com/kataras/iris/v12@latest # or @v
 ```
 
 <div dir="rtl">

+ 2 - 2
vendor/github.com/kataras/iris/v12/README_FR.md

@@ -1,6 +1,6 @@
 # Iris Web Framework
 
-[![build status](https://img.shields.io/github/actions/workflow/status/kataras/iris/ci.yml?branch=main&style=for-the-badge)](https://github.com/kataras/iris/actions/workflows/ci.yml) [![FOSSA Status](https://img.shields.io/badge/LICENSE%20SCAN-PASSING❤️-CD2956?style=for-the-badge&logo=fossa)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkataras%2Firis?ref=badge_shield)<!--[![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)--><!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://pkg.go.dev/github.com/kataras/iris/v12@v12.2.8)--> [![view examples](https://img.shields.io/badge/learn%20by-examples-0C8EC5.svg?style=for-the-badge&logo=go)](https://github.com/kataras/iris/tree/main/_examples) [![chat](https://img.shields.io/gitter/room/iris_go/community.svg?color=7E18DD&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community)<!--[![donate on PayPal](https://img.shields.io/badge/support-PayPal-blue.svg?style=for-the-badge)](https://iris-go.com/donate)--><!-- [![release](https://img.shields.io/badge/release%20-v12.0-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases) -->
+[![build status](https://img.shields.io/github/actions/workflow/status/kataras/iris/ci.yml?branch=main&style=for-the-badge)](https://github.com/kataras/iris/actions/workflows/ci.yml) [![FOSSA Status](https://img.shields.io/badge/LICENSE%20SCAN-PASSING❤️-CD2956?style=for-the-badge&logo=fossa)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkataras%2Firis?ref=badge_shield)<!--[![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)--><!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://pkg.go.dev/github.com/kataras/iris/v12@v)--> [![view examples](https://img.shields.io/badge/learn%20by-examples-0C8EC5.svg?style=for-the-badge&logo=go)](https://github.com/kataras/iris/tree/main/_examples) [![chat](https://img.shields.io/gitter/room/iris_go/community.svg?color=7E18DD&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community)<!--[![donate on PayPal](https://img.shields.io/badge/support-PayPal-blue.svg?style=for-the-badge)](https://iris-go.com/donate)--><!-- [![release](https://img.shields.io/badge/release%20-v12.0-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases) -->
 
 <a href="https://iris-go.com"> <img align="right" src="https://iris-go.com/images/logo-w169.png"></a>
 
@@ -57,7 +57,7 @@ Iris possède un **[wiki](https://www.iris-go.com/#ebookDonateForm)** complet et
 
 <!-- ![](https://media.giphy.com/media/Ur8iqy9FQfmPuyQpgy/giphy.gif) -->
 
-Pour une documentation encore plus complète vous pouvez visiter notre [godocs](https://pkg.go.dev/github.com/kataras/iris/v12@v12.2.8) (en Anglais). Et vous trouverez du code executable dans le dossier [\_examples](_examples/).
+Pour une documentation encore plus complète vous pouvez visiter notre [godocs](https://pkg.go.dev/github.com/kataras/iris/v12@v) (en Anglais). Et vous trouverez du code executable dans le dossier [\_examples](_examples/).
 
 ### Vous préférez une version PDF?
 

+ 2 - 2
vendor/github.com/kataras/iris/v12/README_GR.md

@@ -1,6 +1,6 @@
 # Iris Web Framework
 
-[![build status](https://img.shields.io/github/actions/workflow/status/kataras/iris/ci.yml?branch=main&style=for-the-badge)](https://github.com/kataras/iris/actions/workflows/ci.yml) [![FOSSA Status](https://img.shields.io/badge/LICENSE%20SCAN-PASSING❤️-CD2956?style=for-the-badge&logo=fossa)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkataras%2Firis?ref=badge_shield)<!--[![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)--><!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://pkg.go.dev/github.com/kataras/iris/v12@v12.2.8)--> [![view examples](https://img.shields.io/badge/learn%20by-examples-0C8EC5.svg?style=for-the-badge&logo=go)](https://github.com/kataras/iris/tree/main/_examples) [![chat](https://img.shields.io/gitter/room/iris_go/community.svg?color=7E18DD&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community)<!--[![donate on PayPal](https://img.shields.io/badge/support-PayPal-blue.svg?style=for-the-badge)](https://iris-go.com/donate)--><!-- [![release](https://img.shields.io/badge/release%20-v12.0-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases) -->
+[![build status](https://img.shields.io/github/actions/workflow/status/kataras/iris/ci.yml?branch=main&style=for-the-badge)](https://github.com/kataras/iris/actions/workflows/ci.yml) [![FOSSA Status](https://img.shields.io/badge/LICENSE%20SCAN-PASSING❤️-CD2956?style=for-the-badge&logo=fossa)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkataras%2Firis?ref=badge_shield)<!--[![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)--><!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://pkg.go.dev/github.com/kataras/iris/v12@v)--> [![view examples](https://img.shields.io/badge/learn%20by-examples-0C8EC5.svg?style=for-the-badge&logo=go)](https://github.com/kataras/iris/tree/main/_examples) [![chat](https://img.shields.io/gitter/room/iris_go/community.svg?color=7E18DD&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community)<!--[![donate on PayPal](https://img.shields.io/badge/support-PayPal-blue.svg?style=for-the-badge)](https://iris-go.com/donate)--><!-- [![release](https://img.shields.io/badge/release%20-v12.0-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases) -->
 
 Το Iris είναι ένα γρήγορο, απλό αλλά και πλήρως λειτουργικό και πολύ αποδοτικό web framework για τη Go γλώσσα προγραμματισμού. Παρέχει ένα εκφραστικό και εύχρηστο υπόβαθρο για την επόμενη ιστοσελίδα σας.
 
@@ -53,7 +53,7 @@ $ go run example.go
 
 Το Iris περιέχει εκτενείς και λεπτομερείς **[book](https://www.iris-go.com/#ebookDonateForm)** καθιστώντας το εύκολο στην εκμάθηση.
 
-Για λεπτομερέστερη τεχνική τεκμηρίωση μπορείτε να κατευθυνθείτε προς τα [godocs](https://pkg.go.dev/github.com/kataras/iris/v12@v12.2.8) μας. Και για εκτελέσιμο κώδικα μπορείτε πάντα να επισκέπτεστε τα [παραδείγματα](_examples/).
+Για λεπτομερέστερη τεχνική τεκμηρίωση μπορείτε να κατευθυνθείτε προς τα [godocs](https://pkg.go.dev/github.com/kataras/iris/v12@v) μας. Και για εκτελέσιμο κώδικα μπορείτε πάντα να επισκέπτεστε τα [παραδείγματα](_examples/).
 
 ### Σας αρέσει να διαβάζετε ενώ ταξιδεύετε;
 

+ 2 - 2
vendor/github.com/kataras/iris/v12/README_JA.md

@@ -6,7 +6,7 @@ Try the official [Iris Command Line Interface](https://github.com/kataras/iris-c
 
 # <a href="https://iris-go.com"><img src="https://iris-go.com/images/logo-new-lq-45.png"></a> Iris Web Framework <a href="README_GR.md"><img width="20px" src="https://iris-go.com/images/flag-greece.svg" /></a> <a href="README_FR.md"><img width="20px" src="https://iris-go.com/images/flag-france.svg" /></a> <a href="README_ZH_HANT.md"><img width="20px" src="https://iris-go.com/images/flag-taiwan.svg" /></a> <a href="README_ZH_HANS.md"><img width="20px" src="https://iris-go.com/images/flag-china.svg" /></a> <a href="README_ES.md"><img width="20px" src="https://iris-go.com/images/flag-spain.png" /></a> <a href="README_FA.md"><img width="20px" src="https://iris-go.com/images/flag-iran.svg" /></a> <a href="README_RU.md"><img width="20px" src="https://iris-go.com/images/flag-russia.svg" /></a> <a href="README_KO.md"><img width="20px" src="https://iris-go.com/images/flag-south-korea.svg?v=12" /></a> <a href="README_PT_BR.md"><img width="20px" height="20px" src="https://iris-go.com/images/flag-brazil.svg" /></a> <a href="README_JA.md"><img width="20px" height="20px" src="https://iris-go.com/images/flag-japan.svg" /></a>
 
-[![build status](https://img.shields.io/github/actions/workflow/status/kataras/iris/ci.yml?branch=main&style=for-the-badge)](https://github.com/kataras/iris/actions/workflows/ci.yml) [![view examples](https://img.shields.io/badge/examples%20-285-a83adf.svg?style=for-the-badge&logo=go)](https://github.com/kataras/iris/tree/main/_examples) [![chat](https://img.shields.io/gitter/room/iris_go/community.svg?color=cc2b5e&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community) <!--[![FOSSA Status](https://img.shields.io/badge/LICENSE%20SCAN-PASSING❤️-CD2956?style=for-the-badge&logo=fossa)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkataras%2Firis?ref=badge_shield)--> [![donate](https://img.shields.io/badge/support-Iris-blue.svg?style=for-the-badge&logo=paypal)](https://iris-go.com/donate) <!--[![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)--><!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://pkg.go.dev/github.com/kataras/iris/v12@v12.2.8)--> <!-- [![release](https://img.shields.io/badge/release%20-v12.0-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases) -->
+[![build status](https://img.shields.io/github/actions/workflow/status/kataras/iris/ci.yml?branch=main&style=for-the-badge)](https://github.com/kataras/iris/actions/workflows/ci.yml) [![view examples](https://img.shields.io/badge/examples%20-285-a83adf.svg?style=for-the-badge&logo=go)](https://github.com/kataras/iris/tree/main/_examples) [![chat](https://img.shields.io/gitter/room/iris_go/community.svg?color=cc2b5e&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community) <!--[![FOSSA Status](https://img.shields.io/badge/LICENSE%20SCAN-PASSING❤️-CD2956?style=for-the-badge&logo=fossa)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkataras%2Firis?ref=badge_shield)--> [![donate](https://img.shields.io/badge/support-Iris-blue.svg?style=for-the-badge&logo=paypal)](https://iris-go.com/donate) <!--[![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)--><!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://pkg.go.dev/github.com/kataras/iris/v12@v)--> <!-- [![release](https://img.shields.io/badge/release%20-v12.0-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases) -->
 
 Irisは、高速でシンプルでありながら、十分な機能を備えた、非常に効率的なGo用Webフレームワークです。
 
@@ -219,7 +219,7 @@ Irisが提供する機能の一部:
 $ mkdir myapp
 $ cd myapp
 $ go mod init myapp
-$ go get github.com/kataras/iris/v12@latest # or @v12.2.8
+$ go get github.com/kataras/iris/v12@latest # or @v
 ```
 
 <details><summary>既存のプロジェクトにインストールする場合</summary>

+ 2 - 2
vendor/github.com/kataras/iris/v12/README_KO.md

@@ -1,6 +1,6 @@
 # Iris Web Framework
 
-[![build status](https://img.shields.io/github/actions/workflow/status/kataras/iris/ci.yml?branch=main&style=for-the-badge)](https://github.com/kataras/iris/actions/workflows/ci.yml) [![FOSSA Status](https://img.shields.io/badge/LICENSE%20SCAN-PASSING❤️-CD2956?style=for-the-badge&logo=fossa)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkataras%2Firis?ref=badge_shield)<!--[![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)--><!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://pkg.go.dev/github.com/kataras/iris/v12@v12.2.8)--> [![view examples](https://img.shields.io/badge/learn%20by-examples-0C8EC5.svg?style=for-the-badge&logo=go)](https://github.com/kataras/iris/tree/main/_examples) [![chat](https://img.shields.io/gitter/room/iris_go/community.svg?color=7E18DD&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community)<!--[![donate on PayPal](https://img.shields.io/badge/support-PayPal-blue.svg?style=for-the-badge)](https://iris-go.com/donate)--><!-- [![release](https://img.shields.io/badge/release%20-v12.0-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases) -->
+[![build status](https://img.shields.io/github/actions/workflow/status/kataras/iris/ci.yml?branch=main&style=for-the-badge)](https://github.com/kataras/iris/actions/workflows/ci.yml) [![FOSSA Status](https://img.shields.io/badge/LICENSE%20SCAN-PASSING❤️-CD2956?style=for-the-badge&logo=fossa)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkataras%2Firis?ref=badge_shield)<!--[![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)--><!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://pkg.go.dev/github.com/kataras/iris/v12@v)--> [![view examples](https://img.shields.io/badge/learn%20by-examples-0C8EC5.svg?style=for-the-badge&logo=go)](https://github.com/kataras/iris/tree/main/_examples) [![chat](https://img.shields.io/gitter/room/iris_go/community.svg?color=7E18DD&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community)<!--[![donate on PayPal](https://img.shields.io/badge/support-PayPal-blue.svg?style=for-the-badge)](https://iris-go.com/donate)--><!-- [![release](https://img.shields.io/badge/release%20-v12.0-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases) -->
 
 Iris는 단순하고 빠르며 좋은 성능과 모든 기능을 갖춘 Go언어용 웹 프레임워크입니다. 당신의 웹사이트나 API를 위해서 아름답고 사용하기 쉬운 기반을 제공합니다.
 
@@ -49,7 +49,7 @@ $ go run example.go
 
 Iris는 광범위하고 꼼꼼한 **[wiki](https://www.iris-go.com/#ebookDonateForm)** 를 가지고 있기 때문에 쉽게 프레임워크를 시작할 수 있습니다.
 
-더 자세한 기술문서를 보시려면 [godocs](https://pkg.go.dev/github.com/kataras/iris/v12@v12.2.8)를 방문하세요. 그리고 실행가능한 예제코드는 [\_examples](_examples/) 하위 디렉토리에 있습니다.
+더 자세한 기술문서를 보시려면 [godocs](https://pkg.go.dev/github.com/kataras/iris/v12@v)를 방문하세요. 그리고 실행가능한 예제코드는 [\_examples](_examples/) 하위 디렉토리에 있습니다.
 
 ### 여행하면서 독서를 즐기세요?
 

+ 2 - 2
vendor/github.com/kataras/iris/v12/README_PT_BR.md

@@ -2,7 +2,7 @@
 
 # Iris Web Framework <a href="README_GR.md"><img width="20px" src="https://iris-go.com/images/flag-greece.svg" /></a> <a href="README_FR.md"><img width="20px" src="https://iris-go.com/images/flag-france.svg" /></a> <a href="README_ZH.md"><img width="20px" src="https://iris-go.com/images/flag-china.svg" /></a> <a href="README_ES.md"><img width="20px" src="https://iris-go.com/images/flag-spain.png" /></a> <a href="README_FA.md"><img width="20px" src="https://iris-go.com/images/flag-iran.svg" /></a> <a href="README_RU.md"><img width="20px" src="https://iris-go.com/images/flag-russia.svg" /></a> <a href="README_KO.md"><img width="20px" src="https://iris-go.com/images/flag-south-korea.svg?v=12" /></a> <a href="README_PT_BR.md"><img width="20px" align="center" src="https://www.iris-go.com/images/flag-brazil.svg" /></a> <a href="README_JA.md"><img width="20px" height="20px" src="https://iris-go.com/images/flag-japan.svg" /></a>
 
-[![build status](https://img.shields.io/github/actions/workflow/status/kataras/iris/ci.yml?branch=main&style=for-the-badge)](https://github.com/kataras/iris/actions/workflows/ci.yml) [![view examples](https://img.shields.io/badge/examples%20-270-a83adf.svg?style=for-the-badge&logo=go)](https://github.com/kataras/iris/tree/main/_examples) [![chat](https://img.shields.io/gitter/room/iris_go/community.svg?color=cc2b5e&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community) <!--[![FOSSA Status](https://img.shields.io/badge/LICENSE%20SCAN-PASSING❤️-CD2956?style=for-the-badge&logo=fossa)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkataras%2Firis?ref=badge_shield)--> [![donate](https://img.shields.io/badge/support-Iris-blue.svg?style=for-the-badge&logo=paypal)](https://iris-go.com/donate) <!--[![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)--><!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://pkg.go.dev/github.com/kataras/iris/v12@v12.2.8)--> <!-- [![release](https://img.shields.io/badge/release%20-v12.0-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases) -->
+[![build status](https://img.shields.io/github/actions/workflow/status/kataras/iris/ci.yml?branch=main&style=for-the-badge)](https://github.com/kataras/iris/actions/workflows/ci.yml) [![view examples](https://img.shields.io/badge/examples%20-270-a83adf.svg?style=for-the-badge&logo=go)](https://github.com/kataras/iris/tree/main/_examples) [![chat](https://img.shields.io/gitter/room/iris_go/community.svg?color=cc2b5e&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community) <!--[![FOSSA Status](https://img.shields.io/badge/LICENSE%20SCAN-PASSING❤️-CD2956?style=for-the-badge&logo=fossa)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkataras%2Firis?ref=badge_shield)--> [![donate](https://img.shields.io/badge/support-Iris-blue.svg?style=for-the-badge&logo=paypal)](https://iris-go.com/donate) <!--[![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)--><!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://pkg.go.dev/github.com/kataras/iris/v12@v)--> <!-- [![release](https://img.shields.io/badge/release%20-v12.0-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases) -->
 
 <!-- <a href="https://iris-go.com"> <img align="right" src="https://iris-go.com/images/logo-w169.png"></a> -->
 
@@ -226,7 +226,7 @@ O único requisito é a [Linguagem de programação Go](https://go.dev/dl/).
 $ mkdir myapp
 $ cd myapp
 $ go mod init myapp
-$ go get github.com/kataras/iris/v12@latest # or @v12.2.8
+$ go get github.com/kataras/iris/v12@latest # or @v
 ```
 
 <details><summary>Instalar num projeto existente</summary>

+ 2 - 2
vendor/github.com/kataras/iris/v12/README_RU.md

@@ -1,6 +1,6 @@
 # Iris Web Framework
 
-[![build status](https://img.shields.io/github/actions/workflow/status/kataras/iris/ci.yml?branch=main&style=for-the-badge)](https://github.com/kataras/iris/actions/workflows/ci.yml) [![FOSSA Status](https://img.shields.io/badge/LICENSE%20SCAN-PASSING❤️-CD2956?style=for-the-badge&logo=fossa)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkataras%2Firis?ref=badge_shield)<!--[![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)--><!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://pkg.go.dev/github.com/kataras/iris/v12@v12.2.8)--> [![view examples](https://img.shields.io/badge/learn%20by-examples-0C8EC5.svg?style=for-the-badge&logo=go)](https://github.com/kataras/iris/tree/main/_examples) [![chat](https://img.shields.io/gitter/room/iris_go/community.svg?color=7E18DD&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community)<!--[![donate on PayPal](https://img.shields.io/badge/support-PayPal-blue.svg?style=for-the-badge)](https://iris-go.com/donate)--><!-- [![release](https://img.shields.io/badge/release%20-v12.0-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases) -->
+[![build status](https://img.shields.io/github/actions/workflow/status/kataras/iris/ci.yml?branch=main&style=for-the-badge)](https://github.com/kataras/iris/actions/workflows/ci.yml) [![FOSSA Status](https://img.shields.io/badge/LICENSE%20SCAN-PASSING❤️-CD2956?style=for-the-badge&logo=fossa)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkataras%2Firis?ref=badge_shield)<!--[![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)--><!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://pkg.go.dev/github.com/kataras/iris/v12@v)--> [![view examples](https://img.shields.io/badge/learn%20by-examples-0C8EC5.svg?style=for-the-badge&logo=go)](https://github.com/kataras/iris/tree/main/_examples) [![chat](https://img.shields.io/gitter/room/iris_go/community.svg?color=7E18DD&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community)<!--[![donate on PayPal](https://img.shields.io/badge/support-PayPal-blue.svg?style=for-the-badge)](https://iris-go.com/donate)--><!-- [![release](https://img.shields.io/badge/release%20-v12.0-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases) -->
 Iris — это быстрый, простой, но полнофункциональный и эффективный веб-фреймворк для Go. Он обеспечивает красивую, выразительную и простую в использовании основу для вашего следующего веб-сайта или API.
 
 Узнайте, что [говорят другие люди об Iris](https://iris-go.com/testimonials/) и поставьте **[звёздочку](https://github.com/kataras/iris/stargazers)** этому проекту с открытым исходным кодом, чтобы поддержать его потенциал.
@@ -50,7 +50,7 @@ $ go run example.go
 
 <!-- ![](https://media.giphy.com/media/Ur8iqy9FQfmPuyQpgy/giphy.gif) -->
 
-Для получения более подробной технической документации вы можете обратиться к нашему [godoc](https://pkg.go.dev/github.com/kataras/iris/v12@v12.2.8). А для живых примеров кода — вы всегда можете посетить [\_examples](_examples/) в поддиректории этого репозитория.
+Для получения более подробной технической документации вы можете обратиться к нашему [godoc](https://pkg.go.dev/github.com/kataras/iris/v12@v). А для живых примеров кода — вы всегда можете посетить [\_examples](_examples/) в поддиректории этого репозитория.
 
 ### Вы любите читать во время путешествий?
 

+ 2 - 2
vendor/github.com/kataras/iris/v12/README_VN.md

@@ -6,7 +6,7 @@ Try the official [Iris Command Line Interface](https://github.com/kataras/iris-c
 
 # <a href="https://iris-go.com"><img src="https://iris-go.com/images/logo-new-lq-45.png"></a> Iris Web Framework <a href="README_GR.md"><img width="20px" src="https://iris-go.com/images/flag-greece.svg" /></a> <a href="README_FR.md"><img width="20px" src="https://iris-go.com/images/flag-france.svg" /></a> <a href="README_ZH_HANT.md"><img width="20px" src="https://iris-go.com/images/flag-taiwan.svg" /></a> <a href="README_ZH_HANS.md"><img width="20px" src="https://iris-go.com/images/flag-china.svg" /></a> <a href="README_ES.md"><img width="20px" src="https://iris-go.com/images/flag-spain.png" /></a> <a href="README_FA.md"><img width="20px" src="https://iris-go.com/images/flag-iran.svg" /></a> <a href="README_RU.md"><img width="20px" src="https://iris-go.com/images/flag-russia.svg" /></a> <a href="README_KO.md"><img width="20px" src="https://iris-go.com/images/flag-south-korea.svg?v=12" /></a> <a href="README_PT_BR.md"><img width="20px" height="20px" src="https://iris-go.com/images/flag-brazil.svg" /></a>
 
-[![build status](https://img.shields.io/github/actions/workflow/status/kataras/iris/ci.yml?branch=main&style=for-the-badge)](https://github.com/kataras/iris/actions/workflows/ci.yml) [![view examples](https://img.shields.io/badge/examples%20-285-a83adf.svg?style=for-the-badge&logo=go)](https://github.com/kataras/iris/tree/main/_examples) [![chat](https://img.shields.io/gitter/room/iris_go/community.svg?color=cc2b5e&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community) <!--[![FOSSA Status](https://img.shields.io/badge/LICENSE%20SCAN-PASSING❤️-CD2956?style=for-the-badge&logo=fossa)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkataras%2Firis?ref=badge_shield)--> [![donate](https://img.shields.io/badge/support-Iris-blue.svg?style=for-the-badge&logo=paypal)](https://iris-go.com/donate) <!--[![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)--><!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://pkg.go.dev/github.com/kataras/iris/v12@v12.2.8)--> <!-- [![release](https://img.shields.io/badge/release%20-v12.0-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases) -->
+[![build status](https://img.shields.io/github/actions/workflow/status/kataras/iris/ci.yml?branch=main&style=for-the-badge)](https://github.com/kataras/iris/actions/workflows/ci.yml) [![view examples](https://img.shields.io/badge/examples%20-285-a83adf.svg?style=for-the-badge&logo=go)](https://github.com/kataras/iris/tree/main/_examples) [![chat](https://img.shields.io/gitter/room/iris_go/community.svg?color=cc2b5e&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community) <!--[![FOSSA Status](https://img.shields.io/badge/LICENSE%20SCAN-PASSING❤️-CD2956?style=for-the-badge&logo=fossa)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkataras%2Firis?ref=badge_shield)--> [![donate](https://img.shields.io/badge/support-Iris-blue.svg?style=for-the-badge&logo=paypal)](https://iris-go.com/donate) <!--[![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)--><!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://pkg.go.dev/github.com/kataras/iris/v12@v)--> <!-- [![release](https://img.shields.io/badge/release%20-v12.0-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases) -->
 
 Iris là một khung web nhanh, đơn giản nhưng đầy đủ tính năng và rất hiệu quả dành cho Go.
 
@@ -220,7 +220,7 @@ Yêu cầu duy nhất là [Ngôn ngữ lập trình Go](https://go.dev/dl/).
 $ mkdir myapp
 $ cd myapp
 $ go mod init myapp
-$ go get github.com/kataras/iris/v12@latest # or @v12.2.8
+$ go get github.com/kataras/iris/v12@latest # or @v
 ```
 
 <details><summary>Cài đặt trên dự án hiện có</summary>

+ 1 - 1
vendor/github.com/kataras/iris/v12/README_ZH_HANS.md

@@ -10,7 +10,7 @@
 
 # Iris Web Framework <a href="README_GR.md"><img width="20px" src="https://iris-go.com/images/flag-greece.svg" /></a> <a href="README_FR.md"><img width="20px" src="https://iris-go.com/images/flag-france.svg" /></a> <a href="README_ZH.md"><img width="20px" src="https://iris-go.com/images/flag-china.svg" /></a> <a href="README_ES.md"><img width="20px" src="https://iris-go.com/images/flag-spain.png" /></a> <a href="README_FA.md"><img width="20px" src="https://iris-go.com/images/flag-iran.svg" /></a> <a href="README_RU.md"><img width="20px" src="https://iris-go.com/images/flag-russia.svg" /></a> <a href="README_KO.md"><img width="20px" src="https://iris-go.com/images/flag-south-korea.svg?v=12" /></a> <a href="README_JA.md"><img width="20px" height="20px" src="https://iris-go.com/images/flag-japan.svg" /></a>
 
-[![build status](https://img.shields.io/github/actions/workflow/status/kataras/iris/ci.yml?branch=main&style=for-the-badge)](https://github.com/kataras/iris/actions/workflows/ci.yml) [![view examples](https://img.shields.io/badge/examples%20-253-a83adf.svg?style=for-the-badge&logo=go)](https://github.com/kataras/iris/tree/main/_examples) [![chat](https://img.shields.io/gitter/room/iris_go/community.svg?color=cc2b5e&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community) <!--[![FOSSA Status](https://img.shields.io/badge/LICENSE%20SCAN-PASSING❤️-CD2956?style=for-the-badge&logo=fossa)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkataras%2Firis?ref=badge_shield)--> [![donate](https://img.shields.io/badge/support-Iris-blue.svg?style=for-the-badge&logo=paypal)](https://iris-go.com/donate) <!--[![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)--><!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://pkg.go.dev/github.com/kataras/iris/v12@v12.2.8)--> <!-- [![release](https://img.shields.io/badge/release%20-v12.0-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases) -->
+[![build status](https://img.shields.io/github/actions/workflow/status/kataras/iris/ci.yml?branch=main&style=for-the-badge)](https://github.com/kataras/iris/actions/workflows/ci.yml) [![view examples](https://img.shields.io/badge/examples%20-253-a83adf.svg?style=for-the-badge&logo=go)](https://github.com/kataras/iris/tree/main/_examples) [![chat](https://img.shields.io/gitter/room/iris_go/community.svg?color=cc2b5e&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community) <!--[![FOSSA Status](https://img.shields.io/badge/LICENSE%20SCAN-PASSING❤️-CD2956?style=for-the-badge&logo=fossa)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkataras%2Firis?ref=badge_shield)--> [![donate](https://img.shields.io/badge/support-Iris-blue.svg?style=for-the-badge&logo=paypal)](https://iris-go.com/donate) <!--[![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)--><!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://pkg.go.dev/github.com/kataras/iris/v12@v)--> <!-- [![release](https://img.shields.io/badge/release%20-v12.0-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases) -->
 
 <!-- <a href="https://iris-go.com"> <img align="right" src="https://iris-go.com/images/logo-w169.png"></a> -->
 

+ 2 - 2
vendor/github.com/kataras/iris/v12/README_ZH_HANT.md

@@ -12,7 +12,7 @@
 
 # Iris Web 框架 <a href="README_GR.md"><img width="20px" src="https://iris-go.com/images/flag-greece.svg" /></a> <a href="README_FR.md"><img width="20px" src="https://iris-go.com/images/flag-france.svg" /></a> <a href="README_ZH.md"><img width="20px" src="https://iris-go.com/images/flag-china.svg" /></a> <a href="README_ES.md"><img width="20px" src="https://iris-go.com/images/flag-spain.png" /></a> <a href="README_FA.md"><img width="20px" src="https://iris-go.com/images/flag-iran.svg" /></a> <a href="README_RU.md"><img width="20px" src="https://iris-go.com/images/flag-russia.svg" /></a> <a href="README_KO.md"><img width="20px" src="https://iris-go.com/images/flag-south-korea.svg?v=12" /></a> <a href="README_PT_BR.md"><img width="20px" height="20px" src="https://iris-go.com/images/flag-brazil.svg" /></a> <a href="README_JA.md"><img width="20px" height="20px" src="https://iris-go.com/images/flag-japan.svg" /></a>
 
-[![組建狀態](https://img.shields.io/github/actions/workflow/status/kataras/iris/ci.yml?branch=main&style=for-the-badge)](https://github.com/kataras/iris/actions/workflows/ci.yml) [![查看範例](https://img.shields.io/badge/examples%20-285-a83adf.svg?style=for-the-badge&logo=go)](https://github.com/kataras/iris/tree/main/_examples) [![聊天室](https://img.shields.io/gitter/room/iris_go/community.svg?color=cc2b5e&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community) <!--[![FOSSA Status](https://img.shields.io/badge/LICENSE%20SCAN-PASSING❤️-CD2956?style=for-the-badge&logo=fossa)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkataras%2Firis?ref=badge_shield)--> [![捐助](https://img.shields.io/badge/support-Iris-blue.svg?style=for-the-badge&logo=paypal)](https://iris-go.com/donate) <!--[![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)--><!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://pkg.go.dev/github.com/kataras/iris/v12@v12.2.8)--> <!-- [![release](https://img.shields.io/badge/release%20-v12.0-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases) -->
+[![組建狀態](https://img.shields.io/github/actions/workflow/status/kataras/iris/ci.yml?branch=main&style=for-the-badge)](https://github.com/kataras/iris/actions/workflows/ci.yml) [![查看範例](https://img.shields.io/badge/examples%20-285-a83adf.svg?style=for-the-badge&logo=go)](https://github.com/kataras/iris/tree/main/_examples) [![聊天室](https://img.shields.io/gitter/room/iris_go/community.svg?color=cc2b5e&logo=gitter&style=for-the-badge)](https://gitter.im/iris_go/community) <!--[![FOSSA Status](https://img.shields.io/badge/LICENSE%20SCAN-PASSING❤️-CD2956?style=for-the-badge&logo=fossa)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkataras%2Firis?ref=badge_shield)--> [![捐助](https://img.shields.io/badge/support-Iris-blue.svg?style=for-the-badge&logo=paypal)](https://iris-go.com/donate) <!--[![report card](https://img.shields.io/badge/report%20card-a%2B-ff3333.svg?style=for-the-badge)](https://goreportcard.com/report/github.com/kataras/iris)--><!--[![godocs](https://img.shields.io/badge/go-%20docs-488AC7.svg?style=for-the-badge)](https://pkg.go.dev/github.com/kataras/iris/v12@v)--> <!-- [![release](https://img.shields.io/badge/release%20-v12.0-0077b3.svg?style=for-the-badge)](https://github.com/kataras/iris/releases) -->
 
 <!-- <a href="https://iris-go.com"> <img align="right" src="https://iris-go.com/images/logo-w169.png"></a> -->
 
@@ -237,7 +237,7 @@ Iris 提供了至少這些功能:
 $ mkdir myapp
 $ cd myapp
 $ go mod init myapp
-$ go get github.com/kataras/iris/v12@latest # 或 @v12.2.8
+$ go get github.com/kataras/iris/v12@latest # 或 @v
 ```
 
 <details><summary>在現有專案安裝</summary>

+ 17 - 0
vendor/github.com/kataras/iris/v12/aliases.go

@@ -293,6 +293,14 @@ type (
 	FallbackViewLayout = context.FallbackViewLayout
 )
 
+// Component returns a new Handler which can be registered as a main handler for a route.
+// It's a shortcut handler that renders the given component as HTML through Context.RenderComponent.
+func Component(component context.Component) Handler {
+	return func(ctx Context) {
+		ctx.RenderComponent(component)
+	}
+}
+
 // PrefixDir returns a new FileSystem that opens files
 // by adding the given "prefix" to the directory tree of "fs".
 //
@@ -507,6 +515,15 @@ var (
 	// A shortcut of the `cache#Cache304`.
 	Cache304 = cache.Cache304
 
+	// CookieOverride is a CookieOption which overrides the cookie explicitly to the given "cookie".
+	//
+	// A shortcut for the `context#CookieOverride`.
+	CookieOverride = context.CookieOverride
+	// CookieDomain is a CookieOption which sets the cookie's Domain field.
+	// If empty then the current domain is used.
+	//
+	// A shortcut for the `context#CookieDomain`.
+	CookieDomain = context.CookieDomain
 	// CookieAllowReclaim accepts the Context itself.
 	// If set it will add the cookie to (on `CookieSet`, `CookieSetKV`, `CookieUpsert`)
 	// or remove the cookie from (on `CookieRemove`) the Request object too.

+ 29 - 2
vendor/github.com/kataras/iris/v12/configuration.go

@@ -216,6 +216,13 @@ func WithTimeout(timeoutDur time.Duration, htmlBody ...string) Configurator {
 	}
 }
 
+// NonBlocking sets the `Configuration.NonBlocking` field to true.
+func NonBlocking() Configurator {
+	return func(app *Application) {
+		app.config.NonBlocking = true
+	}
+}
+
 // WithoutServerError will cause to ignore the matched "errors"
 // from the main application's `Run/Listen` function.
 //
@@ -677,6 +684,10 @@ type Configuration struct {
 	// TimeoutMessage specifies the HTML body when a handler hits its life time based
 	// on the Timeout configuration field.
 	TimeoutMessage string `ini:"timeout_message" json:"timeoutMessage" yaml:"TimeoutMessage" toml:"TimeoutMessage"`
+	// NonBlocking, if set to true then the server will start listening for incoming connections
+	// without blocking the main goroutine. Use the Application.Wait method to block and wait for the server to be up and running.
+	NonBlocking bool `ini:"non_blocking" json:"nonBlocking" yaml:"NonBlocking" toml:"NonBlocking"`
+
 	// Tunneling can be optionally set to enable ngrok http(s) tunneling for this Iris app instance.
 	// See the `WithTunneling` Configurator too.
 	Tunneling TunnelingConfiguration `ini:"tunneling" json:"tunneling,omitempty" yaml:"Tunneling" toml:"Tunneling"`
@@ -969,9 +980,15 @@ type Configuration struct {
 
 var _ context.ConfigurationReadOnly = (*Configuration)(nil)
 
-// GetVHost returns the non-exported vhost config field.
+// GetVHost returns the VHost config field.
 func (c *Configuration) GetVHost() string {
-	return c.VHost
+	vhost := c.VHost
+	return vhost
+}
+
+// SetVHost sets the VHost config field.
+func (c *Configuration) SetVHost(s string) {
+	c.VHost = s
 }
 
 // GetLogLevel returns the LogLevel field.
@@ -994,6 +1011,11 @@ func (c *Configuration) GetTimeout() time.Duration {
 	return c.Timeout
 }
 
+// GetNonBlocking returns the NonBlocking field.
+func (c *Configuration) GetNonBlocking() bool {
+	return c.NonBlocking
+}
+
 // GetTimeoutMessage returns the TimeoutMessage field.
 func (c *Configuration) GetTimeoutMessage() string {
 	return c.TimeoutMessage
@@ -1201,6 +1223,10 @@ func WithConfiguration(c Configuration) Configurator {
 			main.TimeoutMessage = v
 		}
 
+		if v := c.NonBlocking; v {
+			main.NonBlocking = v
+		}
+
 		if len(c.Tunneling.Tunnels) > 0 {
 			main.Tunneling = c.Tunneling
 		}
@@ -1375,6 +1401,7 @@ func DefaultConfiguration() Configuration {
 		KeepAlive:                         0,
 		Timeout:                           0,
 		TimeoutMessage:                    DefaultTimeoutMessage,
+		NonBlocking:                       false,
 		DisableStartupLog:                 false,
 		DisableInterruptHandler:           false,
 		DisablePathCorrection:             false,

+ 2 - 0
vendor/github.com/kataras/iris/v12/context/configuration.go

@@ -24,6 +24,8 @@ type ConfigurationReadOnly interface {
 	GetTimeout() time.Duration
 	// GetTimeoutMessage returns the TimeoutMessage field.
 	GetTimeoutMessage() string
+	// GetNonBlocking returns the NonBlocking field.
+	GetNonBlocking() bool
 	// GetDisablePathCorrection returns the DisablePathCorrection field
 	GetDisablePathCorrection() bool
 	// GetDisablePathCorrectionRedirection returns the DisablePathCorrectionRedirection field.

+ 87 - 22
vendor/github.com/kataras/iris/v12/context/context.go

@@ -2,7 +2,7 @@ package context
 
 import (
 	"bytes"
-	stdContext "context"
+	"context"
 	"encoding/json"
 	"encoding/xml"
 	"errors"
@@ -78,7 +78,7 @@ type (
 	// BodyDecoderWithContext same as BodyDecoder but it can accept a standard context,
 	// which is binded to the HTTP request's context.
 	BodyDecoderWithContext interface {
-		DecodeContext(ctx stdContext.Context, data []byte) error
+		DecodeContext(ctx context.Context, data []byte) error
 	}
 
 	// Unmarshaler is the interface implemented by types that can unmarshal any raw data.
@@ -275,8 +275,8 @@ func IsErrCanceled(err error) bool {
 
 	var netErr net.Error
 	return (errors.As(err, &netErr) && netErr.Timeout()) ||
-		errors.Is(err, stdContext.Canceled) ||
-		errors.Is(err, stdContext.DeadlineExceeded) ||
+		errors.Is(err, context.Canceled) ||
+		errors.Is(err, context.DeadlineExceeded) ||
 		errors.Is(err, http.ErrHandlerTimeout) ||
 		err.Error() == "closed pool"
 }
@@ -437,7 +437,7 @@ var acquireGoroutines = func() interface{} {
 	return &goroutines{wg: new(sync.WaitGroup)}
 }
 
-func (ctx *Context) Go(fn func(cancelCtx stdContext.Context)) (running int) {
+func (ctx *Context) Go(fn func(cancelCtx context.Context)) (running int) {
 	g := ctx.values.GetOrSet(goroutinesContextKey, acquireGoroutines).(*goroutines)
 	if fn != nil {
 		g.wg.Add(1)
@@ -448,7 +448,7 @@ func (ctx *Context) Go(fn func(cancelCtx stdContext.Context)) (running int) {
 
 		ctx.waitFunc = g.wg.Wait
 
-		go func(reqCtx stdContext.Context) {
+		go func(reqCtx context.Context) {
 			fn(reqCtx)
 			g.wg.Done()
 
@@ -2842,8 +2842,8 @@ func (ctx *Context) ReadYAML(outPtr interface{}) error {
 
 var (
 	// IsErrEmptyJSON reports whether the given "err" is caused by a
-	// Context.ReadJSON call when the request body
-	// didn't start with { or it was totally empty.
+	// Client.ReadJSON call when the request body was empty or
+	// didn't start with { or [.
 	IsErrEmptyJSON = func(err error) bool {
 		if err == nil {
 			return false
@@ -2858,8 +2858,9 @@ var (
 			return v.Offset == 0 && v.Error() == "unexpected end of JSON input"
 		}
 
-		// when optimization is enabled, the jsoniter will report the following error:
-		return strings.Contains(err.Error(), "readObjectStart: expect {")
+		errMsg := err.Error()
+		// 3rd party pacakges:
+		return strings.Contains(errMsg, "readObjectStart: expect {") || strings.Contains(errMsg, "readArrayStart: expect [")
 	}
 
 	// IsErrPath can be used at `context#ReadForm` and `context#ReadQuery`.
@@ -4258,6 +4259,10 @@ func (h ErrorHandlerFunc) HandleContextError(ctx *Context, err error) {
 }
 
 func (ctx *Context) handleContextError(err error) {
+	if err == nil {
+		return
+	}
+
 	if errHandler := ctx.app.GetContextErrorHandler(); errHandler != nil {
 		errHandler.HandleContextError(ctx, err)
 	} else {
@@ -4290,6 +4295,28 @@ func (ctx *Context) Render(statusCode int, r interface {
 	}
 }
 
+// Component is the interface which all components must implement.
+// A component is a struct which can be rendered to a writer.
+// It's being used by the `Context.RenderComponent` method.
+// An example of compatible Component is a templ.Component.
+type Component interface {
+	Render(context.Context, io.Writer) error
+}
+
+// RenderComponent renders a component to the client.
+// It sets the "Content-Type" header to "text/html; charset=utf-8".
+// It reports any component render errors back to the caller.
+// Look the Application.SetContextErrorHandler to override the
+// default status code 500 with a custom error response.
+func (ctx *Context) RenderComponent(component Component) error {
+	ctx.ContentType("text/html; charset=utf-8")
+	err := component.Render(ctx.Request().Context(), ctx.ResponseWriter())
+	if err != nil {
+		ctx.handleContextError(err)
+	}
+	return err
+}
+
 // JSON marshals the given "v" value to JSON and writes the response to the client.
 // Look the Configuration.EnableProtoJSON and EnableEasyJSON too.
 //
@@ -5386,7 +5413,7 @@ func (ctx *Context) ServeContent(content io.ReadSeeker, filename string, modtime
 // represents one byte. See "golang.org/x/time/rate" package.
 type rateReadSeeker struct {
 	io.ReadSeeker
-	ctx     stdContext.Context
+	ctx     context.Context
 	limiter *rate.Limiter
 }
 
@@ -5545,10 +5572,39 @@ func CookieIncluded(cookie *http.Cookie, cookieNames []string) bool {
 	return true
 }
 
-var cookieNameSanitizer = strings.NewReplacer("\n", "-", "\r", "-")
+// var cookieNameSanitizer = strings.NewReplacer("\n", "-", "\r", "-")
+//
+// func sanitizeCookieName(n string) string {
+// 	return cookieNameSanitizer.Replace(n)
+// }
+
+// CookieOverride is a CookieOption which overrides the cookie explicitly to the given "cookie".
+//
+// Usage:
+// ctx.RemoveCookie("the_cookie_name", iris.CookieOverride(&http.Cookie{Domain: "example.com"}))
+func CookieOverride(cookie *http.Cookie) CookieOption { // The "Cookie" word method name is reserved as it's used as an alias.
+	return func(_ *Context, c *http.Cookie, op uint8) {
+		if op == OpCookieGet {
+			return
+		}
+
+		*cookie = *c
+	}
+}
+
+// CookieDomain is a CookieOption which sets the cookie's Domain field.
+// If empty then the current domain is used.
+//
+// Usage:
+// ctx.RemoveCookie("the_cookie_name", iris.CookieDomain("example.com"))
+func CookieDomain(domain string) CookieOption {
+	return func(_ *Context, c *http.Cookie, op uint8) {
+		if op == OpCookieGet {
+			return
+		}
 
-func sanitizeCookieName(n string) string {
-	return cookieNameSanitizer.Replace(n)
+		c.Domain = domain
+	}
 }
 
 // CookieAllowReclaim accepts the Context itself.
@@ -5746,6 +5802,8 @@ const cookieOptionsContextKey = "iris.cookie.options"
 // cookies sent or received from the next Handler in the chain.
 //
 // Available builtin Cookie options are:
+//   - CookieOverride
+//   - CookieDomain
 //   - CookieAllowReclaim
 //   - CookieAllowSubdomains
 //   - CookieSecure
@@ -5920,21 +5978,28 @@ var (
 )
 
 // RemoveCookie deletes a cookie by its name and path = "/".
-// Tip: change the cookie's path to the current one by: RemoveCookie("name", iris.CookieCleanPath)
+// Tip: change the cookie's path to the current one by: RemoveCookie("the_cookie_name", iris.CookieCleanPath)
+//
+// If you intend to remove a cookie with a specific domain and value, please ensure to pass these values explicitly:
+//
+//	ctx.RemoveCookie("the_cookie_name", iris.CookieDomain("example.com"), iris.CookiePath("/"))
+//
+// OR use a Cookie value instead:
+//
+//	ctx.RemoveCookie("the_cookie_name", iris.CookieOverride(&http.Cookie{Domain: "example.com", Path: "/"}))
 //
 // Example: https://github.com/kataras/iris/tree/main/_examples/cookies/basic
 func (ctx *Context) RemoveCookie(name string, options ...CookieOption) {
-	c := &http.Cookie{}
+	c := &http.Cookie{Path: "/"}
+	// Send the cookie back to the client
+	ctx.applyCookieOptions(c, OpCookieDel, options)
 	c.Name = name
 	c.Value = ""
-	c.Path = "/" // if user wants to change it, use of the CookieOption `CookiePath` is required if not `ctx.SetCookie`.
 	c.HttpOnly = true
-
-	// RFC says 1 second, but let's do it 1  to make sure is working
+	// Set the cookie expiration date to a past time
 	c.Expires = CookieExpireDelete
-	c.MaxAge = -1
+	c.MaxAge = -1 // RFC says 1 second, but let's do it -1  to make sure is working.
 
-	ctx.applyCookieOptions(c, OpCookieDel, options)
 	http.SetCookie(ctx.writer, c)
 }
 
@@ -6459,7 +6524,7 @@ func (ctx *Context) User() User {
 }
 
 // Ensure Iris Context implements the standard Context package, build-time.
-var _ stdContext.Context = (*Context)(nil)
+var _ context.Context = (*Context)(nil)
 
 // Deadline returns the time when work done on behalf of this context
 // should be canceled. Deadline returns ok==false when no deadline is

+ 1 - 1
vendor/github.com/kataras/iris/v12/context/handler.go

@@ -12,7 +12,7 @@ import (
 
 var (
 	// PackageName is the Iris Go module package name.
-	PackageName = strings.TrimSuffix(reflect.TypeOf(Handlers{}).PkgPath(), "/context")
+	PackageName = strings.TrimSuffix(reflect.TypeOf(Context{}).PkgPath(), "/context")
 
 	// WorkingDir is the (initial) current directory.
 	WorkingDir, _ = os.Getwd()

+ 67 - 60
vendor/github.com/kataras/iris/v12/core/host/supervisor.go

@@ -25,6 +25,13 @@ import (
 // Look the `Configure` func for more.
 type Configurator func(su *Supervisor)
 
+// NonBlocking sets the server to non-blocking mode. Use its `Wait` method to wait for server to be up and running.
+func NonBlocking() Configurator {
+	return func(su *Supervisor) {
+		su.nonBlocking = true
+	}
+}
+
 // Supervisor is the wrapper and the manager for a compatible server
 // and it's relative actions, called Tasks.
 //
@@ -34,14 +41,12 @@ type Supervisor struct {
 	// FriendlyAddr can be set to customize the "Now Listening on: {FriendlyAddr}".
 	FriendlyAddr                   string // e.g mydomain.com instead of :443 when AutoTLS is used, see `WriteStartupLogOnServe` task.
 	disableHTTP1ToHTTP2Redirection bool
-	closedManually                 uint32 // future use, accessed atomically (non-zero means we've called the Shutdown)
-	closedByInterruptHandler       uint32 // non-zero means that the end-developer interrupted it by-purpose.
-	manuallyTLS                    bool   // we need that in order to determinate what to output on the console before the server begin.
-	autoTLS                        bool
-	shouldWait                     int32 // non-zero means that the host should wait for unblocking
-	unblockChan                    chan struct{}
 
-	mu sync.Mutex
+	closedByInterruptHandler uint32 // non-zero means that the end-developer interrupted it by-purpose.
+	manuallyTLS              bool   // we need that in order to determinate what to output on the console before the server begin.
+	autoTLS                  bool
+
+	mu sync.RWMutex
 
 	onServe []func(TaskHost)
 	// IgnoreErrors should contains the errors that should be ignored
@@ -73,6 +78,10 @@ type Supervisor struct {
 	// If more than zero then tcp keep alive listener is attached instead of the simple TCP listener.
 	// See `iris.Configuration.KeepAlive`
 	KeepAlive time.Duration
+
+	address     string
+	nonBlocking bool
+	waiter      *Waiter
 }
 
 // New returns a new host supervisor
@@ -83,10 +92,12 @@ type Supervisor struct {
 // It has its own flow, which means that you can prevent
 // to return and exit and restore the flow too.
 func New(srv *http.Server) *Supervisor {
-	return &Supervisor{
-		Server:      srv,
-		unblockChan: make(chan struct{}, 1),
+	su := &Supervisor{
+		Server: srv,
 	}
+
+	su.waiter = NewWaiter(7, su.getAddress)
+	return su
 }
 
 // Configure accepts one or more `Configurator`.
@@ -113,36 +124,6 @@ func (su *Supervisor) NoRedirect() {
 	su.disableHTTP1ToHTTP2Redirection = true
 }
 
-// DeferFlow defers the flow of the exeuction,
-// i.e: when server should return error and exit
-// from app, a DeferFlow call inside a Task
-// can wait for a `RestoreFlow` to exit or not exit if
-// host's server is "fixed".
-//
-// See `RestoreFlow` too.
-func (su *Supervisor) DeferFlow() {
-	atomic.StoreInt32(&su.shouldWait, 1)
-}
-
-// RestoreFlow restores the flow of the execution,
-// if called without a `DeferFlow` call before
-// then it does nothing.
-// See tests to understand how that can be useful on specific cases.
-//
-// See `DeferFlow` too.
-func (su *Supervisor) RestoreFlow() {
-	if su.isWaiting() {
-		atomic.StoreInt32(&su.shouldWait, 0)
-		su.mu.Lock()
-		su.unblockChan <- struct{}{}
-		su.mu.Unlock()
-	}
-}
-
-func (su *Supervisor) isWaiting() bool {
-	return atomic.LoadInt32(&su.shouldWait) != 0
-}
-
 func (su *Supervisor) newListener() (net.Listener, error) {
 	var (
 		l   net.Listener
@@ -198,14 +179,28 @@ func (su *Supervisor) validateErr(err error) error {
 }
 
 func (su *Supervisor) notifyErr(err error) {
-	err = su.validateErr(err)
-	if err != nil {
-		su.mu.Lock()
-		for _, f := range su.onErr {
-			go f(err)
-		}
-		su.mu.Unlock()
+	if err == nil {
+		return
+	}
+
+	su.mu.Lock()
+	for _, f := range su.onErr {
+		go f(err)
 	}
+	su.mu.Unlock()
+}
+
+func (su *Supervisor) getAddress() string {
+	su.mu.RLock()
+	addr := su.address
+	su.mu.RUnlock()
+	return addr
+}
+
+func (su *Supervisor) setAddress(addr string) {
+	su.mu.Lock()
+	su.address = addr
+	su.mu.Unlock()
 }
 
 // RegisterOnServe registers a function to call on
@@ -224,27 +219,36 @@ func (su *Supervisor) notifyServe(host TaskHost) {
 	su.mu.Unlock()
 }
 
-// Remove all channels, do it with events
-// or with channels but with a different channel on each task proc
-// I don't know channels are not so safe, when go func and race risk..
-// so better with callbacks....
 func (su *Supervisor) supervise(blockFunc func() error) error {
 	host := createTaskHost(su)
 
 	su.notifyServe(host)
 	atomic.StoreUint32(&su.closedByInterruptHandler, 0)
-	atomic.StoreUint32(&su.closedManually, 0)
+
+	if su.nonBlocking {
+		go func() {
+			err := blockFunc()
+			if err != nil {
+				su.waiter.Fail(err)
+			}
+
+			err = su.validateErr(err)
+			su.notifyErr(err)
+		}()
+
+		return nil
+	}
 
 	err := blockFunc()
+	err = su.validateErr(err)
 	su.notifyErr(err)
 
-	if su.isWaiting() {
-		for range su.unblockChan {
-			break
-		}
-	}
+	return err
+}
 
-	return su.validateErr(err)
+// Wait blocks until server is up and running or a serve failure.
+func (su *Supervisor) Wait(ctx context.Context) error {
+	return su.waiter.Wait(ctx)
 }
 
 // Serve accepts incoming connections on the Listener l, creating a
@@ -259,7 +263,11 @@ func (su *Supervisor) supervise(blockFunc func() error) error {
 // Serve always returns a non-nil error. After Shutdown or Close, the
 // returned error is http.ErrServerClosed.
 func (su *Supervisor) Serve(l net.Listener) error {
-	return su.supervise(func() error { return su.Server.Serve(l) })
+	su.setAddress(l.Addr().String())
+
+	return su.supervise(func() error {
+		return su.Server.Serve(l)
+	})
 }
 
 // ListenAndServe listens on the TCP network address addr
@@ -502,7 +510,6 @@ func (su *Supervisor) RegisterOnShutdown(cb func()) {
 // separately notify such long-lived connections of shutdown and wait
 // for them to close, if desired.
 func (su *Supervisor) Shutdown(ctx context.Context) error {
-	atomic.StoreUint32(&su.closedManually, 1) // future-use
 	if ctx == nil {
 		ctx = context.Background()
 	}

+ 2 - 2
vendor/github.com/kataras/iris/v12/core/host/task.go

@@ -94,10 +94,10 @@ func WriteStartupLogOnServe(w io.Writer) func(TaskHost) {
 // This function should be registered on Interrupt.
 func ShutdownOnInterrupt(su *Supervisor, shutdownTimeout time.Duration) func() {
 	return func() {
-		ctx, cancel := context.WithTimeout(context.TODO(), shutdownTimeout)
+		ctx, cancel := context.WithTimeout(context.Background(), shutdownTimeout)
 		defer cancel()
+
 		su.shutdownOnInterrupt(ctx)
-		su.RestoreFlow()
 	}
 }
 

+ 134 - 0
vendor/github.com/kataras/iris/v12/core/host/waiter.go

@@ -0,0 +1,134 @@
+package host
+
+import (
+	"context"
+	"fmt"
+	"math"
+	"net"
+	"sync"
+	"time"
+)
+
+// Waiter is a helper for waiting for a server to be up and running.
+type Waiter struct {
+	defaultMaxRetries int
+	addressFunc       func() string
+
+	failure error // or runError for app.Run.
+	mu      sync.RWMutex
+}
+
+// NewWaiter returns a new Waiter.
+func NewWaiter(defaultMaxRetries int, addressFunc func() string) *Waiter {
+	if defaultMaxRetries <= 0 {
+		defaultMaxRetries = 7 // 256 seconds max.
+	}
+
+	return &Waiter{
+		defaultMaxRetries: defaultMaxRetries,
+		addressFunc:       addressFunc,
+	}
+}
+
+// Wait blocks the main goroutine until the application is up and running.
+func (w *Waiter) Wait(ctx context.Context) error {
+	// First check if there is an error already from Done.
+	if err := w.getFailure(); err != nil {
+		return err
+	}
+
+	// Set the base for exponential backoff.
+	base := 2.0
+
+	// Get the maximum number of retries by context or force to default max retries (e.g. 7).
+	var maxRetries int
+	// Get the deadline of the context.
+	if deadline, ok := ctx.Deadline(); ok {
+		now := time.Now()
+		timeout := deadline.Sub(now)
+
+		maxRetries = getMaxRetries(timeout, base)
+	} else {
+		maxRetries = w.defaultMaxRetries
+	}
+
+	// Set the initial retry interval.
+	retryInterval := time.Second
+
+	return w.tryConnect(ctx, w.addressFunc, maxRetries, retryInterval, base)
+}
+
+// getMaxRetries calculates the maximum number of retries from the retry interval and the base.
+func getMaxRetries(retryInterval time.Duration, base float64) int {
+	// Convert the retry interval to seconds.
+	seconds := retryInterval.Seconds()
+	// Apply the inverse formula.
+	retries := math.Log(seconds)/math.Log(base) - 1
+	return int(math.Round(retries))
+}
+
+// tryConnect tries to connect to the server with the given context and retry parameters.
+func (w *Waiter) tryConnect(ctx context.Context, addressFunc func() string, maxRetries int, retryInterval time.Duration, base float64) error {
+	// Try to connect to the server in a loop.
+	for i := 0; i < maxRetries; i++ {
+		// Check the context before each attempt.
+		select {
+		case <-ctx.Done():
+			// Context is canceled, return the context error.
+			return ctx.Err()
+		default:
+			address := addressFunc() // Get this server's listening address.
+			if address == "" {
+				i-- // Note that this may be modified at another go routine of the serve method. So it may be empty at first chance. So retry fetching the VHost every 1 second.
+				time.Sleep(time.Second)
+				continue
+			}
+
+			// Context is not canceled, proceed with the attempt.
+			conn, err := net.Dial("tcp", address)
+			if err == nil {
+				// Connection successful, close the connection and return nil.
+				conn.Close()
+				return nil // exit.
+			} // ignore error.
+
+			// Connection failed, wait for the retry interval and try again.
+			time.Sleep(retryInterval)
+			// After each failed attempt, check the server Run's error again.
+			if err := w.getFailure(); err != nil {
+				return err
+			}
+
+			// Increase the retry interval by the base raised to the power of the number of attempts.
+			/*
+				0	2 seconds
+				1	4 seconds
+				2	8 seconds
+				3	~16 seconds
+				4	~32 seconds
+				5	~64 seconds
+				6	~128 seconds
+				7	~256 seconds
+				8	~512 seconds
+				...
+			*/
+			retryInterval = time.Duration(math.Pow(base, float64(i+1))) * time.Second
+		}
+	}
+	// All attempts failed, return an error.
+	return fmt.Errorf("failed to connect to the server after %d retries", maxRetries)
+}
+
+// Fail is called by the server's Run method when the server failed to start.
+func (w *Waiter) Fail(err error) {
+	w.mu.Lock()
+	w.failure = err
+	w.mu.Unlock()
+}
+
+func (w *Waiter) getFailure() error {
+	w.mu.RLock()
+	err := w.failure
+	w.mu.RUnlock()
+	return err
+}

+ 1 - 1
vendor/github.com/kataras/iris/v12/core/memstore/lifetime.go

@@ -13,7 +13,7 @@ var (
 	Clock func() time.Time = time.Now
 
 	// ExpireDelete may be set on Cookie.Expire for expiring the given cookie.
-	ExpireDelete = time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
+	ExpireDelete = time.Unix(0, 0) // time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
 )
 
 // LifeTime controls the session expiration datetime.

+ 1 - 1
vendor/github.com/kataras/iris/v12/core/netutil/addr.go

@@ -184,7 +184,7 @@ func ResolveVHost(addr string) string {
 	}
 
 	if idx := strings.IndexByte(addr, ':'); idx == 0 {
-		// only port, then return the 0.0.0.0
+		// only port, then return the 0.0.0.0:PORT
 		return /* "0.0.0.0" */ "localhost" + addr[idx:]
 	} else if idx > 0 { // if 0.0.0.0:80 let's just convert it to localhost.
 		if addr[0:idx] == "0.0.0.0" {

+ 81 - 0
vendor/github.com/kataras/iris/v12/core/router/api_builder.go

@@ -1540,6 +1540,87 @@ func (api *APIBuilder) Any(relativePath string, handlers ...context.Handler) (ro
 	return
 }
 
+type (
+	// ServerHandler is the interface which all server handlers should implement.
+	// The Iris Application implements it.
+	// See `Party.HandleServer` method for more.
+	ServerHandler interface {
+		ServeHTTPC(*context.Context)
+	}
+
+	serverBuilder interface {
+		Build() error
+	}
+)
+
+// HandleServer registers a route for all HTTP methods which forwards the requests to the given server.
+//
+// Usage:
+//
+//	app.HandleServer("/api/identity/{first:string}/orgs/{second:string}/{p:path}", otherApp)
+//
+// OR
+//
+//	app.HandleServer("/api/identity", otherApp)
+func (api *APIBuilder) HandleServer(path string, server ServerHandler) {
+	if server == nil {
+		return
+	}
+
+	if app, ok := server.(serverBuilder); ok {
+		// Do an extra check for Build() error at any case
+		// the end-developer didn't call Build before.
+		if err := app.Build(); err != nil {
+			panic(err)
+		}
+	}
+
+	pathParameterName := ""
+
+	// Check and get the last parameter name if it's a wildcard one by the end-developer.
+	parsedPath, err := macro.Parse(path, *api.macros)
+	if err != nil {
+		panic(err)
+	}
+
+	if n := len(parsedPath.Params); n > 0 {
+		lastParam := parsedPath.Params[n-1]
+		if lastParam.IsMacro(macro.Path) {
+			pathParameterName = lastParam.Name
+			// path remains as it was defined by the end-developer.
+		}
+	}
+	//
+
+	if pathParameterName == "" {
+		pathParameterName = fmt.Sprintf("iris_wildcard_path_parameter%d", len(api.routes.routes))
+		path = fmt.Sprintf("%s/{%s:path}", path, pathParameterName)
+	}
+
+	handler := makeServerHandler(pathParameterName, server.ServeHTTPC)
+	api.Any(path, handler)
+}
+
+func makeServerHandler(givenPathParameter string, handler context.Handler) context.Handler {
+	return func(ctx *context.Context) {
+		pathValue := ""
+		if givenPathParameter == "" {
+			pathValue = ctx.Params().GetEntryAt(ctx.Params().Len() - 1).ValueRaw.(string)
+		} else {
+			pathValue = ctx.Params().Get(givenPathParameter)
+		}
+
+		apiPath := "/" + pathValue
+
+		r := ctx.Request()
+		r.URL.Path = apiPath
+		r.URL.RawPath = apiPath
+		ctx.Params().Reset()
+
+		handler(ctx)
+	}
+}
+
 func (api *APIBuilder) registerResourceRoute(reqPath string, h context.Handler) *Route {
 	api.Head(reqPath, h)
 	return api.Get(reqPath, h)

+ 11 - 0
vendor/github.com/kataras/iris/v12/core/router/party.go

@@ -393,6 +393,17 @@ type Party interface {
 	// Connect
 	// Trace
 	Any(registeredPath string, handlers ...context.Handler) []*Route
+	// HandleServer registers a route for all HTTP methods which forwards the requests to the given server.
+	//
+	// Usage:
+	//
+	//	app.HandleServer("/api/identity/{first:string}/orgs/{second:string}/{p:path}", otherApp)
+	//
+	// OR
+	//
+	//	app.HandleServer("/api/identity", otherApp)
+	HandleServer(path string, server ServerHandler)
+
 	// CreateRoutes returns a list of Party-based Routes.
 	// It does NOT registers the route. Use `Handle, Get...` methods instead.
 	// This method can be used for third-parties Iris helpers packages and tools

+ 2 - 2
vendor/github.com/kataras/iris/v12/doc.go

@@ -10,11 +10,11 @@ Source code and other details for the project are available at GitHub:
 
 # Current Version
 
-12.2.8
+12.2.10
 
 # Installation
 
-The only requirement is the Go Programming Language, at least version 1.20.
+The only requirement is the Go Programming Language, at least version 1.21.
 
 	$ go get github.com/kataras/iris/v12@latest
 

+ 2 - 1
vendor/github.com/kataras/iris/v12/hero/struct.go

@@ -81,8 +81,9 @@ func makeStruct(structPtr interface{}, c *Container, partyParamsCount int) *Stru
 	singleton := true
 	elem := v.Elem()
 
-	// fmt.Printf("makeStruct: bindings length = %d\n", len(bindings))
+	// fmt.Printf("Service: %s, Bindings(%d):\n", typ, len(bindings))
 	for _, b := range bindings {
+		// fmt.Printf("* " + b.String() + "\n")
 		if b.Dependency.Static {
 			// Fill now.
 			input, err := b.Dependency.Handle(nil, b.Input)

Some files were not shown because too many files changed in this diff