diff options
author | Valery Piashchynski <[email protected]> | 2021-05-14 09:19:00 +0300 |
---|---|---|
committer | Valery Piashchynski <[email protected]> | 2021-05-14 09:19:00 +0300 |
commit | f76b2392cd5b0c4e9f38736323a29b46f9451f0e (patch) | |
tree | b463fd9267323bec1ed8a63f871686ed99843611 | |
parent | fef96198ee6cc1f23bc869050944aa3071667ae7 (diff) | |
parent | e1ff9daead5033b537296ffb071e551b95af91ab (diff) |
Merge remote-tracking branch 'origin/master' into feature/websockets-plugin
# Conflicts:
# plugins/http/plugin.go
# plugins/static/etag.go
31 files changed, 405 insertions, 364 deletions
diff --git a/.github/workflows/linters.yml b/.github/workflows/linters.yml index 56b0c246..82072675 100644 --- a/.github/workflows/linters.yml +++ b/.github/workflows/linters.yml @@ -15,3 +15,4 @@ jobs: with: version: v1.39 # without patch version only-new-issues: false # show only new issues if it's a pull request + args: --timeout=10m diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index bb7d646b..89173b3f 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -82,7 +82,6 @@ jobs: - uses: codecov/codecov-action@v1 # Docs: <https://github.com/codecov/codecov-action> with: - token: ${{ secrets.CODECOV_TOKEN }} file: ./coverage-ci/summary.txt fail_ci_if_error: false diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ed7c7bb..5afdfdc2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,16 @@ CHANGELOG ========= +v2.2.1 (13.05.2021) +------------------- + +## 🩹 Fixes: + +- 🐛 Fix: revert static plugin. It stays as a separate plugin on the main route (`/`) and supports all the previously announced features. +- 🐛 Fix: remove `build` and other old targets from the Makefile. + +--- + v2.2.0 (11.05.2021) ------------------- @@ -19,6 +29,8 @@ v2.2.0 (11.05.2021) ## 🩹 Fixes: - 🐛 Fix: issue with wrong ordered middlewares (reverse). Now the order is correct. +- 🐛 Fix: issue when RR fails if a user sets `debug` mode with the `exec_ttl` supervisor option. +- 🐛 Fix: uniform log levels. Use everywhere the same levels (warn, error, debug, info, panic). --- @@ -4,25 +4,6 @@ SHELL = /bin/sh -.DEFAULT_GOAL := build - -# This will output the help for each task. thanks to https://marmelab.com/blog/2016/02/29/auto-documented-makefile.html -help: ## Show this help - @printf "\033[33m%s:\033[0m\n" 'Available commands' - @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z0-9_-]+:.*?## / {printf " \033[32m%-14s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) - -build: ## Build RR binary file for local os/arch - CGO_ENABLED=0 go build -trimpath -ldflags "-s" -o ./rr ./cmd/main.go - -clean: ## Make some clean - rm ./rr - -install: build ## Build and install RR locally - cp rr /usr/local/bin/rr - -uninstall: ## Uninstall locally installed RR - rm -f /usr/local/bin/rr - test_coverage: docker-compose -f tests/docker-compose.yaml up -d --remove-orphans rm -rf coverage @@ -4,15 +4,16 @@ go 1.16 require ( github.com/NYTimes/gziphandler v1.1.1 + github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 // indirect github.com/alicebob/miniredis/v2 v2.14.3 github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b github.com/dustin/go-humanize v1.0.0 github.com/fatih/color v1.10.0 github.com/go-ole/go-ole v1.2.5 // indirect github.com/go-redis/redis/v8 v8.8.2 - github.com/gofiber/fiber/v2 v2.8.0 + github.com/gofiber/fiber/v2 v2.9.0 github.com/golang/mock v1.4.4 - github.com/google/flatbuffers v1.12.0 // indirect + github.com/google/flatbuffers v1.12.1 github.com/hashicorp/go-multierror v1.1.1 github.com/json-iterator/go v1.1.11 github.com/olekukonko/tablewriter v0.0.5 @@ -29,7 +30,7 @@ require ( github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a github.com/yookoala/gofast v0.6.0 go.etcd.io/bbolt v1.3.5 - go.uber.org/multierr v1.6.0 + go.uber.org/multierr v1.7.0 go.uber.org/zap v1.16.0 golang.org/x/net v0.0.0-20210226101413-39120d07d75e golang.org/x/sync v0.0.0-20201207232520-09787c993a3a @@ -32,8 +32,8 @@ github.com/Shopify/sarama v1.19.0 h1:9oksLxC6uxVPHPVYUmq6xhr1BOF/hHobWH2UzO67z1s github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk= -github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 h1:5sXbqlSomvdjlRbWyNqkPsJ3Fg+tQZCbgeX1VGljbQY= +github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5 h1:rFw4nCn9iMW+Vajsk51NtYIcwSTkXr+JGrMd36kTDJw= @@ -47,7 +47,6 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2c github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk= github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= -github.com/alicebob/miniredis/v2 v2.14.2/go.mod h1:gquAfGbzn92jvtrSC69+6zZnwSODVXVpYDRaGhWaL6I= github.com/alicebob/miniredis/v2 v2.14.3 h1:QWoo2wchYmLgOB6ctlTt2dewQ1Vu6phl+iQbwT8SYGo= github.com/alicebob/miniredis/v2 v2.14.3/go.mod h1:gquAfGbzn92jvtrSC69+6zZnwSODVXVpYDRaGhWaL6I= github.com/andybalholm/brotli v1.0.1 h1:KqhlKozYbRtJvsPrrEeXcO+N2l6NYT5A2QAFmSULpEc= @@ -57,7 +56,6 @@ github.com/apache/thrift v0.13.0 h1:5hryIiq9gtn+MiLVn0wP37kb/uTeRZgN08WoCsAhIhI= github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e h1:QEF07wC0T1rKkctt1RINW/+RMTVmiwxETico2l3gxJA= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= -github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310 h1:BUAU3CGlLvorLI26FmByPp2eC2qla6E1Tw+scpcg/to= @@ -80,12 +78,10 @@ github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c h1:+0HFd5KSZ/mm3 github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b h1:L/QXpzIa3pOvUGt1D1lA5KjYhPBAN/3iWdP7xeFS9F0= github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA= -github.com/buger/goterm v0.0.0-20181115115552-c206103e1f37/go.mod h1:u9UyCz2eTrSGy6fbupqJ54eY5c4IC8gREQ1053dK12U= github.com/casbin/casbin/v2 v2.1.2 h1:bTwon/ECRx9dwBy2ewRVr5OiqjeXSGiTUY74sDPQi/g= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/cenkalti/backoff/v4 v4.0.0/go.mod h1:eEew/i+1Q6OrCDZh3WiXYv3+nJwBASZ8Bog/87DQnVg= github.com/cenkalti/backoff/v4 v4.1.0 h1:c8LkOFQTzuO0WBM/ae5HdGQuZPfPxp7lqBRwQRm4fSc= github.com/cenkalti/backoff/v4 v4.1.0/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk= @@ -110,7 +106,6 @@ github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/coreos/bbolt v1.3.2 h1:wZwiHHUieZCquLkDL0B8UhzreNWsPHooDAG3q34zk0s= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= -github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.13+incompatible h1:8F3hqu9fGYLBifCmRCJsicFqDx/D68Rt3q1JMazcgBQ= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -124,7 +119,6 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbp github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7 h1:6pwm8kMQKCmgUg0ZHTm5+/YvRK0s3THD/28+T6/kk4A= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -166,7 +160,6 @@ github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1 h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-ini/ini v1.38.1/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo= @@ -175,11 +168,8 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0 h1:TrB8swr/68K7m9CcGut2g3UOihhbcbiMAYiuTXdEih4= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY= github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-redis/redis v6.15.7+incompatible h1:3skhDh95XQMpnqeqNftPkQD9jL9e5e36z/1SUm6dy1U= -github.com/go-redis/redis v6.15.7+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= github.com/go-redis/redis/v8 v8.8.2 h1:O/NcHqobw7SEptA0yA6up6spZVFtwE06SXM8rgLtsP8= github.com/go-redis/redis/v8 v8.8.2/go.mod h1:F7resOH5Kdug49Otu24RjHWwgK7u9AmtqWMnCV1iP5Y= github.com/go-restit/lzjson v0.0.0-20161206095556-efe3c53acc68 h1:QR2R74UbwMtnEVGVvNfcx6mQmWGgN8abQeXOy92pQIo= @@ -188,10 +178,8 @@ github.com/go-sql-driver/mysql v1.4.0 h1:7LxgVwFb2hIQtMm87NdgAVfXjnt4OePseqT1tKx github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= -github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/gofiber/fiber/v2 v2.8.0 h1:BdWvZmg/WY/Vjtjm38aXOp1Lks1BhuyS2b7lSWSPAzk= -github.com/gofiber/fiber/v2 v2.8.0/go.mod h1:Ah3IJikrKNRepl/HuVawppS25X7FWohwfCSRn7kJG28= +github.com/gofiber/fiber/v2 v2.9.0 h1:sZsTKlbyGGZ0UdTUn3ItQv5J9FTQUc4J3OS+03lE5m0= +github.com/gofiber/fiber/v2 v2.9.0/go.mod h1:Ah3IJikrKNRepl/HuVawppS25X7FWohwfCSRn7kJG28= github.com/gogo/googleapis v1.1.0 h1:kFkMAZBNAn4j7K0GiZr8cRYzejq68VbheufiV3YuyFI= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -225,8 +213,8 @@ github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8l github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/flatbuffers v1.12.0 h1:/PtAHvnBY4Kqnx/xCQ3OIV9uYcSFGScBsWI3Oogeh6w= -github.com/google/flatbuffers v1.12.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= +github.com/google/flatbuffers v1.12.1 h1:MVlul7pQNoDzWRLTw5imwYsl+usrS1TXG2H4jg6ImGw= +github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -248,7 +236,6 @@ github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/gopherjs/gopherjs v0.0.0-20180825215210-0210a2f0f73c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 h1:l5lAOZEym3oK3SQ2HBHWsJUfbNBiTXJDeW2QDxw9AQ0= github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -258,7 +245,6 @@ github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= -github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -329,13 +315,11 @@ github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024 h1:rBMNdlhTLzJjJSDIjNEXX1Pz3Hmwmz91v+zycvx9PJc= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= @@ -365,11 +349,9 @@ github.com/lightstep/lightstep-tracer-go v0.18.1 h1:vi1F1IQ8N7hNWytK9DpJsUfQhGuN github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/lyft/protoc-gen-validate v0.0.13 h1:KNt/RhmQTOLr7Aj8PsJ7mTronaFyx80mRTT9qF261dA= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= -github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= @@ -377,20 +359,16 @@ github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= -github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= -github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/miekg/dns v1.0.14 h1:9jZdLNd/P4+SfEJ0TNyxYpsK8N4GtfylBLqtbYN1sbA= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/gox v0.4.0 h1:lfGJxY7ToLJQjHHwi0EX6uYBdK78egf954SQl13PQJc= @@ -430,18 +408,15 @@ github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQ github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FWnp+qbPhuoO21uA= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.15.0 h1:1V1NfVQR87RtWAgp1lv9JZJ5Jap+XFGKPi00andXGi4= github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.5 h1:7n6FEkpFmfCoo2t+YYqXH0evK+a9ICQz0xcAy9dYcaQ= github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48= @@ -530,7 +505,6 @@ github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da h1:p3Vo3i64TCL github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUtVbo7ada43DJhG55ua/hjS5I= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= -github.com/shirou/gopsutil v2.20.7+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/gopsutil v3.21.3+incompatible h1:uenXGGa8ESCQq+dbgtl916dmg6PSAz2cXov0uORQ9v8= github.com/shirou/gopsutil v3.21.3+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= @@ -539,11 +513,9 @@ github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPx github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= -github.com/smartystreets/assertions v0.0.0-20180820201707-7c9eb446e3cf/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v1.1.1 h1:T/YLemO5Yp7KPzS+lVtu+WsHn8yoSwTfItdAd1r3cck= github.com/smartystreets/assertions v1.1.1/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= -github.com/smartystreets/goconvey v0.0.0-20180222194500-ef6db91d284a/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= @@ -558,31 +530,20 @@ github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= -github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8= -github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk= github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spiral/broadcast-ws v1.1.3 h1:UmCQM1XqziDPTzkZfMJ30y48I2+W3RiJScqnoyb8Yn4= -github.com/spiral/broadcast-ws v1.1.3/go.mod h1:NDGHyYe1uUwQO2JvYWh4/8z/YwbjDrY9kC3ul4/BwEs= -github.com/spiral/broadcast/v2 v2.0.5 h1:UAjd5ZVw9wNZI5BJ41n3MQ0Ogg+G4qZEIjAcTZkXQno= -github.com/spiral/broadcast/v2 v2.0.5/go.mod h1:0PahMGr/sugo9LPB1lIeSB/QD5RAvluu8w55umLXP98= github.com/spiral/endure v1.0.1 h1:JHXHHPDiet5Cfx8i2KiC+ayqACmK5Sw0fxNE/QpIuWM= github.com/spiral/endure v1.0.1/go.mod h1:+gB0/jI9tXdHgv0x4P9vXLER8fLgwt9a7aPi0QZeJHE= github.com/spiral/errors v1.0.5/go.mod h1:SwMSZVdZkkJVgXNNafccqOaxWg0XPzVU/dEdUEInE0o= github.com/spiral/errors v1.0.9 h1:RcVZ7a1RYkaT3HWFGDuQiDB02pG6yqh7715Uwd7urwM= github.com/spiral/errors v1.0.9/go.mod h1:SwMSZVdZkkJVgXNNafccqOaxWg0XPzVU/dEdUEInE0o= -github.com/spiral/goridge/v2 v2.4.6 h1:9u/mrxCtOSy0lnumrpPCSOlGBX/Vprid/hFsnzWrd6k= -github.com/spiral/goridge/v2 v2.4.6/go.mod h1:mYjL+Ny7nVfLqjRwIYV2pUSQ61eazvVclHII6FfZfYc= github.com/spiral/goridge/v3 v3.0.1 h1:mWo6hVEDJV3nRwsszx9y262CtrLQNojbONF4ikvKCBg= github.com/spiral/goridge/v3 v3.0.1/go.mod h1:rYfsBwigGneLgYJTIh5urotnH63I5O+p6ZcVq7xc1lY= -github.com/spiral/roadrunner v1.9.2 h1:jGtXs3r5fevdbrkDF8BdFxEY4rIZwplnns1oWj7Vyw8= -github.com/spiral/roadrunner v1.9.2/go.mod h1:Q1al1YGjs7ZHVkAA7+gUKM0rwk6XWG07G0UjyjjuK+0= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271 h1:WhxRHzgeVGETMlmVfqhRn8RIeeNoPr2Czh33I4Zdccw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= @@ -606,7 +567,6 @@ github.com/tklauser/numcpus v0.2.1/go.mod h1:9aU+wOc6WjUIZEwWMP62PL/41d65P+iks1g github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= @@ -620,8 +580,6 @@ github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaU github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= -github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= -github.com/yookoala/gofast v0.4.0/go.mod h1:rfbkoKaQG1bnuTUZcmV3vAlnfpF4FTq8WbQJf2vcpg8= github.com/yookoala/gofast v0.6.0 h1:E5x2acfUD7GkzCf8bmIMwnV10VxDy5tUCHc5LGhluwc= github.com/yookoala/gofast v0.6.0/go.mod h1:OJU201Q6HCaE1cASckaTbMm3KB6e0cZxK0mgqfwOKvQ= github.com/yuin/goldmark v1.2.1 h1:ruQGxdhGHe7FWOJPT0mKs5+pD2Xs1Bm/kdGlHO04FmM= @@ -659,8 +617,9 @@ go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= -go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec= +go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= @@ -716,12 +675,10 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= @@ -798,7 +755,6 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180726210403-bfb5194568d3/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -902,8 +858,9 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/pkg/pool/static_pool.go b/pkg/pool/static_pool.go index 54192262..d57cc95c 100755 --- a/pkg/pool/static_pool.go +++ b/pkg/pool/static_pool.go @@ -170,6 +170,10 @@ func (sp *StaticPool) Exec(p payload.Payload) (payload.Payload, error) { // Be careful, sync with pool.Exec method func (sp *StaticPool) execWithTTL(ctx context.Context, p payload.Payload) (payload.Payload, error) { const op = errors.Op("static_pool_exec_with_context") + if sp.cfg.Debug { + return sp.execDebugWithTTL(ctx, p) + } + ctxAlloc, cancel := context.WithTimeout(ctx, sp.cfg.AllocateTimeout) defer cancel() w, err := sp.getWorker(ctxAlloc, op) @@ -243,7 +247,6 @@ func defaultErrEncoder(sp *StaticPool) ErrorEncoder { return func(err error, w worker.BaseProcess) (payload.Payload, error) { const op = errors.Op("error encoder") // just push event if on any stage was timeout error - switch { case errors.Is(errors.ExecTTL, err): sp.events.Push(events.PoolEvent{Event: events.EventExecTTL, Payload: errors.E(op, err)}) @@ -296,14 +299,31 @@ func (sp *StaticPool) newPoolAllocator(ctx context.Context, timeout time.Duratio } } +// execDebug used when debug mode was not set and exec_ttl is 0 func (sp *StaticPool) execDebug(p payload.Payload) (payload.Payload, error) { sw, err := sp.allocator() if err != nil { return payload.Payload{}, err } + // redirect call to the workers exec method (without ttl) r, err := sw.Exec(p) + if stopErr := sw.Stop(); stopErr != nil { + sp.events.Push(events.WorkerEvent{Event: events.EventWorkerError, Worker: sw, Payload: err}) + } + + return r, err +} + +// execDebugWithTTL used when user set debug mode and exec_ttl +func (sp *StaticPool) execDebugWithTTL(ctx context.Context, p payload.Payload) (payload.Payload, error) { + sw, err := sp.allocator() + if err != nil { + return payload.Payload{}, err + } + // redirect call to the worker with TTL + r, err := sw.ExecWithTTL(ctx, p) if stopErr := sw.Stop(); stopErr != nil { sp.events.Push(events.WorkerEvent{Event: events.EventWorkerError, Worker: sw, Payload: err}) } diff --git a/pkg/pool/static_pool_test.go b/pkg/pool/static_pool_test.go index bf7f10e0..6667bfea 100755 --- a/pkg/pool/static_pool_test.go +++ b/pkg/pool/static_pool_test.go @@ -647,7 +647,7 @@ func Benchmark_Pool_Echo_Replaced(b *testing.B) { } // BenchmarkToStringUnsafe-12 566317729 1.91 ns/op 0 B/op 0 allocs/op -// inline BenchmarkToStringUnsafe-12 1000000000 0.295 ns/op 0 B/op 0 allocs/op +// BenchmarkToStringUnsafe-32 1000000000 0.4434 ns/op 0 B/op 0 allocs/op func BenchmarkToStringUnsafe(b *testing.B) { testPayload := []byte("falsflasjlifjwpoihejfoiwejow{}{}{}{}jelfjasjfhwaopiehjtopwhtgohrgouahsgkljasdlfjasl;fjals;jdflkndgouwhetopwqhjtojfalsflasjlifjwpoihejfoiwejow{}{}{}{}jelfjasjfhwaopiehjtopwhtgohrgouahsgkljasdlfjasl;fjals;jdflkndgouwhetopwqhjtojfalsflasjlifjwpoihejfoiwejow{}{}{}{}jelfjasjfhwaopiehjtopwhtgohrgouahsgkljasdlfjasl;fjals;jdflkndgouwhetopwqhjtojfalsflasjlifjwpoihejfoiwejow{}{}{}{}jelfjasjfhwaopiehjtopwhtgohrgouahsgkljasdlfjasl;fjals;jdflkndgouwhetopwqhjtojfalsflasjlifjwpoihejfoiwejow{}{}{}{}jelfjasjfhwaopiehjtopwhtgohrgouahsgkljasdlfjasl;fjals;jdflkndgouwhetopwqhjtojfalsflasjlifjwpoihejfoiwejow{}{}{}{}jelfjasjfhwaopiehjtopwhtgohrgouahsgkljasdlfjasl;fjals;jdflkndgouwhetopwqhjtojfalsflasjlifjwpoihejfoiwejow{}{}{}{}jelfjasjfhwaopiehjtopwhtgohrgouahsgkljasdlfjasl;fjals;jdflkndgouwhetopwqhjtoj") b.ResetTimer() @@ -659,7 +659,7 @@ func BenchmarkToStringUnsafe(b *testing.B) { } } -// BenchmarkToStringSafe-12 28584489 39.1 ns/op 112 B/op 1 allocs/op +// BenchmarkToStringSafe-32 8017846 182.5 ns/op 896 B/op 1 allocs/op // inline BenchmarkToStringSafe-12 28926276 46.6 ns/op 128 B/op 1 allocs/op func BenchmarkToStringSafe(b *testing.B) { testPayload := []byte("falsflasjlifjwpoihejfoiwejow{}{}{}{}jelfjasjfhwaopiehjtopwhtgohrgouahsgkljasdlfjasl;fjals;jdflkndgouwhetopwqhjtojfalsflasjlifjwpoihejfoiwejow{}{}{}{}jelfjasjfhwaopiehjtopwhtgohrgouahsgkljasdlfjasl;fjals;jdflkndgouwhetopwqhjtojfalsflasjlifjwpoihejfoiwejow{}{}{}{}jelfjasjfhwaopiehjtopwhtgohrgouahsgkljasdlfjasl;fjals;jdflkndgouwhetopwqhjtojfalsflasjlifjwpoihejfoiwejow{}{}{}{}jelfjasjfhwaopiehjtopwhtgohrgouahsgkljasdlfjasl;fjals;jdflkndgouwhetopwqhjtojfalsflasjlifjwpoihejfoiwejow{}{}{}{}jelfjasjfhwaopiehjtopwhtgohrgouahsgkljasdlfjasl;fjals;jdflkndgouwhetopwqhjtojfalsflasjlifjwpoihejfoiwejow{}{}{}{}jelfjasjfhwaopiehjtopwhtgohrgouahsgkljasdlfjasl;fjals;jdflkndgouwhetopwqhjtojfalsflasjlifjwpoihejfoiwejow{}{}{}{}jelfjasjfhwaopiehjtopwhtgohrgouahsgkljasdlfjasl;fjals;jdflkndgouwhetopwqhjtoj") diff --git a/pkg/pool/supervisor_test.go b/pkg/pool/supervisor_test.go index d7e97fdd..dc307c33 100644 --- a/pkg/pool/supervisor_test.go +++ b/pkg/pool/supervisor_test.go @@ -53,6 +53,34 @@ func TestSupervisedPool_Exec(t *testing.T) { p.Destroy(context.Background()) } +// This test should finish without freezes +func TestSupervisedPool_ExecWithDebugMode(t *testing.T) { + var cfgSupervised = cfgSupervised + cfgSupervised.Debug = true + + ctx := context.Background() + p, err := Initialize( + ctx, + func() *exec.Cmd { return exec.Command("php", "../../tests/memleak.php", "pipes") }, + pipe.NewPipeFactory(), + cfgSupervised, + ) + + assert.NoError(t, err) + assert.NotNil(t, p) + + for i := 0; i < 100; i++ { + time.Sleep(time.Millisecond * 100) + _, err = p.Exec(payload.Payload{ + Context: []byte(""), + Body: []byte("foo"), + }) + assert.NoError(t, err) + } + + p.Destroy(context.Background()) +} + func TestSupervisedPool_ExecTTL_TimedOut(t *testing.T) { var cfgExecTTL = Config{ NumWorkers: uint64(1), diff --git a/plugins/http/config/http.go b/plugins/http/config/http.go index 59735e2e..8b63395f 100644 --- a/plugins/http/config/http.go +++ b/plugins/http/config/http.go @@ -33,9 +33,6 @@ type HTTP struct { // Uploads configures uploads configuration. Uploads *Uploads `mapstructure:"uploads"` - // static configuration - Static *Static `mapstructure:"static"` - // Pool configures worker pool. Pool *poolImpl.Config `mapstructure:"pool"` @@ -103,16 +100,6 @@ func (c *HTTP) InitDefaults() error { c.SSLConfig.Address = "127.0.0.1:443" } - // static files - if c.Static != nil { - if c.Static.Pattern == "" { - c.Static.Pattern = "/static/" - } - if c.Static.Dir == "" { - c.Static.Dir = "." - } - } - err := c.HTTP2Config.InitDefaults() if err != nil { return err @@ -189,13 +176,5 @@ func (c *HTTP) Valid() error { } } - // validate static - if c.Static != nil { - err := c.Static.Valid() - if err != nil { - return errors.E(op, err) - } - } - return nil } diff --git a/plugins/http/config/static.go b/plugins/http/config/static.go deleted file mode 100644 index 4b7b3a9b..00000000 --- a/plugins/http/config/static.go +++ /dev/null @@ -1,58 +0,0 @@ -package config - -import ( - "os" - - "github.com/spiral/errors" -) - -// Static describes file location and controls access to them. -type Static struct { - // Dir contains name of directory to control access to. - // Default - "." - Dir string - - // HTTP pattern, where to serve static files - // for example - `/static/`, `/my-files/static/`, etc - // Default - /static/ - Pattern string - - // CalculateEtag can be true/false and used to calculate etag for the static - CalculateEtag bool `mapstructure:"calculate_etag"` - - // Weak etag `W/` - Weak bool - - // forbid specifies list of file extensions which are forbidden for access. - // example: .php, .exe, .bat, .htaccess and etc. - Forbid []string - - // Allow specifies list of file extensions which are allowed for access. - // example: .php, .exe, .bat, .htaccess and etc. - Allow []string - - // Request headers to add to every static. - Request map[string]string - - // Response headers to add to every static. - Response map[string]string -} - -// Valid returns nil if config is valid. -func (c *Static) Valid() error { - const op = errors.Op("static_plugin_valid") - st, err := os.Stat(c.Dir) - if err != nil { - if os.IsNotExist(err) { - return errors.E(op, errors.Errorf("root directory '%s' does not exists", c.Dir)) - } - - return err - } - - if !st.IsDir() { - return errors.E(op, errors.Errorf("invalid root directory '%s'", c.Dir)) - } - - return nil -} diff --git a/plugins/http/plugin.go b/plugins/http/plugin.go index 3b9c12ea..2b68bbe5 100644 --- a/plugins/http/plugin.go +++ b/plugins/http/plugin.go @@ -5,9 +5,6 @@ import ( "fmt" "log" "net/http" - "os" - "path/filepath" - "strings" "sync" "github.com/hashicorp/go-multierror" @@ -16,11 +13,10 @@ import ( "github.com/spiral/roadrunner/v2/pkg/pool" "github.com/spiral/roadrunner/v2/pkg/process" "github.com/spiral/roadrunner/v2/pkg/worker" - handler "github.com/spiral/roadrunner/v2/pkg/worker_handler" "github.com/spiral/roadrunner/v2/plugins/config" "github.com/spiral/roadrunner/v2/plugins/http/attributes" httpConfig "github.com/spiral/roadrunner/v2/plugins/http/config" - "github.com/spiral/roadrunner/v2/plugins/http/static" + handler "github.com/spiral/roadrunner/v2/plugins/http/worker_handler" "github.com/spiral/roadrunner/v2/plugins/logger" "github.com/spiral/roadrunner/v2/plugins/server" "github.com/spiral/roadrunner/v2/plugins/status" @@ -136,7 +132,7 @@ func (s *Plugin) Serve() chan error { return errCh } -func (s *Plugin) serve(errCh chan error) { //nolint:gocognit +func (s *Plugin) serve(errCh chan error) { var err error const op = errors.Op("http_plugin_serve") s.pool, err = s.server.NewWorkerPool(context.Background(), pool.Config{ @@ -165,56 +161,11 @@ func (s *Plugin) serve(errCh chan error) { //nolint:gocognit s.handler.AddListener(s.logCallback) - // Create new HTTP Multiplexer - mux := http.NewServeMux() - - // if we have static, handler here, create a fileserver - if s.cfg.Static != nil { - h := http.FileServer(static.FS(s.cfg.Static)) - // Static files handler - mux.HandleFunc(s.cfg.Static.Pattern, func(w http.ResponseWriter, r *http.Request) { - if s.cfg.Static.Request != nil { - for k, v := range s.cfg.Static.Request { - r.Header.Add(k, v) - } - } - - if s.cfg.Static.Response != nil { - for k, v := range s.cfg.Static.Response { - w.Header().Set(k, v) - } - } - - // calculate etag for the resource - if s.cfg.Static.CalculateEtag { - // do not allow paths like ../../resource - // only specified folder and resources in it - // https://lgtm.com/rules/1510366186013/ - if strings.Contains(r.URL.Path, "..") { - w.WriteHeader(http.StatusForbidden) - return - } - f, errS := os.Open(filepath.Join(s.cfg.Static.Dir, r.URL.Path)) - if errS != nil { - s.log.Warn("error opening file to calculate the Etag", "provided path", r.URL.Path) - } - - // Set etag value to the ResponseWriter - static.SetEtag(s.cfg.Static, f, w) - } - - h.ServeHTTP(w, r) - }) - } - - // handle main route - mux.HandleFunc("/", s.ServeHTTP) - if s.cfg.EnableHTTP() { if s.cfg.EnableH2C() { - s.http = &http.Server{Handler: h2c.NewHandler(mux, &http2.Server{}), ErrorLog: s.stdLog} + s.http = &http.Server{Handler: h2c.NewHandler(s, &http2.Server{}), ErrorLog: s.stdLog} } else { - s.http = &http.Server{Handler: mux, ErrorLog: s.stdLog} + s.http = &http.Server{Handler: s, ErrorLog: s.stdLog} } } @@ -238,7 +189,7 @@ func (s *Plugin) serve(errCh chan error) { //nolint:gocognit } if s.cfg.EnableFCGI() { - s.fcgi = &http.Server{Handler: mux, ErrorLog: s.stdLog} + s.fcgi = &http.Server{Handler: s, ErrorLog: s.stdLog} } // start http, https and fcgi servers if requested in the config diff --git a/plugins/http/serve.go b/plugins/http/serve.go index 26fccf79..734860f5 100644 --- a/plugins/http/serve.go +++ b/plugins/http/serve.go @@ -231,12 +231,24 @@ func (s *Plugin) tlsAddr(host string, forcePort bool) string { return host } +// static plugin name +const static string = "static" + func applyMiddlewares(server *http.Server, middlewares map[string]Middleware, order []string, log logger.Logger) { for i := len(order) - 1; i >= 0; i-- { + // set static last in the row + if order[i] == static { + continue + } if mdwr, ok := middlewares[order[i]]; ok { server.Handler = mdwr.Middleware(server.Handler) } else { log.Warn("requested middleware does not exist", "requested", order[i]) } } + + // set static if exists + if mdwr, ok := middlewares[static]; ok { + server.Handler = mdwr.Middleware(server.Handler) + } } diff --git a/plugins/http/static/static.go b/plugins/http/static/static.go deleted file mode 100644 index d0278466..00000000 --- a/plugins/http/static/static.go +++ /dev/null @@ -1,88 +0,0 @@ -package static - -import ( - "io/fs" - "net/http" - "path/filepath" - "strings" - - httpConfig "github.com/spiral/roadrunner/v2/plugins/http/config" -) - -type ExtensionFilter struct { - allowed map[string]struct{} - forbidden map[string]struct{} -} - -func NewExtensionFilter(allow, forbid []string) *ExtensionFilter { - ef := &ExtensionFilter{ - allowed: make(map[string]struct{}, len(allow)), - forbidden: make(map[string]struct{}, len(forbid)), - } - - for i := 0; i < len(forbid); i++ { - // skip empty lines - if forbid[i] == "" { - continue - } - ef.forbidden[forbid[i]] = struct{}{} - } - - for i := 0; i < len(allow); i++ { - // skip empty lines - if allow[i] == "" { - continue - } - ef.allowed[allow[i]] = struct{}{} - } - - // check if any forbidden items presented in the allowed - // if presented, delete such items from allowed - for k := range ef.allowed { - if _, ok := ef.forbidden[k]; ok { - delete(ef.allowed, k) - } - } - - return ef -} - -type FileSystem struct { - ef *ExtensionFilter - // embedded - http.FileSystem -} - -// Open wrapper around http.FileSystem Open method, name here is the name of the -func (f FileSystem) Open(name string) (http.File, error) { - file, err := f.FileSystem.Open(name) - if err != nil { - return nil, err - } - - fstat, err := file.Stat() - if err != nil { - return nil, fs.ErrNotExist - } - - if fstat.IsDir() { - return nil, fs.ErrPermission - } - - ext := strings.ToLower(filepath.Ext(fstat.Name())) - if _, ok := f.ef.forbidden[ext]; ok { - return nil, fs.ErrPermission - } - - // if file extension is allowed, append it to the FileInfo slice - if _, ok := f.ef.allowed[ext]; ok { - return file, nil - } - - return nil, fs.ErrNotExist -} - -// FS is a constructor for the http.FileSystem -func FS(config *httpConfig.Static) http.FileSystem { - return FileSystem{NewExtensionFilter(config.Allow, config.Forbid), http.Dir(config.Dir)} -} diff --git a/plugins/server/config.go b/plugins/server/config.go index a4b0d91c..00ce4140 100644 --- a/plugins/server/config.go +++ b/plugins/server/config.go @@ -4,7 +4,7 @@ import ( "time" ) -// All config (.rr.yaml) +// Config All config (.rr.yaml) // For other section use pointer to distinguish between `empty` and `not present` type Config struct { // Server config section diff --git a/plugins/server/plugin.go b/plugins/server/plugin.go index 320da372..ef77f7ab 100644 --- a/plugins/server/plugin.go +++ b/plugins/server/plugin.go @@ -58,8 +58,7 @@ func (server *Plugin) Name() string { } // Available interface implementation -func (server *Plugin) Available() { -} +func (server *Plugin) Available() {} // Serve (Start) server plugin (just a mock here to satisfy interface) func (server *Plugin) Serve() chan error { diff --git a/plugins/static/config.go b/plugins/static/config.go new file mode 100644 index 00000000..c3f9c17d --- /dev/null +++ b/plugins/static/config.go @@ -0,0 +1,55 @@ +package static + +import ( + "os" + + "github.com/spiral/errors" +) + +// Config describes file location and controls access to them. +type Config struct { + Static *struct { + // Dir contains name of directory to control access to. + // Default - "." + Dir string + + // CalculateEtag can be true/false and used to calculate etag for the static + CalculateEtag bool `mapstructure:"calculate_etag"` + + // Weak etag `W/` + Weak bool + + // forbid specifies list of file extensions which are forbidden for access. + // example: .php, .exe, .bat, .htaccess and etc. + Forbid []string + + // Allow specifies list of file extensions which are allowed for access. + // example: .php, .exe, .bat, .htaccess and etc. + Allow []string + + // Request headers to add to every static. + Request map[string]string + + // Response headers to add to every static. + Response map[string]string + } +} + +// Valid returns nil if config is valid. +func (c *Config) Valid() error { + const op = errors.Op("static_plugin_valid") + st, err := os.Stat(c.Static.Dir) + if err != nil { + if os.IsNotExist(err) { + return errors.E(op, errors.Errorf("root directory '%s' does not exists", c.Static.Dir)) + } + + return err + } + + if !st.IsDir() { + return errors.E(op, errors.Errorf("invalid root directory '%s'", c.Static.Dir)) + } + + return nil +} diff --git a/plugins/http/static/etag.go b/plugins/static/etag.go index c457b95e..5ee0d2f3 100644 --- a/plugins/http/static/etag.go +++ b/plugins/static/etag.go @@ -4,9 +4,7 @@ import ( "hash/crc32" "io" "net/http" - "os" - httpConfig "github.com/spiral/roadrunner/v2/plugins/http/config" "github.com/spiral/roadrunner/v2/utils" ) @@ -18,7 +16,22 @@ var weakPrefix = []byte(`W/`) // CRC32 table var crc32q = crc32.MakeTable(0x48D90782) -func SetEtag(cfg *httpConfig.Static, f *os.File, w http.ResponseWriter) { +// SetEtag sets etag for the file +func SetEtag(weak bool, f http.File, name string, w http.ResponseWriter) { + // preallocate + calculatedEtag := make([]byte, 0, 64) + + // write weak + if weak { + calculatedEtag = append(calculatedEtag, weakPrefix...) + calculatedEtag = append(calculatedEtag, '"') + calculatedEtag = appendUint(calculatedEtag, crc32.Checksum(utils.AsBytes(name), crc32q)) + calculatedEtag = append(calculatedEtag, '"') + + w.Header().Set(etag, utils.AsString(calculatedEtag)) + return + } + // read the file content body, err := io.ReadAll(f) if err != nil { @@ -30,14 +43,6 @@ func SetEtag(cfg *httpConfig.Static, f *os.File, w http.ResponseWriter) { return } - // preallocate - calculatedEtag := make([]byte, 0, 64) - - // write weak - if cfg.Weak { - calculatedEtag = append(calculatedEtag, weakPrefix...) - } - calculatedEtag = append(calculatedEtag, '"') calculatedEtag = appendUint(calculatedEtag, uint32(len(body))) calculatedEtag = append(calculatedEtag, '-') diff --git a/plugins/static/plugin.go b/plugins/static/plugin.go new file mode 100644 index 00000000..f6d9a0f2 --- /dev/null +++ b/plugins/static/plugin.go @@ -0,0 +1,188 @@ +package static + +import ( + "net/http" + "path" + "strings" + + "github.com/spiral/errors" + "github.com/spiral/roadrunner/v2/plugins/config" + "github.com/spiral/roadrunner/v2/plugins/logger" +) + +// PluginName contains default service name. +const PluginName = "static" + +const RootPluginName = "http" + +// Plugin serves static files. Potentially convert into middleware? +type Plugin struct { + // server configuration (location, forbidden files and etc) + cfg *Config + + log logger.Logger + + // root is initiated http directory + root http.Dir + + // file extensions which are allowed to be served + allowedExtensions map[string]struct{} + + // file extensions which are forbidden to be served + forbiddenExtensions map[string]struct{} +} + +// Init must return configure service and return true if service hasStatus enabled. Must return error in case of +// misconfiguration. Services must not be used without proper configuration pushed first. +func (s *Plugin) Init(cfg config.Configurer, log logger.Logger) error { + const op = errors.Op("static_plugin_init") + if !cfg.Has(RootPluginName) { + return errors.E(op, errors.Disabled) + } + + err := cfg.UnmarshalKey(RootPluginName, &s.cfg) + if err != nil { + return errors.E(op, errors.Disabled, err) + } + + if s.cfg.Static == nil { + return errors.E(op, errors.Disabled) + } + + s.log = log + s.root = http.Dir(s.cfg.Static.Dir) + + err = s.cfg.Valid() + if err != nil { + return errors.E(op, err) + } + + // create 2 hashmaps with the allowed and forbidden file extensions + s.allowedExtensions = make(map[string]struct{}, len(s.cfg.Static.Allow)) + s.forbiddenExtensions = make(map[string]struct{}, len(s.cfg.Static.Forbid)) + + // init forbidden + for i := 0; i < len(s.cfg.Static.Forbid); i++ { + // skip empty lines + if s.cfg.Static.Forbid[i] == "" { + continue + } + s.forbiddenExtensions[s.cfg.Static.Forbid[i]] = struct{}{} + } + + // init allowed + for i := 0; i < len(s.cfg.Static.Allow); i++ { + // skip empty lines + if s.cfg.Static.Allow[i] == "" { + continue + } + s.allowedExtensions[s.cfg.Static.Allow[i]] = struct{}{} + } + + // check if any forbidden items presented in the allowed + // if presented, delete such items from allowed + for k := range s.forbiddenExtensions { + delete(s.allowedExtensions, k) + } + + // at this point we have distinct allowed and forbidden hashmaps, also with alwaysServed + return nil +} + +func (s *Plugin) Name() string { + return PluginName +} + +// Middleware must return true if request/response pair is handled within the middleware. +func (s *Plugin) Middleware(next http.Handler) http.Handler { + // Define the http.HandlerFunc + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // do not allow paths like ../../resource + // only specified folder and resources in it + // https://lgtm.com/rules/1510366186013/ + if strings.Contains(r.URL.Path, "..") { + w.WriteHeader(http.StatusForbidden) + return + } + + if s.cfg.Static.Request != nil { + for k, v := range s.cfg.Static.Request { + r.Header.Add(k, v) + } + } + + if s.cfg.Static.Response != nil { + for k, v := range s.cfg.Static.Response { + w.Header().Set(k, v) + } + } + + // first - create a proper file path + fPath := path.Clean(r.URL.Path) + ext := strings.ToLower(path.Ext(fPath)) + + // check that file extension in the forbidden list + if _, ok := s.forbiddenExtensions[ext]; ok { + s.log.Debug("file extension is forbidden", "ext", ext) + next.ServeHTTP(w, r) + return + } + + // if we have some allowed extensions, we should check them + // if not - all extensions allowed except forbidden + if len(s.allowedExtensions) > 0 { + // not found in allowed + if _, ok := s.allowedExtensions[ext]; !ok { + next.ServeHTTP(w, r) + return + } + + // file extension allowed + } + + // ok, file is not in the forbidden list + // Stat it and get file info + f, err := s.root.Open(fPath) + if err != nil { + // else no such file, show error in logs only in debug mode + s.log.Debug("no such file or directory", "error", err) + // pass request to the worker + next.ServeHTTP(w, r) + return + } + + // at high confidence there is should not be an error + // because we stat-ed the path previously and know, that that is file (not a dir), and it exists + finfo, err := f.Stat() + if err != nil { + // else no such file, show error in logs only in debug mode + s.log.Debug("no such file or directory", "error", err) + // pass request to the worker + next.ServeHTTP(w, r) + return + } + + defer func() { + err = f.Close() + if err != nil { + s.log.Error("file close error", "error", err) + } + }() + + // if provided path to the dir, do not serve the dir, but pass the request to the worker + if finfo.IsDir() { + s.log.Debug("possible path to dir provided") + // pass request to the worker + next.ServeHTTP(w, r) + return + } + + // set etag + if s.cfg.Static.CalculateEtag { + SetEtag(s.cfg.Static.Weak, f, finfo.Name(), w) + } + + // we passed all checks - serve the file + http.ServeContent(w, r, finfo.Name(), finfo.ModTime(), f) + }) +} diff --git a/tests/plugins/http/configs/.rr-http-static-etags.yaml b/tests/plugins/http/configs/.rr-http-static-etags.yaml index e18c50dd..b09de0f4 100644 --- a/tests/plugins/http/configs/.rr-http-static-etags.yaml +++ b/tests/plugins/http/configs/.rr-http-static-etags.yaml @@ -15,8 +15,7 @@ http: uploads: forbid: [ ".php", ".exe", ".bat" ] static: - dir: "../../../" - pattern: "/tests/" + dir: "../../../tests" forbid: [ "" ] allow: [ ".txt", ".php" ] calculate_etag: true diff --git a/tests/plugins/http/configs/.rr-http-static-files.yaml b/tests/plugins/http/configs/.rr-http-static-files.yaml index 5d8b50e8..18c6107d 100644 --- a/tests/plugins/http/configs/.rr-http-static-files.yaml +++ b/tests/plugins/http/configs/.rr-http-static-files.yaml @@ -15,8 +15,7 @@ http: uploads: forbid: [ ".php", ".exe", ".bat" ] static: - dir: "../../../" - pattern: "/tests/" + dir: "../../../tests" allow: [ ".ico" ] forbid: [ ".php", ".htaccess" ] @@ -25,6 +24,7 @@ http: max_jobs: 0 allocate_timeout: 60s destroy_timeout: 60s + logs: mode: development - level: error + level: info diff --git a/tests/plugins/http/configs/.rr-http-static-security.yaml b/tests/plugins/http/configs/.rr-http-static-security.yaml index bbec13f9..e2e3af2a 100644 --- a/tests/plugins/http/configs/.rr-http-static-security.yaml +++ b/tests/plugins/http/configs/.rr-http-static-security.yaml @@ -15,8 +15,7 @@ http: uploads: forbid: [ ".php", ".exe", ".bat" ] static: - dir: "../../../" - pattern: "/tests/" + dir: "../../../tests" forbid: [ "" ] allow: [ ".txt", ".php" ] calculate_etag: true diff --git a/tests/plugins/http/configs/.rr-http-static.yaml b/tests/plugins/http/configs/.rr-http-static.yaml index bbec13f9..e2e3af2a 100644 --- a/tests/plugins/http/configs/.rr-http-static.yaml +++ b/tests/plugins/http/configs/.rr-http-static.yaml @@ -15,8 +15,7 @@ http: uploads: forbid: [ ".php", ".exe", ".bat" ] static: - dir: "../../../" - pattern: "/tests/" + dir: "../../../tests" forbid: [ "" ] allow: [ ".txt", ".php" ] calculate_etag: true diff --git a/tests/plugins/http/http_plugin_test.go b/tests/plugins/http/http_plugin_test.go index 8f76e3ba..128eec26 100644 --- a/tests/plugins/http/http_plugin_test.go +++ b/tests/plugins/http/http_plugin_test.go @@ -30,6 +30,7 @@ import ( "github.com/spiral/roadrunner/v2/plugins/logger" "github.com/spiral/roadrunner/v2/plugins/resetter" "github.com/spiral/roadrunner/v2/plugins/server" + "github.com/spiral/roadrunner/v2/plugins/static" "github.com/spiral/roadrunner/v2/tests/mocks" "github.com/yookoala/gofast" @@ -1578,6 +1579,7 @@ func TestStaticEtagPlugin(t *testing.T) { &server.Plugin{}, &httpPlugin.Plugin{}, &gzip.Plugin{}, + &static.Plugin{}, ) assert.NoError(t, err) @@ -1633,7 +1635,7 @@ func TestStaticEtagPlugin(t *testing.T) { func serveStaticSampleEtag(t *testing.T) { // OK 200 response - b, r, err := get("http://localhost:21603/tests/static/sample.txt") + b, r, err := get("http://localhost:21603/sample.txt") assert.NoError(t, err) assert.Equal(t, "sample\n", b) assert.Equal(t, r.StatusCode, http.StatusOK) @@ -1646,7 +1648,7 @@ func serveStaticSampleEtag(t *testing.T) { Timeout: time.Second * 5, } - parsedURL, _ := url.Parse("http://localhost:21603/tests/static/sample.txt") + parsedURL, _ := url.Parse("http://localhost:21603/sample.txt") req := &http.Request{ Method: http.MethodGet, @@ -1675,6 +1677,7 @@ func TestStaticPluginSecurity(t *testing.T) { &server.Plugin{}, &httpPlugin.Plugin{}, &gzip.Plugin{}, + &static.Plugin{}, ) assert.NoError(t, err) @@ -1804,7 +1807,7 @@ func serveStaticSampleNotAllowedPath(t *testing.T) { _, r, err := get("http://localhost:21603/../../../../tests/../static/sample.txt") assert.NoError(t, err) - assert.Equal(t, r.StatusCode, 200) + assert.Equal(t, 403, r.StatusCode) _ = r.Body.Close() } @@ -1823,6 +1826,7 @@ func TestStaticPlugin(t *testing.T) { &server.Plugin{}, &httpPlugin.Plugin{}, &gzip.Plugin{}, + &static.Plugin{}, ) assert.NoError(t, err) @@ -1879,7 +1883,7 @@ func TestStaticPlugin(t *testing.T) { } func staticHeaders(t *testing.T) { - req, err := http.NewRequest("GET", "http://localhost:21603/tests/client.php", nil) + req, err := http.NewRequest("GET", "http://localhost:21603/client.php", nil) if err != nil { t.Fatal(err) } @@ -1907,7 +1911,7 @@ func staticHeaders(t *testing.T) { } func staticNotForbid(t *testing.T) { - b, r, err := get("http://localhost:21603/tests/client.php") + b, r, err := get("http://localhost:21603/client.php") assert.NoError(t, err) assert.Equal(t, all("../../../tests/client.php"), b) assert.Equal(t, all("../../../tests/client.php"), b) @@ -1915,7 +1919,7 @@ func staticNotForbid(t *testing.T) { } func serveStaticSample(t *testing.T) { - b, r, err := get("http://localhost:21603/tests/static/sample.txt") + b, r, err := get("http://localhost:21603/sample.txt") assert.NoError(t, err) assert.Equal(t, "sample\n", b) _ = r.Body.Close() @@ -1936,6 +1940,7 @@ func TestStaticDisabled_Error(t *testing.T) { &server.Plugin{}, &httpPlugin.Plugin{}, &gzip.Plugin{}, + &static.Plugin{}, ) assert.NoError(t, err) assert.Error(t, cont.Init()) @@ -1956,6 +1961,7 @@ func TestStaticFilesDisabled(t *testing.T) { &server.Plugin{}, &httpPlugin.Plugin{}, &gzip.Plugin{}, + &static.Plugin{}, ) assert.NoError(t, err) @@ -2032,10 +2038,13 @@ func TestStaticFilesForbid(t *testing.T) { mockLogger.EXPECT().Debug("worker destructed", "pid", gomock.Any()).AnyTimes() mockLogger.EXPECT().Debug("worker constructed", "pid", gomock.Any()).AnyTimes() - mockLogger.EXPECT().Debug("201 GET http://localhost:34653/tests/http?hello=world", "remote", "127.0.0.1", "elapsed", gomock.Any()).MinTimes(1) - mockLogger.EXPECT().Debug("201 GET http://localhost:34653/tests/client.XXX?hello=world", "remote", "127.0.0.1", "elapsed", gomock.Any()).MinTimes(1) - mockLogger.EXPECT().Debug("201 GET http://localhost:34653/tests/client.php?hello=world", "remote", "127.0.0.1", "elapsed", gomock.Any()).MinTimes(1) + mockLogger.EXPECT().Debug("201 GET http://localhost:34653/http?hello=world", "remote", "127.0.0.1", "elapsed", gomock.Any()).MinTimes(1) + mockLogger.EXPECT().Debug("201 GET http://localhost:34653/client.XXX?hello=world", "remote", "127.0.0.1", "elapsed", gomock.Any()).MinTimes(1) + mockLogger.EXPECT().Debug("201 GET http://localhost:34653/client.php?hello=world", "remote", "127.0.0.1", "elapsed", gomock.Any()).MinTimes(1) mockLogger.EXPECT().Error("file open error", "error", gomock.Any()).AnyTimes() + mockLogger.EXPECT().Debug("no such file or directory", "error", gomock.Any()).AnyTimes() + mockLogger.EXPECT().Debug("possible path to dir provided").AnyTimes() + mockLogger.EXPECT().Debug("file extension is forbidden", gomock.Any(), gomock.Any()).AnyTimes() mockLogger.EXPECT().Error(gomock.Any(), gomock.Any(), gomock.Any()).AnyTimes() // placeholder for the workerlogerror err = cont.RegisterAll( @@ -2044,6 +2053,7 @@ func TestStaticFilesForbid(t *testing.T) { &server.Plugin{}, &httpPlugin.Plugin{}, &gzip.Plugin{}, + &static.Plugin{}, ) assert.NoError(t, err) @@ -2094,37 +2104,29 @@ func TestStaticFilesForbid(t *testing.T) { t.Run("StaticTestFilesDir", staticTestFilesDir) t.Run("StaticNotFound", staticNotFound) t.Run("StaticFilesForbid", staticFilesForbid) - t.Run("StaticFilesAlways", staticFilesAlways) stopCh <- struct{}{} wg.Wait() } func staticTestFilesDir(t *testing.T) { - b, r, err := get("http://localhost:34653/tests/http?hello=world") + b, r, err := get("http://localhost:34653/http?hello=world") assert.NoError(t, err) - assert.Equal(t, "403 Forbidden\n", b) + assert.Equal(t, "WORLD", b) _ = r.Body.Close() } func staticNotFound(t *testing.T) { - b, _, _ := get("http://localhost:34653/tests/client.XXX?hello=world") //nolint:bodyclose - assert.Equal(t, "404 page not found\n", b) -} - -func staticFilesAlways(t *testing.T) { - _, r, err := get("http://localhost:34653/tests/favicon.ico") - assert.NoError(t, err) - assert.Equal(t, 404, r.StatusCode) - _ = r.Body.Close() + b, _, _ := get("http://localhost:34653/client.XXX?hello=world") //nolint:bodyclose + assert.Equal(t, "WORLD", b) } func staticFilesForbid(t *testing.T) { - b, r, err := get("http://localhost:34653/tests/client.php?hello=world") + b, r, err := get("http://localhost:34653/client.php?hello=world") if err != nil { t.Fatal(err) } - assert.Equal(t, "403 Forbidden\n", b) + assert.Equal(t, "WORLD", b) _ = r.Body.Close() } diff --git a/tests/plugins/server/configs/.rr-no-app-section.yaml b/tests/plugins/server/configs/.rr-no-app-section.yaml index e44eeb56..d28265d5 100644 --- a/tests/plugins/server/configs/.rr-no-app-section.yaml +++ b/tests/plugins/server/configs/.rr-no-app-section.yaml @@ -3,10 +3,10 @@ server: user: "" group: "" env: - "RR_CONFIG": "/some/place/on/the/C134" - "RR_CONFIG2": "C138" + - RR_CONFIG: "/some/place/on/the/C134" + - RR_CONFIG2: "C138" relay: "pipes" relay_timeout: "20s" logs: mode: development - level: error
\ No newline at end of file + level: error diff --git a/tests/plugins/server/configs/.rr-sockets.yaml b/tests/plugins/server/configs/.rr-sockets.yaml index 0bc2d0f9..4c57f36f 100644 --- a/tests/plugins/server/configs/.rr-sockets.yaml +++ b/tests/plugins/server/configs/.rr-sockets.yaml @@ -3,10 +3,10 @@ server: user: "" group: "" env: - "RR_CONFIG": "/some/place/on/the/C134" - "RR_CONFIG2": "C138" + - RR_CONFIG: "/some/place/on/the/C134" + - RR_CONFIG2: "C138" relay: "unix://unix.sock" relay_timeout: "20s" logs: mode: development - level: error
\ No newline at end of file + level: error diff --git a/tests/plugins/server/configs/.rr-tcp.yaml b/tests/plugins/server/configs/.rr-tcp.yaml index f4580460..4582482f 100644 --- a/tests/plugins/server/configs/.rr-tcp.yaml +++ b/tests/plugins/server/configs/.rr-tcp.yaml @@ -3,10 +3,10 @@ server: user: "" group: "" env: - "RR_CONFIG": "/some/place/on/the/C134" - "RR_CONFIG2": "C138" + - RR_CONFIG: "/some/place/on/the/C134" + - RR_CONFIG2: "C138" relay: "tcp://localhost:9999" relay_timeout: "20s" logs: mode: development - level: error
\ No newline at end of file + level: error diff --git a/tests/plugins/server/configs/.rr-wrong-command.yaml b/tests/plugins/server/configs/.rr-wrong-command.yaml index c97d8b7e..9d105d90 100644 --- a/tests/plugins/server/configs/.rr-wrong-command.yaml +++ b/tests/plugins/server/configs/.rr-wrong-command.yaml @@ -3,10 +3,10 @@ server: user: "" group: "" env: - "RR_CONFIG": "/some/place/on/the/C134" - "RR_CONFIG2": "C138" + - RR_CONFIG: "/some/place/on/the/C134" + - RR_CONFIG2: "C138" relay: "pipes" relay_timeout: "20s" logs: mode: development - level: error
\ No newline at end of file + level: error diff --git a/tests/plugins/server/configs/.rr-wrong-relay.yaml b/tests/plugins/server/configs/.rr-wrong-relay.yaml index 9722a487..c4d1edb0 100644 --- a/tests/plugins/server/configs/.rr-wrong-relay.yaml +++ b/tests/plugins/server/configs/.rr-wrong-relay.yaml @@ -3,10 +3,10 @@ server: user: "" group: "" env: - "RR_CONFIG": "/some/place/on/the/C134" - "RR_CONFIG2": "C138" + - RR_CONFIG: "/some/place/on/the/C134" + - RR_CONFIG2: "C138" relay: "pupes" relay_timeout: "20s" logs: mode: development - level: error
\ No newline at end of file + level: error diff --git a/tests/plugins/server/configs/.rr.yaml b/tests/plugins/server/configs/.rr.yaml index e44eeb56..d28265d5 100644 --- a/tests/plugins/server/configs/.rr.yaml +++ b/tests/plugins/server/configs/.rr.yaml @@ -3,10 +3,10 @@ server: user: "" group: "" env: - "RR_CONFIG": "/some/place/on/the/C134" - "RR_CONFIG2": "C138" + - RR_CONFIG: "/some/place/on/the/C134" + - RR_CONFIG2: "C138" relay: "pipes" relay_timeout: "20s" logs: mode: development - level: error
\ No newline at end of file + level: error diff --git a/tests/static/sample.txt b/tests/sample.txt index d64a3d96..d64a3d96 100644 --- a/tests/static/sample.txt +++ b/tests/sample.txt |