From 2c151a42ed58a418dcd42465a77b705d4193315f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 9 May 2022 08:31:27 +0000 Subject: [PATCH] Bump github.com/vulcand/oxy from 1.3.0 to 1.4.0 (#16) --- go.mod | 6 +- go.sum | 29 +-- .../github.com/vulcand/oxy/buffer/buffer.go | 117 +++++---- .../vulcand/oxy/buffer/threshold.go | 33 +-- vendor/github.com/vulcand/oxy/forward/fwd.go | 149 ++++++----- .../github.com/vulcand/oxy/forward/headers.go | 10 +- .../vulcand/oxy/forward/post_config.go | 1 + .../vulcand/oxy/forward/post_config_18.go | 1 + .../github.com/vulcand/oxy/forward/rewrite.go | 6 +- .../vulcand/oxy/internal/holsterv4/LICENSE | 201 +++++++++++++++ .../oxy/internal/holsterv4/clock/README.md | 47 ++++ .../oxy/internal/holsterv4/clock/clock.go | 105 ++++++++ .../internal/holsterv4/clock/clock_mutex.go | 131 ++++++++++ .../oxy/internal/holsterv4/clock/duration.go | 65 +++++ .../oxy/internal/holsterv4/clock/frozen.go | 231 ++++++++++++++++++ .../oxy/internal/holsterv4/clock/go19.go | 106 ++++++++ .../oxy/internal/holsterv4/clock/interface.go | 35 +++ .../oxy/internal/holsterv4/clock/rfc822.go | 119 +++++++++ .../oxy/internal/holsterv4/clock/system.go | 68 ++++++ vendor/github.com/vulcand/oxy/trace/trace.go | 25 +- vendor/github.com/vulcand/oxy/utils/auth.go | 6 +- .../github.com/vulcand/oxy/utils/dumpreq.go | 36 ++- .../github.com/vulcand/oxy/utils/handler.go | 14 +- .../github.com/vulcand/oxy/utils/netutils.go | 39 +-- vendor/github.com/vulcand/oxy/utils/source.go | 14 +- vendor/modules.txt | 9 +- 26 files changed, 1361 insertions(+), 242 deletions(-) create mode 100644 vendor/github.com/vulcand/oxy/internal/holsterv4/LICENSE create mode 100644 vendor/github.com/vulcand/oxy/internal/holsterv4/clock/README.md create mode 100644 vendor/github.com/vulcand/oxy/internal/holsterv4/clock/clock.go create mode 100644 vendor/github.com/vulcand/oxy/internal/holsterv4/clock/clock_mutex.go create mode 100644 vendor/github.com/vulcand/oxy/internal/holsterv4/clock/duration.go create mode 100644 vendor/github.com/vulcand/oxy/internal/holsterv4/clock/frozen.go create mode 100644 vendor/github.com/vulcand/oxy/internal/holsterv4/clock/go19.go create mode 100644 vendor/github.com/vulcand/oxy/internal/holsterv4/clock/interface.go create mode 100644 vendor/github.com/vulcand/oxy/internal/holsterv4/clock/rfc822.go create mode 100644 vendor/github.com/vulcand/oxy/internal/holsterv4/clock/system.go diff --git a/go.mod b/go.mod index feb9f1e..fde403d 100644 --- a/go.mod +++ b/go.mod @@ -16,9 +16,9 @@ require ( github.com/prometheus/common v0.34.0 github.com/prometheus/procfs v0.7.3 // indirect github.com/sirupsen/logrus v1.8.1 - github.com/vulcand/oxy v1.3.0 - golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect - golang.org/x/net v0.0.0-20220412020605-290c469a71a5 // indirect + github.com/vulcand/oxy v1.4.0 + golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f // indirect + golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 // indirect golang.org/x/sys v0.0.0-20220412071739-889880a91fd5 // indirect golang.org/x/term v0.0.0-20220411215600-e5f449aeb171 // indirect google.golang.org/protobuf v1.28.0 // indirect diff --git a/go.sum b/go.sum index 9567e8e..4500808 100644 --- a/go.sum +++ b/go.sum @@ -33,6 +33,7 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= github.com/alecthomas/kingpin v2.2.6+incompatible h1:5svnBTFgJjZvGKyYBtMB0+m5wvrbUHiqye8wRJMlnYI= github.com/alecthomas/kingpin v2.2.6+incompatible/go.mod h1:59OFYbFVLKQKq+mqrL6Rw5bR0c3ACQaawgXx0QYndlE= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -62,8 +63,6 @@ github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XP github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w= -github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -157,10 +156,8 @@ github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyC github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= -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/gravitational/trace v0.0.0-20190726142706-a535a178675f/go.mod h1:RvdOUHE4SHqR3oXlFFKnGzms8a5dugHygGw1bqDstYI= github.com/gravitational/trace v1.1.16-0.20220114165159-14a9a7dd6aaf/go.mod h1:zXqxTI6jXDdKnlf8s+nT+3c8LrwUEy3yNpO4XJL90lA= github.com/gravitational/trace v1.1.18 h1:Ulobib6xd5g1ct+ZC01HPAEvODws7QerjuTY9L4U8pY= github.com/gravitational/trace v1.1.18/go.mod h1:n0ijrq6psJY0sOI/NzLp+xdd8xl79jjwzVOFHDY6+kQ= @@ -169,7 +166,6 @@ github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/jonboulle/clockwork v0.2.3 h1:N1FyPPFU62shxAPCrBvOMoqlr6gt7bAYKDASFu+JFaE= github.com/jonboulle/clockwork v0.2.3/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= @@ -191,12 +187,8 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/mailgun/minheap v0.0.0-20170619185613-3dbe6c6bf55f/go.mod h1:V3EvCedtJTvUYzJF2GZMRB0JMlai+6cBu3VCTQz33GQ= github.com/mailgun/multibuf v0.0.0-20150714184110-565402cd71fb h1:m2FGM8K2LC9Zyt/7zbQNn5Uvf/YV7vFWKtoMcC7hHU8= github.com/mailgun/multibuf v0.0.0-20150714184110-565402cd71fb/go.mod h1:E0vRBBIQUHcRtmL/oR6w/jehh4FJqJFxe86gBnw9gXc= -github.com/mailgun/timetools v0.0.0-20141028012446-7e6055773c51 h1:Kg/NPZLLC3aAFr1YToMs98dbCdhootQ1hZIvZU28hAQ= -github.com/mailgun/timetools v0.0.0-20141028012446-7e6055773c51/go.mod h1:RYmqHbhWwIz3z9eVmQ2rx82rulEMG0t+Q1bzfc9DYN4= -github.com/mailgun/ttlmap v0.0.0-20170619185759-c1c17f74874f/go.mod h1:8heskWJ5c0v5J9WH89ADhyal1DOZcayll8fSbhB+/9A= 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/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -249,7 +241,6 @@ github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM= -github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= @@ -263,11 +254,10 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/vulcand/oxy v1.3.0 h1:358BVHmJNLjhOrhbjq2EVJX5NQ3HxrP0d5OyHLRliX0= -github.com/vulcand/oxy v1.3.0/go.mod h1:hN/gw/jg+GH4A+bqvznsW26Izd4jNGV6h1z3s7drRzs= -github.com/vulcand/predicate v1.1.0/go.mod h1:mlccC5IRBoc2cIFmCB8ZM62I3VDb6p2GXESMHa3CnZg= +github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= +github.com/vulcand/oxy v1.4.0 h1:QslVUBCCev9zf+0QNr+SJlfpidz+4NZXu1yNfv2bLsc= +github.com/vulcand/oxy v1.4.0/go.mod h1:ygVjK9yyTc1iScEZ8ZbFpjjHH2DlX8qXS7s+C5G7lJE= github.com/vulcand/predicate v1.2.0 h1:uFsW1gcnnR7R+QTID+FVcs0sSYlIGntoGOTb3rQJt50= github.com/vulcand/predicate v1.2.0/go.mod h1:VipoNYXny6c8N381zGUWkjuuNHiRbeAZhE7Qm9c+2GA= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -288,8 +278,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20220126234351-aa10faf2a1f8/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 h1:kUhD7nTDoI3fVd9G4ORWrbV5NY0liEs/Jg2pv5f+bBA= -golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f h1:OeJjE6G4dgCY4PIXvIRQbE8+RX+uXZyGhUy/ksMGJoc= +golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -356,8 +346,8 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220412020605-290c469a71a5 h1:bRb386wvrE+oBNdF1d/Xh9mQrfQ4ecYhW5qJ5GvTGT4= -golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 h1:HVyaeDAYux4pnY+D/SiwmLOR36ewZ4iGQIIrtnuCjFA= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -583,8 +573,8 @@ gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -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= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -592,7 +582,6 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -launchpad.net/gocheck v0.0.0-20140225173054-000000000087/go.mod h1:hj7XX3B/0A+80Vse0e+BUHsHMTEhd0O4cpUHr/e/BUM= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/vendor/github.com/vulcand/oxy/buffer/buffer.go b/vendor/github.com/vulcand/oxy/buffer/buffer.go index 00dfa9c..4189035 100644 --- a/vendor/github.com/vulcand/oxy/buffer/buffer.go +++ b/vendor/github.com/vulcand/oxy/buffer/buffer.go @@ -39,7 +39,6 @@ import ( "bufio" "fmt" "io" - "io/ioutil" "net" "net/http" "reflect" @@ -50,57 +49,17 @@ import ( ) const ( - // DefaultMemBodyBytes Store up to 1MB in RAM + // DefaultMemBodyBytes Store up to 1MB in RAM. DefaultMemBodyBytes = 1048576 - // DefaultMaxBodyBytes No limit by default + // DefaultMaxBodyBytes No limit by default. DefaultMaxBodyBytes = -1 - // DefaultMaxRetryAttempts Maximum retry attempts + // DefaultMaxRetryAttempts Maximum retry attempts. DefaultMaxRetryAttempts = 10 ) var errHandler utils.ErrorHandler = &SizeErrHandler{} -// Buffer is responsible for buffering requests and responses -// It buffers large requests and responses to disk, -type Buffer struct { - maxRequestBodyBytes int64 - memRequestBodyBytes int64 - - maxResponseBodyBytes int64 - memResponseBodyBytes int64 - - retryPredicate hpredicate - - next http.Handler - errHandler utils.ErrorHandler - - log *log.Logger -} - -// New returns a new buffer middleware. New() function supports optional functional arguments -func New(next http.Handler, setters ...optSetter) (*Buffer, error) { - strm := &Buffer{ - next: next, - - maxRequestBodyBytes: DefaultMaxBodyBytes, - memRequestBodyBytes: DefaultMemBodyBytes, - - maxResponseBodyBytes: DefaultMaxBodyBytes, - memResponseBodyBytes: DefaultMemBodyBytes, - - log: log.StandardLogger(), - } - for _, s := range setters { - if err := s(strm); err != nil { - return nil, err - } - } - if strm.errHandler == nil { - strm.errHandler = errHandler - } - - return strm, nil -} +type optSetter func(b *Buffer) error // Logger defines the logger the buffer will use. // @@ -112,8 +71,6 @@ func Logger(l *log.Logger) optSetter { } } -type optSetter func(b *Buffer) error - // CondSetter Conditional setter. // ex: Cond(a > 4, MemRequestBodyBytes(a)) func CondSetter(condition bool, setter optSetter) optSetter { @@ -135,7 +92,7 @@ func CondSetter(condition bool, setter optSetter) optSetter { // // Example of the predicate: // -// `Attempts() <= 2 && ResponseCode() == 502` +// `Attempts() <= 2 && ResponseCode() == 502`. // func Retry(predicate string) optSetter { return func(b *Buffer) error { @@ -148,7 +105,7 @@ func Retry(predicate string) optSetter { } } -// ErrorHandler sets error handler of the server +// ErrorHandler sets error handler of the server. func ErrorHandler(h utils.ErrorHandler) optSetter { return func(b *Buffer) error { b.errHandler = h @@ -156,7 +113,7 @@ func ErrorHandler(h utils.ErrorHandler) optSetter { } } -// MaxRequestBodyBytes sets the maximum request body size in bytes +// MaxRequestBodyBytes sets the maximum request body size in bytes. func MaxRequestBodyBytes(m int64) optSetter { return func(b *Buffer) error { if m < 0 { @@ -179,7 +136,7 @@ func MemRequestBodyBytes(m int64) optSetter { } } -// MaxResponseBodyBytes sets the maximum response body size in bytes +// MaxResponseBodyBytes sets the maximum response body size in bytes. func MaxResponseBodyBytes(m int64) optSetter { return func(b *Buffer) error { if m < 0 { @@ -202,6 +159,48 @@ func MemResponseBodyBytes(m int64) optSetter { } } +// Buffer is responsible for buffering requests and responses +// It buffers large requests and responses to disk,. +type Buffer struct { + maxRequestBodyBytes int64 + memRequestBodyBytes int64 + + maxResponseBodyBytes int64 + memResponseBodyBytes int64 + + retryPredicate hpredicate + + next http.Handler + errHandler utils.ErrorHandler + + log *log.Logger +} + +// New returns a new buffer middleware. New() function supports optional functional arguments. +func New(next http.Handler, setters ...optSetter) (*Buffer, error) { + strm := &Buffer{ + next: next, + + maxRequestBodyBytes: DefaultMaxBodyBytes, + memRequestBodyBytes: DefaultMemBodyBytes, + + maxResponseBodyBytes: DefaultMaxBodyBytes, + memResponseBodyBytes: DefaultMemBodyBytes, + + log: log.StandardLogger(), + } + for _, s := range setters { + if err := s(strm); err != nil { + return nil, err + } + } + if strm.errHandler == nil { + strm.errHandler = errHandler + } + + return strm, nil +} + // Wrap sets the next handler to be called by buffer handler. func (b *Buffer) Wrap(next http.Handler) error { b.next = next @@ -210,7 +209,7 @@ func (b *Buffer) Wrap(next http.Handler) error { func (b *Buffer) ServeHTTP(w http.ResponseWriter, req *http.Request) { if b.log.Level >= log.DebugLevel { - logEntry := b.log.WithField("Request", utils.DumpHttpRequest(req)) + logEntry := b.log.WithField("Request", utils.DumpHTTPRequest(req)) logEntry.Debug("vulcand/oxy/buffer: begin ServeHttp on request") defer logEntry.Debug("vulcand/oxy/buffer: completed ServeHttp on request") } @@ -301,7 +300,7 @@ func (b *Buffer) ServeHTTP(w http.ResponseWriter, req *http.Request) { utils.CopyHeaders(w.Header(), bw.Header()) w.WriteHeader(bw.code) if reader != nil { - io.Copy(w, reader) + _, _ = io.Copy(w, reader) } return } @@ -330,9 +329,9 @@ func (b *Buffer) copyRequest(req *http.Request, body io.ReadCloser, bodySize int o.TransferEncoding = []string{} // http.Transport will close the request body on any error, we are controlling the close process ourselves, so we override the closer here if body == nil { - o.Body = ioutil.NopCloser(req.Body) + o.Body = io.NopCloser(req.Body) } else { - o.Body = ioutil.NopCloser(body.(io.Reader)) + o.Body = io.NopCloser(body.(io.Reader)) } return &o } @@ -356,7 +355,7 @@ type bufferWriter struct { log *log.Logger } -// RFC2616 #4.4 +// RFC2616 #4.4. func (b *bufferWriter) expectBody(r *http.Request) bool { if r.Method == "HEAD" { return false @@ -398,7 +397,7 @@ func (b *bufferWriter) WriteHeader(code int) { b.code = code } -// CloseNotifier interface - this allows downstream connections to be terminated when the client terminates. +// CloseNotify CloseNotifier interface - this allows downstream connections to be terminated when the client terminates. func (b *bufferWriter) CloseNotify() <-chan bool { if cn, ok := b.responseWriter.(http.CloseNotifier); ok { return cn.CloseNotify() @@ -420,13 +419,13 @@ func (b *bufferWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { return nil, nil, fmt.Errorf("the response writer wrapped in this proxy does not implement http.Hijacker. Its type is: %v", reflect.TypeOf(b.responseWriter)) } -// SizeErrHandler Size error handler +// SizeErrHandler Size error handler. type SizeErrHandler struct{} func (e *SizeErrHandler) ServeHTTP(w http.ResponseWriter, req *http.Request, err error) { if _, ok := err.(*multibuf.MaxSizeReachedError); ok { w.WriteHeader(http.StatusRequestEntityTooLarge) - w.Write([]byte(http.StatusText(http.StatusRequestEntityTooLarge))) + _, _ = w.Write([]byte(http.StatusText(http.StatusRequestEntityTooLarge))) return } utils.DefaultHandler.ServeHTTP(w, req, err) diff --git a/vendor/github.com/vulcand/oxy/buffer/threshold.go b/vendor/github.com/vulcand/oxy/buffer/threshold.go index 0fdde7d..1bb712e 100644 --- a/vendor/github.com/vulcand/oxy/buffer/threshold.go +++ b/vendor/github.com/vulcand/oxy/buffer/threshold.go @@ -7,7 +7,7 @@ import ( "github.com/vulcand/predicate" ) -// IsValidExpression check if it's a valid expression +// IsValidExpression check if it's a valid expression. func IsValidExpression(expr string) bool { _, err := parseExpression(expr) return err == nil @@ -21,7 +21,7 @@ type context struct { type hpredicate func(*context) bool -// Parses expression in the go language into Failover predicates +// Parses expression in the go language into Failover predicates. func parseExpression(in string) (hpredicate, error) { p, err := predicate.NewParser(predicate.Def{ Operators: predicate.Operators{ @@ -56,16 +56,17 @@ func parseExpression(in string) (hpredicate, error) { } type toString func(c *context) string + type toInt func(c *context) int -// RequestMethod returns mapper of the request to its method e.g. POST +// RequestMethod returns mapper of the request to its method e.g. POST. func requestMethod() toString { return func(c *context) string { return c.r.Method } } -// Attempts returns mapper of the request to the number of proxy attempts +// Attempts returns mapper of the request to the number of proxy attempts. func attempts() toInt { return func(c *context) int { return c.attempt @@ -86,7 +87,7 @@ func isNetworkError() hpredicate { } } -// and returns predicate by joining the passed predicates with logical 'and' +// and returns predicate by joining the passed predicates with logical 'and'. func and(fns ...hpredicate) hpredicate { return func(c *context) bool { for _, fn := range fns { @@ -98,7 +99,7 @@ func and(fns ...hpredicate) hpredicate { } } -// or returns predicate by joining the passed predicates with logical 'or' +// or returns predicate by joining the passed predicates with logical 'or'. func or(fns ...hpredicate) hpredicate { return func(c *context) bool { for _, fn := range fns { @@ -110,14 +111,14 @@ func or(fns ...hpredicate) hpredicate { } } -// not creates negation of the passed predicate +// not creates negation of the passed predicate. func not(p hpredicate) hpredicate { return func(c *context) bool { return !p(c) } } -// eq returns predicate that tests for equality of the value of the mapper and the constant +// eq returns predicate that tests for equality of the value of the mapper and the constant. func eq(m interface{}, value interface{}) (hpredicate, error) { switch mapper := m.(type) { case toString: @@ -128,7 +129,7 @@ func eq(m interface{}, value interface{}) (hpredicate, error) { return nil, fmt.Errorf("unsupported argument: %T", m) } -// neq returns predicate that tests for inequality of the value of the mapper and the constant +// neq returns predicate that tests for inequality of the value of the mapper and the constant. func neq(m interface{}, value interface{}) (hpredicate, error) { p, err := eq(m, value) if err != nil { @@ -137,16 +138,17 @@ func neq(m interface{}, value interface{}) (hpredicate, error) { return not(p), nil } -// lt returns predicate that tests that value of the mapper function is less than the constant +// lt returns predicate that tests that value of the mapper function is less than the constant. func lt(m interface{}, value interface{}) (hpredicate, error) { switch mapper := m.(type) { case toInt: return intLT(mapper, value) + default: + return nil, fmt.Errorf("unsupported argument: %T", m) } - return nil, fmt.Errorf("unsupported argument: %T", m) } -// le returns predicate that tests that value of the mapper function is less or equal than the constant +// le returns predicate that tests that value of the mapper function is less or equal than the constant. func le(m interface{}, value interface{}) (hpredicate, error) { l, err := lt(m, value) if err != nil { @@ -161,16 +163,17 @@ func le(m interface{}, value interface{}) (hpredicate, error) { }, nil } -// gt returns predicate that tests that value of the mapper function is greater than the constant +// gt returns predicate that tests that value of the mapper function is greater than the constant. func gt(m interface{}, value interface{}) (hpredicate, error) { switch mapper := m.(type) { case toInt: return intGT(mapper, value) + default: + return nil, fmt.Errorf("unsupported argument: %T", m) } - return nil, fmt.Errorf("unsupported argument: %T", m) } -// ge returns predicate that tests that value of the mapper function is less or equal than the constant +// ge returns predicate that tests that value of the mapper function is less or equal than the constant. func ge(m interface{}, value interface{}) (hpredicate, error) { g, err := gt(m, value) if err != nil { diff --git a/vendor/github.com/vulcand/oxy/forward/fwd.go b/vendor/github.com/vulcand/oxy/forward/fwd.go index be39838..8f1cb1c 100644 --- a/vendor/github.com/vulcand/oxy/forward/fwd.go +++ b/vendor/github.com/vulcand/oxy/forward/fwd.go @@ -7,7 +7,6 @@ import ( "bytes" "crypto/tls" "errors" - "fmt" "io" "net" "net/http" @@ -20,10 +19,11 @@ import ( "github.com/gorilla/websocket" log "github.com/sirupsen/logrus" + "github.com/vulcand/oxy/internal/holsterv4/clock" "github.com/vulcand/oxy/utils" ) -// OxyLogger interface of the internal +// OxyLogger interface of the internal. type OxyLogger interface { log.FieldLogger GetLevel() log.Level @@ -37,14 +37,14 @@ func (i *internalLogger) GetLevel() log.Level { return i.Level } -// ReqRewriter can alter request headers and body +// ReqRewriter can alter request headers and body. type ReqRewriter interface { Rewrite(r *http.Request) } type optSetter func(f *Forwarder) error -// PassHostHeader specifies if a client's Host header field should be delegated +// PassHostHeader specifies if a client's Host header field should be delegated. func PassHostHeader(b bool) optSetter { return func(f *Forwarder) error { f.httpForwarder.passHost = b @@ -53,7 +53,7 @@ func PassHostHeader(b bool) optSetter { } // RoundTripper sets a new http.RoundTripper -// Forwarder will use http.DefaultTransport as a default round tripper +// Forwarder will use http.DefaultTransport as a default round tripper. func RoundTripper(r http.RoundTripper) optSetter { return func(f *Forwarder) error { f.httpForwarder.roundTripper = r @@ -61,7 +61,7 @@ func RoundTripper(r http.RoundTripper) optSetter { } } -// Rewriter defines a request rewriter for the HTTP forwarder +// Rewriter defines a request rewriter for the HTTP forwarder. func Rewriter(r ReqRewriter) optSetter { return func(f *Forwarder) error { f.httpForwarder.rewriter = r @@ -69,7 +69,7 @@ func Rewriter(r ReqRewriter) optSetter { } } -// WebsocketTLSClientConfig define the websocker client TLS configuration +// WebsocketTLSClientConfig define the websocker client TLS configuration. func WebsocketTLSClientConfig(tcc *tls.Config) optSetter { return func(f *Forwarder) error { f.httpForwarder.tlsClientConfig = tcc @@ -77,7 +77,7 @@ func WebsocketTLSClientConfig(tcc *tls.Config) optSetter { } } -// ErrorHandler is a functional argument that sets error handler of the server +// ErrorHandler is a functional argument that sets error handler of the server. func ErrorHandler(h utils.ErrorHandler) optSetter { return func(f *Forwarder) error { f.errHandler = h @@ -120,15 +120,15 @@ func Logger(l log.FieldLogger) optSetter { } } -// StateListener defines a state listener for the HTTP forwarder -func StateListener(stateListener UrlForwardingStateListener) optSetter { +// StateListener defines a state listener for the HTTP forwarder. +func StateListener(stateListener URLForwardingStateListener) optSetter { return func(f *Forwarder) error { f.stateListener = stateListener return nil } } -// WebsocketConnectionClosedHook defines a hook called when websocket connection is closed +// WebsocketConnectionClosedHook defines a hook called when websocket connection is closed. func WebsocketConnectionClosedHook(hook func(req *http.Request, conn net.Conn)) optSetter { return func(f *Forwarder) error { f.httpForwarder.websocketConnectionClosedHook = hook @@ -136,7 +136,7 @@ func WebsocketConnectionClosedHook(hook func(req *http.Request, conn net.Conn)) } } -// ResponseModifier defines a response modifier for the HTTP forwarder +// ResponseModifier defines a response modifier for the HTTP forwarder. func ResponseModifier(responseModifier func(*http.Response) error) optSetter { return func(f *Forwarder) error { f.httpForwarder.modifyResponse = responseModifier @@ -144,7 +144,7 @@ func ResponseModifier(responseModifier func(*http.Response) error) optSetter { } } -// StreamingFlushInterval defines a streaming flush interval for the HTTP forwarder +// StreamingFlushInterval defines a streaming flush interval for the HTTP forwarder. func StreamingFlushInterval(flushInterval time.Duration) optSetter { return func(f *Forwarder) error { f.httpForwarder.flushInterval = flushInterval @@ -153,21 +153,20 @@ func StreamingFlushInterval(flushInterval time.Duration) optSetter { } // Forwarder wraps two traffic forwarding implementations: HTTP and websockets. -// It decides based on the specified request which implementation to use +// It decides based on the specified request which implementation to use. type Forwarder struct { *httpForwarder *handlerContext - stateListener UrlForwardingStateListener + stateListener URLForwardingStateListener stream bool } -// handlerContext defines a handler context for error reporting and logging +// handlerContext defines a handler context for error reporting and logging. type handlerContext struct { errHandler utils.ErrorHandler } -// httpForwarder is a handler that can reverse proxy -// HTTP traffic +// httpForwarder is a handler that can reverse proxy HTTP traffic. type httpForwarder struct { roundTripper http.RoundTripper rewriter ReqRewriter @@ -183,18 +182,22 @@ type httpForwarder struct { websocketConnectionClosedHook func(req *http.Request, conn net.Conn) } -const defaultFlushInterval = time.Duration(100) * time.Millisecond +const defaultFlushInterval = 100 * clock.Millisecond -// Connection states +// Connection states. const ( StateConnected = iota StateDisconnected ) -// UrlForwardingStateListener URL forwarding state listener -type UrlForwardingStateListener func(*url.URL, int) +// UrlForwardingStateListener alias on URLForwardingStateListener. +// Deprecated: use URLForwardingStateListener instead. +type UrlForwardingStateListener = URLForwardingStateListener -// New creates an instance of Forwarder based on the provided list of configuration options +// URLForwardingStateListener URL forwarding state listener. +type URLForwardingStateListener func(*url.URL, int) + +// New creates an instance of Forwarder based on the provided list of configuration options. func New(setters ...optSetter) (*Forwarder, error) { f := &Forwarder{ httpForwarder: &httpForwarder{log: &internalLogger{Logger: log.StandardLogger()}}, @@ -240,10 +243,10 @@ func New(setters ...optSetter) (*Forwarder, error) { } // ServeHTTP decides which forwarder to use based on the specified -// request and delegates to the proper implementation +// request and delegates to the proper implementation. func (f *Forwarder) ServeHTTP(w http.ResponseWriter, req *http.Request) { if f.log.GetLevel() >= log.DebugLevel { - logEntry := f.log.WithField("Request", utils.DumpHttpRequest(req)) + logEntry := f.log.WithField("Request", utils.DumpHTTPRequest(req)) logEntry.Debug("vulcand/oxy/forward: begin ServeHttp on request") defer logEntry.Debug("vulcand/oxy/forward: completed ServeHttp on request") } @@ -259,7 +262,7 @@ func (f *Forwarder) ServeHTTP(w http.ResponseWriter, req *http.Request) { } } -func (f *httpForwarder) getUrlFromRequest(req *http.Request) *url.URL { +func (f *httpForwarder) getURLFromRequest(req *http.Request) *url.URL { // If the Request was created by Go via a real HTTP request, RequestURI will // contain the original query string. If the Request was created in code, RequestURI // will be empty, and we will use the URL object instead @@ -275,13 +278,13 @@ func (f *httpForwarder) getUrlFromRequest(req *http.Request) *url.URL { return u } -// Modify the request to handle the target URL +// Modify the request to handle the target URL. func (f *httpForwarder) modifyRequest(outReq *http.Request, target *url.URL) { outReq.URL = utils.CopyURL(outReq.URL) outReq.URL.Scheme = target.Scheme outReq.URL.Host = target.Host - u := f.getUrlFromRequest(outReq) + u := f.getURLFromRequest(outReq) outReq.URL.Path = u.Path outReq.URL.RawPath = u.RawPath @@ -302,10 +305,10 @@ func (f *httpForwarder) modifyRequest(outReq *http.Request, target *url.URL) { } } -// serveWebSocket forwards websocket traffic +// serveWebSocket forwards websocket traffic. func (f *httpForwarder) serveWebSocket(w http.ResponseWriter, req *http.Request, ctx *handlerContext) { if f.log.GetLevel() >= log.DebugLevel { - logEntry := f.log.WithField("Request", utils.DumpHttpRequest(req)) + logEntry := f.log.WithField("Request", utils.DumpHTTPRequest(req)) logEntry.Debug("vulcand/oxy/forward/websocket: begin ServeHttp on request") defer logEntry.Debug("vulcand/oxy/forward/websocket: completed ServeHttp on request") } @@ -313,45 +316,47 @@ func (f *httpForwarder) serveWebSocket(w http.ResponseWriter, req *http.Request, outReq := f.copyWebSocketRequest(req) dialer := websocket.DefaultDialer - if outReq.URL.Scheme == "wss" && f.tlsClientConfig != nil { dialer.TLSClientConfig = f.tlsClientConfig.Clone() // WebSocket is only in http/1.1 dialer.TLSClientConfig.NextProtos = []string{"http/1.1"} } + targetConn, resp, err := dialer.DialContext(outReq.Context(), outReq.URL.String(), outReq.Header) if err != nil { if resp == nil { ctx.errHandler.ServeHTTP(w, req, err) - } else { - f.log.Errorf("vulcand/oxy/forward/websocket: Error dialing %q: %v with resp: %d %s", outReq.Host, err, resp.StatusCode, resp.Status) - hijacker, ok := w.(http.Hijacker) - if !ok { - f.log.Errorf("vulcand/oxy/forward/websocket: %s can not be hijack", reflect.TypeOf(w)) - ctx.errHandler.ServeHTTP(w, req, err) - return - } + return + } - conn, _, errHijack := hijacker.Hijack() - if errHijack != nil { - f.log.Errorf("vulcand/oxy/forward/websocket: Failed to hijack responseWriter") - ctx.errHandler.ServeHTTP(w, req, errHijack) - return - } - defer func() { - conn.Close() - if f.websocketConnectionClosedHook != nil { - f.websocketConnectionClosedHook(req, conn) - } - }() + f.log.Errorf("vulcand/oxy/forward/websocket: Error dialing %q: %v with resp: %d %s", outReq.Host, err, resp.StatusCode, resp.Status) + hijacker, ok := w.(http.Hijacker) + if !ok { + f.log.Errorf("vulcand/oxy/forward/websocket: %s can not be hijack", reflect.TypeOf(w)) + ctx.errHandler.ServeHTTP(w, req, err) + return + } - errWrite := resp.Write(conn) - if errWrite != nil { - f.log.Errorf("vulcand/oxy/forward/websocket: Failed to forward response") - ctx.errHandler.ServeHTTP(w, req, errWrite) - return + conn, _, errHijack := hijacker.Hijack() + if errHijack != nil { + f.log.Errorf("vulcand/oxy/forward/websocket: Failed to hijack responseWriter") + ctx.errHandler.ServeHTTP(w, req, errHijack) + return + } + defer func() { + _ = conn.Close() + if f.websocketConnectionClosedHook != nil { + f.websocketConnectionClosedHook(req, conn) } + }() + + errWrite := resp.Write(conn) + if errWrite != nil { + f.log.Errorf("vulcand/oxy/forward/websocket: Failed to forward response") + ctx.errHandler.ServeHTTP(w, req, errWrite) + return } + return } @@ -369,8 +374,8 @@ func (f *httpForwarder) serveWebSocket(w http.ResponseWriter, req *http.Request, return } defer func() { - underlyingConn.Close() - targetConn.Close() + _ = underlyingConn.Close() + _ = targetConn.Close() if f.websocketConnectionClosedHook != nil { f.websocketConnectionClosedHook(req, underlyingConn.UnderlyingConn()) } @@ -379,7 +384,6 @@ func (f *httpForwarder) serveWebSocket(w http.ResponseWriter, req *http.Request, errClient := make(chan error, 1) errBackend := make(chan error, 1) replicateWebsocketConn := func(dst, src *websocket.Conn, errc chan error) { - forward := func(messageType int, reader io.Reader) error { writer, err := dst.NextWriter(messageType) if err != nil { @@ -402,24 +406,21 @@ func (f *httpForwarder) serveWebSocket(w http.ResponseWriter, req *http.Request, for { msgType, reader, err := src.NextReader() - if err != nil { - m := websocket.FormatCloseMessage(websocket.CloseNormalClosure, fmt.Sprintf("%v", err)) + m := websocket.FormatCloseMessage(websocket.CloseNormalClosure, err.Error()) if e, ok := err.(*websocket.CloseError); ok { if e.Code != websocket.CloseNoStatusReceived { m = nil // Following codes are not valid on the wire so just close the // underlying TCP connection without sending a close frame. - if e.Code != websocket.CloseAbnormalClosure && - e.Code != websocket.CloseTLSHandshake { - + if e.Code != websocket.CloseAbnormalClosure && e.Code != websocket.CloseTLSHandshake { m = websocket.FormatCloseMessage(e.Code, e.Text) } } } errc <- err if m != nil { - forward(websocket.CloseMessage, bytes.NewReader([]byte(m))) + _ = forward(websocket.CloseMessage, bytes.NewReader(m)) } break } @@ -440,8 +441,8 @@ func (f *httpForwarder) serveWebSocket(w http.ResponseWriter, req *http.Request, message = "vulcand/oxy/forward/websocket: Error when copying from backend to client: %v" case err = <-errBackend: message = "vulcand/oxy/forward/websocket: Error when copying from client to backend: %v" - } + if e, ok := err.(*websocket.CloseError); !ok || e.Code == websocket.CloseAbnormalClosure { f.log.Errorf(message, err) } @@ -463,7 +464,7 @@ func (f *httpForwarder) copyWebSocketRequest(req *http.Request) (outReq *http.Re outReq.URL.Scheme = "ws" } - u := f.getUrlFromRequest(outReq) + u := f.getURLFromRequest(outReq) outReq.URL.Path = u.Path outReq.URL.RawPath = u.RawPath @@ -487,15 +488,15 @@ func (f *httpForwarder) copyWebSocketRequest(req *http.Request) (outReq *http.Re return outReq } -// serveHTTP forwards HTTP traffic using the configured transport +// serveHTTP forwards HTTP traffic using the configured transport. func (f *httpForwarder) serveHTTP(w http.ResponseWriter, inReq *http.Request, ctx *handlerContext) { if f.log.GetLevel() >= log.DebugLevel { - logEntry := f.log.WithField("Request", utils.DumpHttpRequest(inReq)) + logEntry := f.log.WithField("Request", utils.DumpHTTPRequest(inReq)) logEntry.Debug("vulcand/oxy/forward/http: begin ServeHttp on request") defer logEntry.Debug("vulcand/oxy/forward/http: completed ServeHttp on request") } - start := time.Now().UTC() + start := clock.Now().UTC() outReq := new(http.Request) *outReq = *inReq // includes shallow copies of maps, but we handle this in Director @@ -517,14 +518,14 @@ func (f *httpForwarder) serveHTTP(w http.ResponseWriter, inReq *http.Request, ct if inReq.TLS != nil { f.log.Debugf("vulcand/oxy/forward/http: Round trip: %v, code: %v, Length: %v, duration: %v tls:version: %x, tls:resume:%t, tls:csuite:%x, tls:server:%v", - inReq.URL, pw.StatusCode(), pw.GetLength(), time.Now().UTC().Sub(start), + inReq.URL, pw.StatusCode(), pw.GetLength(), clock.Now().UTC().Sub(start), inReq.TLS.Version, inReq.TLS.DidResume, inReq.TLS.CipherSuite, inReq.TLS.ServerName) } else { f.log.Debugf("vulcand/oxy/forward/http: Round trip: %v, code: %v, Length: %v, duration: %v", - inReq.URL, pw.StatusCode(), pw.GetLength(), time.Now().UTC().Sub(start)) + inReq.URL, pw.StatusCode(), pw.GetLength(), clock.Now().UTC().Sub(start)) } } else { revproxy.ServeHTTP(w, outReq) @@ -538,11 +539,9 @@ func (f *httpForwarder) serveHTTP(w http.ResponseWriter, inReq *http.Request, ct break } } - } -// IsWebsocketRequest determines if the specified HTTP request is a -// websocket handshake request +// IsWebsocketRequest determines if the specified HTTP request is a websocket handshake request. func IsWebsocketRequest(req *http.Request) bool { containsHeader := func(name, value string) bool { items := strings.Split(req.Header.Get(name), ",") diff --git a/vendor/github.com/vulcand/oxy/forward/headers.go b/vendor/github.com/vulcand/oxy/forward/headers.go index 512e284..565794a 100644 --- a/vendor/github.com/vulcand/oxy/forward/headers.go +++ b/vendor/github.com/vulcand/oxy/forward/headers.go @@ -1,6 +1,6 @@ package forward -// Headers +// Headers. const ( XForwardedProto = "X-Forwarded-Proto" XForwardedFor = "X-Forwarded-For" @@ -25,7 +25,7 @@ const ( // HopHeaders Hop-by-hop headers. These are removed when sent to the backend. // http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html -// Copied from reverseproxy.go, too bad +// Copied from reverseproxy.go, too bad. var HopHeaders = []string{ Connection, KeepAlive, @@ -37,7 +37,7 @@ var HopHeaders = []string{ Upgrade, } -// WebsocketDialHeaders Websocket dial headers +// WebsocketDialHeaders Websocket dial headers. var WebsocketDialHeaders = []string{ Upgrade, Connection, @@ -47,7 +47,7 @@ var WebsocketDialHeaders = []string{ SecWebsocketAccept, } -// WebsocketUpgradeHeaders Websocket upgrade headers +// WebsocketUpgradeHeaders Websocket upgrade headers. var WebsocketUpgradeHeaders = []string{ Upgrade, Connection, @@ -55,7 +55,7 @@ var WebsocketUpgradeHeaders = []string{ SecWebsocketExtensions, } -// XHeaders X-* headers +// XHeaders X-* headers. var XHeaders = []string{ XForwardedProto, XForwardedFor, diff --git a/vendor/github.com/vulcand/oxy/forward/post_config.go b/vendor/github.com/vulcand/oxy/forward/post_config.go index 1c4b123..56e03d1 100644 --- a/vendor/github.com/vulcand/oxy/forward/post_config.go +++ b/vendor/github.com/vulcand/oxy/forward/post_config.go @@ -1,3 +1,4 @@ +//go:build go1.11 // +build go1.11 package forward diff --git a/vendor/github.com/vulcand/oxy/forward/post_config_18.go b/vendor/github.com/vulcand/oxy/forward/post_config_18.go index 7fee684..2e85835 100644 --- a/vendor/github.com/vulcand/oxy/forward/post_config_18.go +++ b/vendor/github.com/vulcand/oxy/forward/post_config_18.go @@ -1,3 +1,4 @@ +//go:build !go1.11 // +build !go1.11 package forward diff --git a/vendor/github.com/vulcand/oxy/forward/rewrite.go b/vendor/github.com/vulcand/oxy/forward/rewrite.go index b5f8da1..0611174 100644 --- a/vendor/github.com/vulcand/oxy/forward/rewrite.go +++ b/vendor/github.com/vulcand/oxy/forward/rewrite.go @@ -8,18 +8,18 @@ import ( "github.com/vulcand/oxy/utils" ) -// HeaderRewriter is responsible for removing hop-by-hop headers and setting forwarding headers +// HeaderRewriter is responsible for removing hop-by-hop headers and setting forwarding headers. type HeaderRewriter struct { TrustForwardHeader bool Hostname string } -// clean up IP in case if it is ipv6 address and it has {zone} information in it, like "[fe80::d806:a55d:eb1b:49cc%vEthernet (vmxnet3 Ethernet Adapter - Virtual Switch)]:64692" +// clean up IP in case if it is ipv6 address and it has {zone} information in it, like "[fe80::d806:a55d:eb1b:49cc%vEthernet (vmxnet3 Ethernet Adapter - Virtual Switch)]:64692". func ipv6fix(clientIP string) string { return strings.Split(clientIP, "%")[0] } -// Rewrite rewrite request headers +// Rewrite rewrite request headers. func (rw *HeaderRewriter) Rewrite(req *http.Request) { if !rw.TrustForwardHeader { utils.RemoveHeaders(req.Header, XHeaders...) diff --git a/vendor/github.com/vulcand/oxy/internal/holsterv4/LICENSE b/vendor/github.com/vulcand/oxy/internal/holsterv4/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/vendor/github.com/vulcand/oxy/internal/holsterv4/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/github.com/vulcand/oxy/internal/holsterv4/clock/README.md b/vendor/github.com/vulcand/oxy/internal/holsterv4/clock/README.md new file mode 100644 index 0000000..5caff75 --- /dev/null +++ b/vendor/github.com/vulcand/oxy/internal/holsterv4/clock/README.md @@ -0,0 +1,47 @@ +# Clock + +A drop in (almost) replacement for the system `time` package. It provides a way +to make scheduled calls, timers and tickers deterministic in tests. By default +it forwards all calls to the system `time` package. In test, however, it is +possible to enable the frozen clock mode, and advance time manually to make +scheduled even trigger at certain moments. + +# Usage + +```go +package foo + +import ( + "testing" + + "github.com/vulcand/oxy/internal/holsterv4/clock" + "github.com/stretchr/testify/assert" +) + +func TestSleep(t *testing.T) { + // Freeze switches the clock package to the frozen clock mode. You need to + // advance time manually from now on. Note that all scheduled events, timers + // and ticker created before this call keep operating in real time. + // + // The initial time is set to now here, but you can set any datetime. + clock.Freeze(clock.Now()) + // Do not forget to revert the effect of Freeze at the end of the test. + defer clock.Unfreeze() + + var fired bool + + clock.AfterFunc(100*clock.Millisecond, func() { + fired = true + }) + clock.Advance(93*clock.Millisecond) + + // Advance will make all fire all events, timers, tickers that are + // scheduled for the passed period of time. Note that scheduled functions + // are called from within Advanced unlike system time package that calls + // them in their own goroutine. + assert.Equal(t, 97*clock.Millisecond, clock.Advance(6*clock.Millisecond)) + assert.True(t, fired) + assert.Equal(t, 100*clock.Millisecond, clock.Advance(1*clock.Millisecond)) + assert.True(t, fired) +} +``` diff --git a/vendor/github.com/vulcand/oxy/internal/holsterv4/clock/clock.go b/vendor/github.com/vulcand/oxy/internal/holsterv4/clock/clock.go new file mode 100644 index 0000000..ca329ad --- /dev/null +++ b/vendor/github.com/vulcand/oxy/internal/holsterv4/clock/clock.go @@ -0,0 +1,105 @@ +//go:build !holster_test_mode + +// Package clock provides the same functions as the system package time. In +// production it forwards all calls to the system time package, but in tests +// the time can be frozen by calling Freeze function and from that point it has +// to be advanced manually with Advance function making all scheduled calls +// deterministic. +// +// The functions provided by the package have the same parameters and return +// values as their system counterparts with a few exceptions. Where either +// *time.Timer or *time.Ticker is returned by a system function, the clock +// package counterpart returns clock.Timer or clock.Ticker interface +// respectively. The interfaces provide API as respective structs except C is +// not a channel, but a function that returns <-chan time.Time. +package clock + +import "time" + +var ( + frozenAt time.Time + realtime = &systemTime{} + provider Clock = realtime +) + +// Freeze after this function is called all time related functions start +// generate deterministic timers that are triggered by Advance function. It is +// supposed to be used in tests only. Returns an Unfreezer so it can be a +// one-liner in tests: defer clock.Freeze(clock.Now()).Unfreeze() +func Freeze(now time.Time) Unfreezer { + frozenAt = now.UTC() + provider = &frozenTime{now: now} + return Unfreezer{} +} + +type Unfreezer struct{} + +func (u Unfreezer) Unfreeze() { + Unfreeze() +} + +// Unfreeze reverses effect of Freeze. +func Unfreeze() { + provider = realtime +} + +// Realtime returns a clock provider wrapping the SDK's time package. It is +// supposed to be used in tests when time is frozen to schedule test timeouts. +func Realtime() Clock { + return realtime +} + +// Makes the deterministic time move forward by the specified duration, firing +// timers along the way in the natural order. It returns how much time has +// passed since it was frozen. So you can assert on the return value in tests +// to make it explicit where you stand on the deterministic time scale. +func Advance(d time.Duration) time.Duration { + ft, ok := provider.(*frozenTime) + if !ok { + panic("Freeze time first!") + } + ft.advance(d) + return Now().UTC().Sub(frozenAt) +} + +// Wait4Scheduled blocks until either there are n or more scheduled events, or +// the timeout elapses. It returns true if the wait condition has been met +// before the timeout expired, false otherwise. +func Wait4Scheduled(count int, timeout time.Duration) bool { + return provider.Wait4Scheduled(count, timeout) +} + +// Now see time.Now. +func Now() time.Time { + return provider.Now() +} + +// Sleep see time.Sleep. +func Sleep(d time.Duration) { + provider.Sleep(d) +} + +// After see time.After. +func After(d time.Duration) <-chan time.Time { + return provider.After(d) +} + +// NewTimer see time.NewTimer. +func NewTimer(d time.Duration) Timer { + return provider.NewTimer(d) +} + +// AfterFunc see time.AfterFunc. +func AfterFunc(d time.Duration, f func()) Timer { + return provider.AfterFunc(d, f) +} + +// NewTicker see time.Ticker. +func NewTicker(d time.Duration) Ticker { + return provider.NewTicker(d) +} + +// Tick see time.Tick. +func Tick(d time.Duration) <-chan time.Time { + return provider.Tick(d) +} diff --git a/vendor/github.com/vulcand/oxy/internal/holsterv4/clock/clock_mutex.go b/vendor/github.com/vulcand/oxy/internal/holsterv4/clock/clock_mutex.go new file mode 100644 index 0000000..f7f8708 --- /dev/null +++ b/vendor/github.com/vulcand/oxy/internal/holsterv4/clock/clock_mutex.go @@ -0,0 +1,131 @@ +//go:build holster_test_mode + +// Package clock provides the same functions as the system package time. In +// production it forwards all calls to the system time package, but in tests +// the time can be frozen by calling Freeze function and from that point it has +// to be advanced manually with Advance function making all scheduled calls +// deterministic. +// +// The functions provided by the package have the same parameters and return +// values as their system counterparts with a few exceptions. Where either +// *time.Timer or *time.Ticker is returned by a system function, the clock +// package counterpart returns clock.Timer or clock.Ticker interface +// respectively. The interfaces provide API as respective structs except C is +// not a channel, but a function that returns <-chan time.Time. +package clock + +import ( + "sync" + "time" +) + +var ( + frozenAt time.Time + realtime = &systemTime{} + provider Clock = realtime + rwMutex = sync.RWMutex{} +) + +// Freeze after this function is called all time related functions start +// generate deterministic timers that are triggered by Advance function. It is +// supposed to be used in tests only. Returns an Unfreezer so it can be a +// one-liner in tests: defer clock.Freeze(clock.Now()).Unfreeze() +func Freeze(now time.Time) Unfreezer { + frozenAt = now.UTC() + rwMutex.Lock() + defer rwMutex.Unlock() + provider = &frozenTime{now: now} + return Unfreezer{} +} + +type Unfreezer struct{} + +func (u Unfreezer) Unfreeze() { + Unfreeze() +} + +// Unfreeze reverses effect of Freeze. +func Unfreeze() { + rwMutex.Lock() + defer rwMutex.Unlock() + provider = realtime +} + +// Realtime returns a clock provider wrapping the SDK's time package. It is +// supposed to be used in tests when time is frozen to schedule test timeouts. +func Realtime() Clock { + return realtime +} + +// Makes the deterministic time move forward by the specified duration, firing +// timers along the way in the natural order. It returns how much time has +// passed since it was frozen. So you can assert on the return value in tests +// to make it explicit where you stand on the deterministic time scale. +func Advance(d time.Duration) time.Duration { + rwMutex.RLock() + ft, ok := provider.(*frozenTime) + rwMutex.RUnlock() + if !ok { + panic("Freeze time first!") + } + ft.advance(d) + return Now().UTC().Sub(frozenAt) +} + +// Wait4Scheduled blocks until either there are n or more scheduled events, or +// the timeout elapses. It returns true if the wait condition has been met +// before the timeout expired, false otherwise. +func Wait4Scheduled(count int, timeout time.Duration) bool { + rwMutex.RLock() + defer rwMutex.RUnlock() + return provider.Wait4Scheduled(count, timeout) +} + +// Now see time.Now. +func Now() time.Time { + rwMutex.RLock() + defer rwMutex.RUnlock() + return provider.Now() +} + +// Sleep see time.Sleep. +func Sleep(d time.Duration) { + rwMutex.RLock() + defer rwMutex.RUnlock() + provider.Sleep(d) +} + +// After see time.After. +func After(d time.Duration) <-chan time.Time { + rwMutex.RLock() + defer rwMutex.RUnlock() + return provider.After(d) +} + +// NewTimer see time.NewTimer. +func NewTimer(d time.Duration) Timer { + rwMutex.RLock() + defer rwMutex.RUnlock() + return provider.NewTimer(d) +} + +// AfterFunc see time.AfterFunc. +func AfterFunc(d time.Duration, f func()) Timer { + rwMutex.RLock() + defer rwMutex.RUnlock() + return provider.AfterFunc(d, f) +} + +// NewTicker see time.Ticker. +func NewTicker(d time.Duration) Ticker { + rwMutex.RLock() + defer rwMutex.RUnlock() + return provider.NewTicker(d) +} + +// Tick see time.Tick. +func Tick(d time.Duration) <-chan time.Time { + rwMutex.RLock() + defer rwMutex.RUnlock() + return provider.Tick(d) +} diff --git a/vendor/github.com/vulcand/oxy/internal/holsterv4/clock/duration.go b/vendor/github.com/vulcand/oxy/internal/holsterv4/clock/duration.go new file mode 100644 index 0000000..f15801f --- /dev/null +++ b/vendor/github.com/vulcand/oxy/internal/holsterv4/clock/duration.go @@ -0,0 +1,65 @@ +package clock + +import ( + "encoding/json" + "fmt" +) + +type DurationJSON struct { + Duration Duration +} + +func NewDurationJSON(v interface{}) (DurationJSON, error) { + switch v := v.(type) { + case Duration: + return DurationJSON{Duration: v}, nil + case float64: + return DurationJSON{Duration: Duration(v)}, nil + case int64: + return DurationJSON{Duration: Duration(v)}, nil + case int: + return DurationJSON{Duration: Duration(v)}, nil + case []byte: + duration, err := ParseDuration(string(v)) + if err != nil { + return DurationJSON{}, fmt.Errorf("while parsing []byte: %w", err) + } + return DurationJSON{Duration: duration}, nil + case string: + duration, err := ParseDuration(v) + if err != nil { + return DurationJSON{}, fmt.Errorf("while parsing string: %w", err) + } + return DurationJSON{Duration: duration}, nil + default: + return DurationJSON{}, fmt.Errorf("bad type %T", v) + } +} + +func NewDurationJSONOrPanic(v interface{}) DurationJSON { + d, err := NewDurationJSON(v) + if err != nil { + panic(err) + } + return d +} + +func (d DurationJSON) MarshalJSON() ([]byte, error) { + return json.Marshal(d.Duration.String()) +} + +func (d *DurationJSON) UnmarshalJSON(b []byte) error { + var v interface{} + var err error + + if err = json.Unmarshal(b, &v); err != nil { + return err + } + + *d, err = NewDurationJSON(v) + return err +} + +func (d DurationJSON) String() string { + return d.Duration.String() +} diff --git a/vendor/github.com/vulcand/oxy/internal/holsterv4/clock/frozen.go b/vendor/github.com/vulcand/oxy/internal/holsterv4/clock/frozen.go new file mode 100644 index 0000000..df85d00 --- /dev/null +++ b/vendor/github.com/vulcand/oxy/internal/holsterv4/clock/frozen.go @@ -0,0 +1,231 @@ +package clock + +import ( + "errors" + "sync" + "time" +) + +type frozenTime struct { + mu sync.Mutex + now time.Time + timers []*frozenTimer + waiter *waiter +} + +type waiter struct { + count int + signalCh chan struct{} +} + +func (ft *frozenTime) Now() time.Time { + ft.mu.Lock() + defer ft.mu.Unlock() + return ft.now +} + +func (ft *frozenTime) Sleep(d time.Duration) { + <-ft.NewTimer(d).C() +} + +func (ft *frozenTime) After(d time.Duration) <-chan time.Time { + return ft.NewTimer(d).C() +} + +func (ft *frozenTime) NewTimer(d time.Duration) Timer { + return ft.AfterFunc(d, nil) +} + +func (ft *frozenTime) AfterFunc(d time.Duration, f func()) Timer { + t := &frozenTimer{ + ft: ft, + when: ft.Now().Add(d), + f: f, + } + if f == nil { + t.c = make(chan time.Time, 1) + } + ft.startTimer(t) + return t +} + +func (ft *frozenTime) advance(d time.Duration) { + ft.mu.Lock() + defer ft.mu.Unlock() + + ft.now = ft.now.Add(d) + for t := ft.nextExpired(); t != nil; t = ft.nextExpired() { + // Send the timer expiration time to the timer channel if it is + // defined. But make sure not to block on the send if the channel is + // full. This behavior will make a ticker skip beats if it readers are + // not fast enough. + if t.c != nil { + select { + case t.c <- t.when: + default: + } + } + // If it is a ticking timer then schedule next tick, otherwise mark it + // as stopped. + if t.interval != 0 { + t.when = t.when.Add(t.interval) + t.stopped = false + ft.unlockedStartTimer(t) + } + // If a function is associated with the timer then call it, but make + // sure to release the lock for the time of call it is necessary + // because the lock is not re-entrant but the function may need to + // start another timer or ticker. + if t.f != nil { + func() { + ft.mu.Unlock() + defer ft.mu.Lock() + t.f() + }() + } + } +} + +func (ft *frozenTime) stopTimer(t *frozenTimer) bool { + ft.mu.Lock() + defer ft.mu.Unlock() + + if t.stopped { + return false + } + for i, curr := range ft.timers { + if curr == t { + t.stopped = true + copy(ft.timers[i:], ft.timers[i+1:]) + lastIdx := len(ft.timers) - 1 + ft.timers[lastIdx] = nil + ft.timers = ft.timers[:lastIdx] + return true + } + } + return false +} + +func (ft *frozenTime) nextExpired() *frozenTimer { + if len(ft.timers) == 0 { + return nil + } + t := ft.timers[0] + if ft.now.Before(t.when) { + return nil + } + copy(ft.timers, ft.timers[1:]) + lastIdx := len(ft.timers) - 1 + ft.timers[lastIdx] = nil + ft.timers = ft.timers[:lastIdx] + t.stopped = true + return t +} + +func (ft *frozenTime) startTimer(t *frozenTimer) { + ft.mu.Lock() + defer ft.mu.Unlock() + + ft.unlockedStartTimer(t) + + if ft.waiter == nil { + return + } + if len(ft.timers) >= ft.waiter.count { + close(ft.waiter.signalCh) + } +} + +func (ft *frozenTime) unlockedStartTimer(t *frozenTimer) { + pos := 0 + for _, curr := range ft.timers { + if t.when.Before(curr.when) { + break + } + pos++ + } + ft.timers = append(ft.timers, nil) + copy(ft.timers[pos+1:], ft.timers[pos:]) + ft.timers[pos] = t +} + +type frozenTimer struct { + ft *frozenTime + when time.Time + interval time.Duration + stopped bool + c chan time.Time + f func() +} + +func (t *frozenTimer) C() <-chan time.Time { + return t.c +} + +func (t *frozenTimer) Stop() bool { + return t.ft.stopTimer(t) +} + +func (t *frozenTimer) Reset(d time.Duration) bool { + active := t.ft.stopTimer(t) + t.when = t.ft.Now().Add(d) + t.ft.startTimer(t) + return active +} + +type frozenTicker struct { + t *frozenTimer +} + +func (t *frozenTicker) C() <-chan time.Time { + return t.t.C() +} + +func (t *frozenTicker) Stop() { + t.t.Stop() +} + +func (ft *frozenTime) NewTicker(d time.Duration) Ticker { + if d <= 0 { + panic(errors.New("non-positive interval for NewTicker")) + } + t := &frozenTimer{ + ft: ft, + when: ft.Now().Add(d), + interval: d, + c: make(chan time.Time, 1), + } + ft.startTimer(t) + return &frozenTicker{t} +} + +func (ft *frozenTime) Tick(d time.Duration) <-chan time.Time { + if d <= 0 { + return nil + } + return ft.NewTicker(d).C() +} + +func (ft *frozenTime) Wait4Scheduled(count int, timeout time.Duration) bool { + ft.mu.Lock() + if len(ft.timers) >= count { + ft.mu.Unlock() + return true + } + if ft.waiter != nil { + panic("Concurrent call") + } + ft.waiter = &waiter{count, make(chan struct{})} + ft.mu.Unlock() + + success := false + select { + case <-ft.waiter.signalCh: + success = true + case <-time.After(timeout): + } + ft.mu.Lock() + ft.waiter = nil + ft.mu.Unlock() + return success +} diff --git a/vendor/github.com/vulcand/oxy/internal/holsterv4/clock/go19.go b/vendor/github.com/vulcand/oxy/internal/holsterv4/clock/go19.go new file mode 100644 index 0000000..f5e169e --- /dev/null +++ b/vendor/github.com/vulcand/oxy/internal/holsterv4/clock/go19.go @@ -0,0 +1,106 @@ +// +build go1.9 + +// This file introduces aliases to allow using of the clock package as a +// drop-in replacement of the standard time package. + +package clock + +import "time" + +type ( + Time = time.Time + Duration = time.Duration + Location = time.Location + + Weekday = time.Weekday + Month = time.Month + + ParseError = time.ParseError +) + +const ( + Nanosecond = time.Nanosecond + Microsecond = time.Microsecond + Millisecond = time.Millisecond + Second = time.Second + Minute = time.Minute + Hour = time.Hour + + Sunday = time.Sunday + Monday = time.Monday + Tuesday = time.Tuesday + Wednesday = time.Wednesday + Thursday = time.Thursday + Friday = time.Friday + Saturday = time.Saturday + + January = time.January + February = time.February + March = time.March + April = time.April + May = time.May + June = time.June + July = time.July + August = time.August + September = time.September + October = time.October + November = time.November + December = time.December + + ANSIC = time.ANSIC + UnixDate = time.UnixDate + RubyDate = time.RubyDate + RFC822 = time.RFC822 + RFC822Z = time.RFC822Z + RFC850 = time.RFC850 + RFC1123 = time.RFC1123 + RFC1123Z = time.RFC1123Z + RFC3339 = time.RFC3339 + RFC3339Nano = time.RFC3339Nano + Kitchen = time.Kitchen + Stamp = time.Stamp + StampMilli = time.StampMilli + StampMicro = time.StampMicro + StampNano = time.StampNano +) + +var ( + UTC = time.UTC + Local = time.Local +) + +func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time { + return time.Date(year, month, day, hour, min, sec, nsec, loc) +} + +func FixedZone(name string, offset int) *Location { + return time.FixedZone(name, offset) +} + +func LoadLocation(name string) (*Location, error) { + return time.LoadLocation(name) +} + +func Parse(layout, value string) (Time, error) { + return time.Parse(layout, value) +} + +func ParseDuration(s string) (Duration, error) { + return time.ParseDuration(s) +} + +func ParseInLocation(layout, value string, loc *Location) (Time, error) { + return time.ParseInLocation(layout, value, loc) +} + +func Unix(sec int64, nsec int64) Time { + return time.Unix(sec, nsec) +} + +func Since(t Time) Duration { + return provider.Now().Sub(t) +} + +func Until(t Time) Duration { + return t.Sub(provider.Now()) +} diff --git a/vendor/github.com/vulcand/oxy/internal/holsterv4/clock/interface.go b/vendor/github.com/vulcand/oxy/internal/holsterv4/clock/interface.go new file mode 100644 index 0000000..15f5ca1 --- /dev/null +++ b/vendor/github.com/vulcand/oxy/internal/holsterv4/clock/interface.go @@ -0,0 +1,35 @@ +package clock + +import "time" + +// Timer see time.Timer. +type Timer interface { + C() <-chan time.Time + Stop() bool + Reset(d time.Duration) bool +} + +// Ticker see time.Ticker. +type Ticker interface { + C() <-chan time.Time + Stop() +} + +// NewStoppedTimer returns a stopped timer. Call Reset to get it ticking. +func NewStoppedTimer() Timer { + t := NewTimer(42 * time.Hour) + t.Stop() + return t +} + +// Clock is an interface that mimics the one of the SDK time package. +type Clock interface { + Now() time.Time + Sleep(d time.Duration) + After(d time.Duration) <-chan time.Time + NewTimer(d time.Duration) Timer + AfterFunc(d time.Duration, f func()) Timer + NewTicker(d time.Duration) Ticker + Tick(d time.Duration) <-chan time.Time + Wait4Scheduled(n int, timeout time.Duration) bool +} diff --git a/vendor/github.com/vulcand/oxy/internal/holsterv4/clock/rfc822.go b/vendor/github.com/vulcand/oxy/internal/holsterv4/clock/rfc822.go new file mode 100644 index 0000000..664941d --- /dev/null +++ b/vendor/github.com/vulcand/oxy/internal/holsterv4/clock/rfc822.go @@ -0,0 +1,119 @@ +package clock + +import ( + "strconv" + "time" +) + +var datetimeLayouts = [48]string{ + // Day first month 2nd abbreviated. + "Mon, 2 Jan 2006 15:04:05 MST", + "Mon, 2 Jan 2006 15:04:05 -0700", + "Mon, 2 Jan 2006 15:04:05 -0700 (MST)", + "2 Jan 2006 15:04:05 MST", + "2 Jan 2006 15:04:05 -0700", + "2 Jan 2006 15:04:05 -0700 (MST)", + "Mon, 2 Jan 2006 15:04 MST", + "Mon, 2 Jan 2006 15:04 -0700", + "Mon, 2 Jan 2006 15:04 -0700 (MST)", + "2 Jan 2006 15:04 MST", + "2 Jan 2006 15:04 -0700", + "2 Jan 2006 15:04 -0700 (MST)", + + // Month first day 2nd abbreviated. + "Mon, Jan 2 2006 15:04:05 MST", + "Mon, Jan 2 2006 15:04:05 -0700", + "Mon, Jan 2 2006 15:04:05 -0700 (MST)", + "Jan 2 2006 15:04:05 MST", + "Jan 2 2006 15:04:05 -0700", + "Jan 2 2006 15:04:05 -0700 (MST)", + "Mon, Jan 2 2006 15:04 MST", + "Mon, Jan 2 2006 15:04 -0700", + "Mon, Jan 2 2006 15:04 -0700 (MST)", + "Jan 2 2006 15:04 MST", + "Jan 2 2006 15:04 -0700", + "Jan 2 2006 15:04 -0700 (MST)", + + // Day first month 2nd not abbreviated. + "Mon, 2 January 2006 15:04:05 MST", + "Mon, 2 January 2006 15:04:05 -0700", + "Mon, 2 January 2006 15:04:05 -0700 (MST)", + "2 January 2006 15:04:05 MST", + "2 January 2006 15:04:05 -0700", + "2 January 2006 15:04:05 -0700 (MST)", + "Mon, 2 January 2006 15:04 MST", + "Mon, 2 January 2006 15:04 -0700", + "Mon, 2 January 2006 15:04 -0700 (MST)", + "2 January 2006 15:04 MST", + "2 January 2006 15:04 -0700", + "2 January 2006 15:04 -0700 (MST)", + + // Month first day 2nd not abbreviated. + "Mon, January 2 2006 15:04:05 MST", + "Mon, January 2 2006 15:04:05 -0700", + "Mon, January 2 2006 15:04:05 -0700 (MST)", + "January 2 2006 15:04:05 MST", + "January 2 2006 15:04:05 -0700", + "January 2 2006 15:04:05 -0700 (MST)", + "Mon, January 2 2006 15:04 MST", + "Mon, January 2 2006 15:04 -0700", + "Mon, January 2 2006 15:04 -0700 (MST)", + "January 2 2006 15:04 MST", + "January 2 2006 15:04 -0700", + "January 2 2006 15:04 -0700 (MST)", +} + +// Allows seamless JSON encoding/decoding of rfc822 formatted timestamps. +// https://www.ietf.org/rfc/rfc822.txt section 5. +type RFC822Time struct { + Time +} + +// NewRFC822Time creates RFC822Time from a standard Time. The created value is +// truncated down to second precision because RFC822 does not allow for better. +func NewRFC822Time(t Time) RFC822Time { + return RFC822Time{Time: t.Truncate(Second)} +} + +// ParseRFC822Time parses an RFC822 time string. +func ParseRFC822Time(s string) (Time, error) { + var t time.Time + var err error + for _, layout := range datetimeLayouts { + t, err = Parse(layout, s) + if err == nil { + return t, err + } + } + return t, err +} + +// NewRFC822Time creates RFC822Time from a Unix timestamp (seconds from Epoch). +func NewRFC822TimeFromUnix(timestamp int64) RFC822Time { + return RFC822Time{Time: Unix(timestamp, 0).UTC()} +} + +func (t RFC822Time) MarshalJSON() ([]byte, error) { + return []byte(strconv.Quote(t.Format(RFC1123))), nil +} + +func (t *RFC822Time) UnmarshalJSON(s []byte) error { + q, err := strconv.Unquote(string(s)) + if err != nil { + return err + } + parsed, err := ParseRFC822Time(q) + if err != nil { + return err + } + t.Time = parsed + return nil +} + +func (t RFC822Time) String() string { + return t.Format(RFC1123) +} + +func (t RFC822Time) StringWithOffset() string { + return t.Format(RFC1123Z) +} diff --git a/vendor/github.com/vulcand/oxy/internal/holsterv4/clock/system.go b/vendor/github.com/vulcand/oxy/internal/holsterv4/clock/system.go new file mode 100644 index 0000000..04d6673 --- /dev/null +++ b/vendor/github.com/vulcand/oxy/internal/holsterv4/clock/system.go @@ -0,0 +1,68 @@ +package clock + +import "time" + +type systemTime struct{} + +func (st *systemTime) Now() time.Time { + return time.Now() +} + +func (st *systemTime) Sleep(d time.Duration) { + time.Sleep(d) +} + +func (st *systemTime) After(d time.Duration) <-chan time.Time { + return time.After(d) +} + +type systemTimer struct { + t *time.Timer +} + +func (st *systemTime) NewTimer(d time.Duration) Timer { + t := time.NewTimer(d) + return &systemTimer{t} +} + +func (st *systemTime) AfterFunc(d time.Duration, f func()) Timer { + t := time.AfterFunc(d, f) + return &systemTimer{t} +} + +func (t *systemTimer) C() <-chan time.Time { + return t.t.C +} + +func (t *systemTimer) Stop() bool { + return t.t.Stop() +} + +func (t *systemTimer) Reset(d time.Duration) bool { + return t.t.Reset(d) +} + +type systemTicker struct { + t *time.Ticker +} + +func (t *systemTicker) C() <-chan time.Time { + return t.t.C +} + +func (t *systemTicker) Stop() { + t.t.Stop() +} + +func (st *systemTime) NewTicker(d time.Duration) Ticker { + t := time.NewTicker(d) + return &systemTicker{t} +} + +func (st *systemTime) Tick(d time.Duration) <-chan time.Time { + return time.Tick(d) +} + +func (st *systemTime) Wait4Scheduled(count int, timeout time.Duration) bool { + panic("Not supported") +} diff --git a/vendor/github.com/vulcand/oxy/trace/trace.go b/vendor/github.com/vulcand/oxy/trace/trace.go index 48b6d1d..ce5e51d 100644 --- a/vendor/github.com/vulcand/oxy/trace/trace.go +++ b/vendor/github.com/vulcand/oxy/trace/trace.go @@ -11,13 +11,14 @@ import ( "time" log "github.com/sirupsen/logrus" + "github.com/vulcand/oxy/internal/holsterv4/clock" "github.com/vulcand/oxy/utils" ) -// Option is a functional option setter for Tracer +// Option is a functional option setter for Tracer. type Option func(*Tracer) error -// ErrorHandler is a functional argument that sets error handler of the server +// ErrorHandler is a functional argument that sets error handler of the server. func ErrorHandler(h utils.ErrorHandler) Option { return func(t *Tracer) error { t.errHandler = h @@ -25,7 +26,7 @@ func ErrorHandler(h utils.ErrorHandler) Option { } } -// RequestHeaders adds request headers to capture +// RequestHeaders adds request headers to capture. func RequestHeaders(headers ...string) Option { return func(t *Tracer) error { t.reqHeaders = append(t.reqHeaders, headers...) @@ -33,7 +34,7 @@ func RequestHeaders(headers ...string) Option { } } -// ResponseHeaders adds response headers to capture +// ResponseHeaders adds response headers to capture. func ResponseHeaders(headers ...string) Option { return func(t *Tracer) error { t.respHeaders = append(t.respHeaders, headers...) @@ -41,7 +42,7 @@ func ResponseHeaders(headers ...string) Option { } } -// Tracer records request and response emitting JSON structured data to the output +// Tracer records request and response emitting JSON structured data to the output. type Tracer struct { errHandler utils.ErrorHandler next http.Handler @@ -84,11 +85,11 @@ func Logger(l *log.Logger) Option { } func (t *Tracer) ServeHTTP(w http.ResponseWriter, req *http.Request) { - start := time.Now() + start := clock.Now() pw := utils.NewProxyWriterWithLogger(w, t.log) t.next.ServeHTTP(pw, req) - l := t.newRecord(req, pw, time.Since(start)) + l := t.newRecord(req, pw, clock.Since(start)) if err := json.NewEncoder(t.writer).Encode(l); err != nil { t.log.Errorf("Failed to marshal request: %v", err) } @@ -106,7 +107,7 @@ func (t *Tracer) newRecord(req *http.Request, pw *utils.ProxyWriter, diff time.D Response: Response{ Code: pw.StatusCode(), BodyBytes: bodyBytes(pw.Header()), - Roundtrip: float64(diff) / float64(time.Millisecond), + Roundtrip: float64(diff) / float64(clock.Millisecond), Headers: captureHeaders(pw.Header(), t.respHeaders), }, } @@ -141,13 +142,13 @@ func captureHeaders(in http.Header, headers []string) http.Header { return out } -// Record represents a structured request and response record +// Record represents a structured request and response record. type Record struct { Request Request `json:"request"` Response Response `json:"response"` } -// Request contains information about an HTTP request +// Request contains information about an HTTP request. type Request struct { Method string `json:"method"` // Method - request method BodyBytes int64 `json:"body_bytes"` // BodyBytes - size of request body in bytes @@ -156,7 +157,7 @@ type Request struct { TLS *TLS `json:"tls,omitempty"` // TLS - optional TLS record, will be recorded if it's a TLS connection } -// Response contains information about HTTP response +// Response contains information about HTTP response. type Response struct { Code int `json:"code"` // Code - response status code Roundtrip float64 `json:"roundtrip"` // Roundtrip - round trip time in milliseconds @@ -164,7 +165,7 @@ type Response struct { BodyBytes int64 `json:"body_bytes"` // BodyBytes - size of response body in bytes } -// TLS contains information about this TLS connection +// TLS contains information about this TLS connection. type TLS struct { Version string `json:"version"` // Version - TLS version Resume bool `json:"resume"` // Resume tells if the session has been re-used (session tickets) diff --git a/vendor/github.com/vulcand/oxy/utils/auth.go b/vendor/github.com/vulcand/oxy/utils/auth.go index 4fd819c..4bb2b0f 100644 --- a/vendor/github.com/vulcand/oxy/utils/auth.go +++ b/vendor/github.com/vulcand/oxy/utils/auth.go @@ -6,7 +6,7 @@ import ( "strings" ) -// BasicAuth basic auth information +// BasicAuth basic auth information. type BasicAuth struct { Username string Password string @@ -17,11 +17,11 @@ func (ba *BasicAuth) String() string { return fmt.Sprintf("Basic %s", encoded) } -// ParseAuthHeader creates a new BasicAuth from header values +// ParseAuthHeader creates a new BasicAuth from header values. func ParseAuthHeader(header string) (*BasicAuth, error) { values := strings.Fields(header) if len(values) != 2 { - return nil, fmt.Errorf(fmt.Sprintf("Failed to parse header '%s'", header)) + return nil, fmt.Errorf("Failed to parse header '%s'", header) } authType := strings.ToLower(values[0]) diff --git a/vendor/github.com/vulcand/oxy/utils/dumpreq.go b/vendor/github.com/vulcand/oxy/utils/dumpreq.go index eecb222..f1eab2d 100644 --- a/vendor/github.com/vulcand/oxy/utils/dumpreq.go +++ b/vendor/github.com/vulcand/oxy/utils/dumpreq.go @@ -9,8 +9,12 @@ import ( "net/url" ) -// SerializableHttpRequest serializable HTTP request -type SerializableHttpRequest struct { +// SerializableHttpRequest alias on SerializableHTTPRequest. +// Deprecated: use SerializableHTTPRequest instead. +type SerializableHttpRequest = SerializableHTTPRequest + +// SerializableHTTPRequest serializable HTTP request. +type SerializableHTTPRequest struct { Method string URL *url.URL Proto string // "HTTP/1.0" @@ -29,13 +33,13 @@ type SerializableHttpRequest struct { TLS *tls.ConnectionState } -// Clone clone a request -func Clone(r *http.Request) *SerializableHttpRequest { +// Clone clone a request. +func Clone(r *http.Request) *SerializableHTTPRequest { if r == nil { return nil } - rc := new(SerializableHttpRequest) + rc := new(SerializableHTTPRequest) rc.Method = r.Method rc.URL = r.URL rc.Proto = r.Proto @@ -49,16 +53,28 @@ func Clone(r *http.Request) *SerializableHttpRequest { return rc } -// ToJson serializes to JSON -func (s *SerializableHttpRequest) ToJson() string { +// ToJson serializes to JSON. +// Deprecated: use ToJSON instead. +func (s *SerializableHTTPRequest) ToJson() string { + return s.ToJSON() +} + +// ToJSON serializes to JSON. +func (s *SerializableHTTPRequest) ToJSON() string { jsonVal, err := json.Marshal(s) if err != nil || jsonVal == nil { - return fmt.Sprintf("Error marshalling SerializableHttpRequest to json: %s", err) + return fmt.Sprintf("Error marshalling SerializableHTTPRequest to json: %s", err) } return string(jsonVal) } -// DumpHttpRequest dump a HTTP request to JSON +// DumpHttpRequest dump a HTTP request to JSON. +// Deprecated: use DumpHTTPRequest instead. func DumpHttpRequest(req *http.Request) string { - return Clone(req).ToJson() + return DumpHTTPRequest(req) +} + +// DumpHTTPRequest dump a HTTP request to JSON. +func DumpHTTPRequest(req *http.Request) string { + return Clone(req).ToJSON() } diff --git a/vendor/github.com/vulcand/oxy/utils/handler.go b/vendor/github.com/vulcand/oxy/utils/handler.go index 24b9e3a..fde2b34 100644 --- a/vendor/github.com/vulcand/oxy/utils/handler.go +++ b/vendor/github.com/vulcand/oxy/utils/handler.go @@ -9,21 +9,21 @@ import ( log "github.com/sirupsen/logrus" ) -// StatusClientClosedRequest non-standard HTTP status code for client disconnection +// StatusClientClosedRequest non-standard HTTP status code for client disconnection. const StatusClientClosedRequest = 499 -// StatusClientClosedRequestText non-standard HTTP status for client disconnection +// StatusClientClosedRequestText non-standard HTTP status for client disconnection. const StatusClientClosedRequestText = "Client Closed Request" -// ErrorHandler error handler +// ErrorHandler error handler. type ErrorHandler interface { ServeHTTP(w http.ResponseWriter, req *http.Request, err error) } -// DefaultHandler default error handler +// DefaultHandler default error handler. var DefaultHandler ErrorHandler = &StdHandler{} -// StdHandler Standard error handler +// StdHandler Standard error handler. type StdHandler struct{} func (e *StdHandler) ServeHTTP(w http.ResponseWriter, req *http.Request, err error) { @@ -42,7 +42,7 @@ func (e *StdHandler) ServeHTTP(w http.ResponseWriter, req *http.Request, err err } w.WriteHeader(statusCode) - w.Write([]byte(statusText(statusCode))) + _, _ = w.Write([]byte(statusText(statusCode))) log.Debugf("'%d %s' caused by: %v", statusCode, statusText(statusCode), err) } @@ -53,7 +53,7 @@ func statusText(statusCode int) string { return http.StatusText(statusCode) } -// ErrorHandlerFunc error handler function type +// ErrorHandlerFunc error handler function type. type ErrorHandlerFunc func(http.ResponseWriter, *http.Request, error) // ServeHTTP calls f(w, r). diff --git a/vendor/github.com/vulcand/oxy/utils/netutils.go b/vendor/github.com/vulcand/oxy/utils/netutils.go index 692d300..b6845f7 100644 --- a/vendor/github.com/vulcand/oxy/utils/netutils.go +++ b/vendor/github.com/vulcand/oxy/utils/netutils.go @@ -12,7 +12,7 @@ import ( log "github.com/sirupsen/logrus" ) -// ProxyWriter calls recorder, used to debug logs +// ProxyWriter calls recorder, used to debug logs. type ProxyWriter struct { w http.ResponseWriter code int @@ -21,12 +21,12 @@ type ProxyWriter struct { log *log.Logger } -// NewProxyWriter creates a new ProxyWriter +// NewProxyWriter creates a new ProxyWriter. func NewProxyWriter(w http.ResponseWriter) *ProxyWriter { return NewProxyWriterWithLogger(w, log.StandardLogger()) } -// NewProxyWriterWithLogger creates a new ProxyWriter +// NewProxyWriterWithLogger creates a new ProxyWriter. func NewProxyWriterWithLogger(w http.ResponseWriter, l *log.Logger) *ProxyWriter { return &ProxyWriter{ w: w, @@ -34,7 +34,7 @@ func NewProxyWriterWithLogger(w http.ResponseWriter, l *log.Logger) *ProxyWriter } } -// StatusCode gets status code +// StatusCode gets status code. func (p *ProxyWriter) StatusCode() int { if p.code == 0 { // per contract standard lib will set this to http.StatusOK if not set @@ -44,28 +44,28 @@ func (p *ProxyWriter) StatusCode() int { return p.code } -// GetLength gets content length +// GetLength gets content length. func (p *ProxyWriter) GetLength() int64 { return p.length } -// Header gets response header +// Header gets response header. func (p *ProxyWriter) Header() http.Header { return p.w.Header() } func (p *ProxyWriter) Write(buf []byte) (int, error) { - p.length = p.length + int64(len(buf)) + p.length += int64(len(buf)) return p.w.Write(buf) } -// WriteHeader writes status code +// WriteHeader writes status code. func (p *ProxyWriter) WriteHeader(code int) { p.code = code p.w.WriteHeader(code) } -// Flush flush the writer +// Flush flush the writer. func (p *ProxyWriter) Flush() { if f, ok := p.w.(http.Flusher); ok { f.Flush() @@ -91,7 +91,7 @@ func (p *ProxyWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { return nil, nil, fmt.Errorf("the response writer that was wrapped in this proxy, does not implement http.Hijacker. It is of type: %v", reflect.TypeOf(p.w)) } -// NewBufferWriter creates a new BufferWriter +// NewBufferWriter creates a new BufferWriter. func NewBufferWriter(w io.WriteCloser) *BufferWriter { return &BufferWriter{ W: w, @@ -99,19 +99,19 @@ func NewBufferWriter(w io.WriteCloser) *BufferWriter { } } -// BufferWriter buffer writer +// BufferWriter buffer writer. type BufferWriter struct { H http.Header Code int W io.WriteCloser } -// Close close the writer +// Close close the writer. func (b *BufferWriter) Close() error { return b.W.Close() } -// Header gets response header +// Header gets response header. func (b *BufferWriter) Header() http.Header { return b.H } @@ -120,7 +120,7 @@ func (b *BufferWriter) Write(buf []byte) (int, error) { return b.W.Write(buf) } -// WriteHeader writes status code +// WriteHeader writes status code. func (b *BufferWriter) WriteHeader(code int) { b.Code = code } @@ -156,24 +156,25 @@ func NopWriteCloser(w io.Writer) io.WriteCloser { return &nopWriteCloser{Writer: w} } -// CopyURL provides update safe copy by avoiding shallow copying User field +// CopyURL provides update safe copy by avoiding shallow copying User field. func CopyURL(i *url.URL) *url.URL { out := *i if i.User != nil { - out.User = &(*i.User) + u := *i.User + out.User = &u } return &out } // CopyHeaders copies http headers from source to destination, it -// does not overide, but adds multiple headers +// does not override, but adds multiple headers. func CopyHeaders(dst http.Header, src http.Header) { for k, vv := range src { dst[k] = append(dst[k], vv...) } } -// HasHeaders determines whether any of the header names is present in the http headers +// HasHeaders determines whether any of the header names is present in the http headers. func HasHeaders(names []string, headers http.Header) bool { for _, h := range names { if headers.Get(h) != "" { @@ -183,7 +184,7 @@ func HasHeaders(names []string, headers http.Header) bool { return false } -// RemoveHeaders removes the header with the given names from the headers map +// RemoveHeaders removes the header with the given names from the headers map. func RemoveHeaders(headers http.Header, names ...string) { for _, h := range names { headers.Del(h) diff --git a/vendor/github.com/vulcand/oxy/utils/source.go b/vendor/github.com/vulcand/oxy/utils/source.go index 5306b59..d8d6c27 100644 --- a/vendor/github.com/vulcand/oxy/utils/source.go +++ b/vendor/github.com/vulcand/oxy/utils/source.go @@ -8,23 +8,23 @@ import ( // SourceExtractor extracts the source from the request, e.g. that may be client ip, or particular header that // identifies the source. amount stands for amount of connections the source consumes, usually 1 for connection limiters -// error should be returned when source can not be identified +// error should be returned when source can not be identified. type SourceExtractor interface { Extract(req *http.Request) (token string, amount int64, err error) } -// ExtractorFunc extractor function type +// ExtractorFunc extractor function type. type ExtractorFunc func(req *http.Request) (token string, amount int64, err error) -// Extract extract from request +// Extract extract from request. func (f ExtractorFunc) Extract(req *http.Request) (string, int64, error) { return f(req) } -// ExtractSource extract source function type +// ExtractSource extract source function type. type ExtractSource func(req *http.Request) -// NewExtractor creates a new SourceExtractor +// NewExtractor creates a new SourceExtractor. func NewExtractor(variable string) (SourceExtractor, error) { if variable == "client.ip" { return ExtractorFunc(extractClientIP), nil @@ -34,7 +34,7 @@ func NewExtractor(variable string) (SourceExtractor, error) { } if strings.HasPrefix(variable, "request.header.") { header := strings.TrimPrefix(variable, "request.header.") - if len(header) == 0 { + if header == "" { return nil, fmt.Errorf("wrong header: %s", header) } return makeHeaderExtractor(header), nil @@ -44,7 +44,7 @@ func NewExtractor(variable string) (SourceExtractor, error) { func extractClientIP(req *http.Request) (string, int64, error) { vals := strings.SplitN(req.RemoteAddr, ":", 2) - if len(vals[0]) == 0 { + if vals[0] == "" { return "", 0, fmt.Errorf("failed to parse client IP: %v", req.RemoteAddr) } return vals[0], 1, nil diff --git a/vendor/modules.txt b/vendor/modules.txt index 10cfc39..9208495 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -132,19 +132,20 @@ github.com/prometheus/procfs/internal/util # github.com/sirupsen/logrus v1.8.1 ## explicit; go 1.13 github.com/sirupsen/logrus -# github.com/vulcand/oxy v1.3.0 -## explicit; go 1.14 +# github.com/vulcand/oxy v1.4.0 +## explicit; go 1.17 github.com/vulcand/oxy/buffer github.com/vulcand/oxy/forward +github.com/vulcand/oxy/internal/holsterv4/clock github.com/vulcand/oxy/trace github.com/vulcand/oxy/utils # github.com/vulcand/predicate v1.2.0 ## explicit; go 1.16 github.com/vulcand/predicate -# golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 +# golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f ## explicit; go 1.17 golang.org/x/crypto/ssh/terminal -# golang.org/x/net v0.0.0-20220412020605-290c469a71a5 +# golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 ## explicit; go 1.17 golang.org/x/net/context golang.org/x/net/html