Merge pull request #75289 from dims/update-http2-dep-go-1.12

Update golang.org/x/net/... dependencies to release-branch.go1.12
pull/564/head
Kubernetes Prow Robot 2019-03-13 04:33:46 -07:00 committed by GitHub
commit e7d09ceb50
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
91 changed files with 5568 additions and 4380 deletions

51
Godeps/Godeps.json generated
View File

@ -3,6 +3,9 @@
"GoVersion": "go1.12", "GoVersion": "go1.12",
"GodepVersion": "v80-k8s-r1", "GodepVersion": "v80-k8s-r1",
"Packages": [ "Packages": [
"golang.org/x/net/internal/nettest",
"golang.org/x/net/internal/socks",
"golang.org/x/net/internal/sockstest",
"github.com/bazelbuild/bazel-gazelle/cmd/gazelle", "github.com/bazelbuild/bazel-gazelle/cmd/gazelle",
"github.com/bazelbuild/buildtools/buildozer", "github.com/bazelbuild/buildtools/buildozer",
"github.com/cespare/prettybench", "github.com/cespare/prettybench",
@ -2385,8 +2388,8 @@
}, },
{ {
"ImportPath": "github.com/grpc-ecosystem/go-grpc-middleware", "ImportPath": "github.com/grpc-ecosystem/go-grpc-middleware",
"Comment": "v1.0.0-4-g498ae206fc3cfe", "Comment": "v1.0.0-8-gcfaf5686ec79ff",
"Rev": "498ae206fc3cfe81cd82e48c1d4354026fa5f9ec" "Rev": "cfaf5686ec79ff8344257723b6f5ba1ae0ffeb4d"
}, },
{ {
"ImportPath": "github.com/grpc-ecosystem/go-grpc-prometheus", "ImportPath": "github.com/grpc-ecosystem/go-grpc-prometheus",
@ -3622,55 +3625,67 @@
}, },
{ {
"ImportPath": "golang.org/x/net/context", "ImportPath": "golang.org/x/net/context",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/context/ctxhttp", "ImportPath": "golang.org/x/net/context/ctxhttp",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/html", "ImportPath": "golang.org/x/net/html",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/html/atom", "ImportPath": "golang.org/x/net/html/atom",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/html/charset", "ImportPath": "golang.org/x/net/html/charset",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/http/httpguts",
"Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/internal/nettest",
"Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/internal/socks",
"Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/internal/sockstest",
"Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/internal/timeseries", "ImportPath": "golang.org/x/net/internal/timeseries",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
}, },
{ {
"ImportPath": "golang.org/x/net/proxy", "ImportPath": "golang.org/x/net/proxy",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/trace", "ImportPath": "golang.org/x/net/trace",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/websocket", "ImportPath": "golang.org/x/net/websocket",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/oauth2", "ImportPath": "golang.org/x/oauth2",

109
Godeps/LICENSES generated
View File

@ -101156,6 +101156,41 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================================================ ================================================================================
================================================================================
= vendor/golang.org/x/net/http/httpguts licensed under: =
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
= vendor/golang.org/x/net/LICENSE 5d4950ecb7b26d2c5e4e7b4e0dd74707
================================================================================
================================================================================ ================================================================================
= vendor/golang.org/x/net/http2 licensed under: = = vendor/golang.org/x/net/http2 licensed under: =
@ -101262,7 +101297,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================================================ ================================================================================
= vendor/golang.org/x/net/internal/timeseries licensed under: = = vendor/golang.org/x/net/internal/nettest licensed under: =
Copyright (c) 2009 The Go Authors. All rights reserved. Copyright (c) 2009 The Go Authors. All rights reserved.
@ -101297,7 +101332,77 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
================================================================================ ================================================================================
= vendor/golang.org/x/net/lex/httplex licensed under: = = vendor/golang.org/x/net/internal/socks licensed under: =
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
= vendor/golang.org/x/net/LICENSE 5d4950ecb7b26d2c5e4e7b4e0dd74707
================================================================================
================================================================================
= vendor/golang.org/x/net/internal/sockstest licensed under: =
Copyright (c) 2009 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
= vendor/golang.org/x/net/LICENSE 5d4950ecb7b26d2c5e4e7b4e0dd74707
================================================================================
================================================================================
= vendor/golang.org/x/net/internal/timeseries licensed under: =
Copyright (c) 2009 The Go Authors. All rights reserved. Copyright (c) 2009 The Go Authors. All rights reserved.

View File

@ -52,9 +52,23 @@ if [[ -d Godeps ]]; then
mv Godeps "${BACKUP}/Godeps" mv Godeps "${BACKUP}/Godeps"
fi fi
## Workaround "httplex" was dropped from golang.org/x/net repo and the code
## was moved to the "golang.org/x/net/http/httpguts" directory, we do not use
## this directly, however many packages we vendor are still using the older
## golang.org/x/net and we need to keep this until all those dependencies
## are switched to newer golang.org/x/net.
IGNORED_PACKAGES=(
"golang.org/x/net/lex/httplex"
)
REQUIRED_BINS=(
"golang.org/x/net/internal/nettest"
"golang.org/x/net/internal/socks"
"golang.org/x/net/internal/sockstest"
)
# Some things we want in godeps aren't code dependencies, so ./... # Some things we want in godeps aren't code dependencies, so ./...
# won't pick them up. # won't pick them up.
REQUIRED_BINS=( REQUIRED_BINS+=(
"github.com/bazelbuild/bazel-gazelle/cmd/gazelle" "github.com/bazelbuild/bazel-gazelle/cmd/gazelle"
"github.com/bazelbuild/buildtools/buildozer" "github.com/bazelbuild/buildtools/buildozer"
"github.com/cespare/prettybench" "github.com/cespare/prettybench"
@ -74,7 +88,7 @@ kube::log::status "Running godep save - this might take a while"
# This uses $(pwd) rather than ${KUBE_ROOT} because KUBE_ROOT will be # This uses $(pwd) rather than ${KUBE_ROOT} because KUBE_ROOT will be
# realpath'ed, and godep barfs ("... is not using a known version control # realpath'ed, and godep barfs ("... is not using a known version control
# system") on our staging dirs. # system") on our staging dirs.
GOPATH="${GOPATH}:$(pwd)/staging" ${KUBE_GODEP:?} save "${REQUIRED_BINS[@]}" GOPATH="${GOPATH}:$(pwd)/staging" ${KUBE_GODEP:?} save -i $(IFS=,; echo "${IGNORED_PACKAGES[*]}") "${REQUIRED_BINS[@]}"
# create a symlink in vendor directory pointing to the staging client. This # create a symlink in vendor directory pointing to the staging client. This
# let other packages use the staging client as if it were vendored. # let other packages use the staging client as if it were vendored.

View File

@ -54,21 +54,21 @@
"ImportPath": "github.com/stretchr/testify/require", "ImportPath": "github.com/stretchr/testify/require",
"Rev": "c679ae2cc0cb27ec3293fea7e254e47386f05d69" "Rev": "c679ae2cc0cb27ec3293fea7e254e47386f05d69"
}, },
{
"ImportPath": "golang.org/x/net/http/httpguts",
"Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
}, },
{ {
"ImportPath": "golang.org/x/text/secure/bidirule", "ImportPath": "golang.org/x/text/secure/bidirule",

View File

@ -488,7 +488,7 @@
}, },
{ {
"ImportPath": "github.com/grpc-ecosystem/go-grpc-middleware", "ImportPath": "github.com/grpc-ecosystem/go-grpc-middleware",
"Rev": "498ae206fc3cfe81cd82e48c1d4354026fa5f9ec" "Rev": "cfaf5686ec79ff8344257723b6f5ba1ae0ffeb4d"
}, },
{ {
"ImportPath": "github.com/grpc-ecosystem/go-grpc-prometheus", "ImportPath": "github.com/grpc-ecosystem/go-grpc-prometheus",
@ -688,35 +688,35 @@
}, },
{ {
"ImportPath": "golang.org/x/net/context", "ImportPath": "golang.org/x/net/context",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/http/httpguts",
"Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/internal/timeseries", "ImportPath": "golang.org/x/net/internal/timeseries",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
}, },
{ {
"ImportPath": "golang.org/x/net/trace", "ImportPath": "golang.org/x/net/trace",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/websocket", "ImportPath": "golang.org/x/net/websocket",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/oauth2", "ImportPath": "golang.org/x/oauth2",

View File

@ -120,31 +120,31 @@
}, },
{ {
"ImportPath": "golang.org/x/net/html", "ImportPath": "golang.org/x/net/html",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/html/atom", "ImportPath": "golang.org/x/net/html/atom",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/http/httpguts",
"Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
}, },
{ {
"ImportPath": "golang.org/x/net/websocket", "ImportPath": "golang.org/x/net/websocket",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/text/secure/bidirule", "ImportPath": "golang.org/x/text/secure/bidirule",

View File

@ -468,7 +468,7 @@
}, },
{ {
"ImportPath": "github.com/grpc-ecosystem/go-grpc-middleware", "ImportPath": "github.com/grpc-ecosystem/go-grpc-middleware",
"Rev": "498ae206fc3cfe81cd82e48c1d4354026fa5f9ec" "Rev": "cfaf5686ec79ff8344257723b6f5ba1ae0ffeb4d"
}, },
{ {
"ImportPath": "github.com/grpc-ecosystem/go-grpc-prometheus", "ImportPath": "github.com/grpc-ecosystem/go-grpc-prometheus",
@ -696,35 +696,35 @@
}, },
{ {
"ImportPath": "golang.org/x/net/context", "ImportPath": "golang.org/x/net/context",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/http/httpguts",
"Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/internal/timeseries", "ImportPath": "golang.org/x/net/internal/timeseries",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
}, },
{ {
"ImportPath": "golang.org/x/net/trace", "ImportPath": "golang.org/x/net/trace",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/websocket", "ImportPath": "golang.org/x/net/websocket",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/oauth2", "ImportPath": "golang.org/x/oauth2",

View File

@ -168,23 +168,23 @@
}, },
{ {
"ImportPath": "golang.org/x/net/context", "ImportPath": "golang.org/x/net/context",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/http/httpguts",
"Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
}, },
{ {
"ImportPath": "golang.org/x/oauth2", "ImportPath": "golang.org/x/oauth2",

View File

@ -192,27 +192,27 @@
}, },
{ {
"ImportPath": "golang.org/x/net/context", "ImportPath": "golang.org/x/net/context",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/context/ctxhttp", "ImportPath": "golang.org/x/net/context/ctxhttp",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/http/httpguts",
"Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
}, },
{ {
"ImportPath": "golang.org/x/oauth2", "ImportPath": "golang.org/x/oauth2",

View File

@ -84,23 +84,23 @@
}, },
{ {
"ImportPath": "golang.org/x/net/context", "ImportPath": "golang.org/x/net/context",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/http/httpguts",
"Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
}, },
{ {
"ImportPath": "golang.org/x/oauth2", "ImportPath": "golang.org/x/oauth2",

View File

@ -18,21 +18,21 @@
"ImportPath": "github.com/google/gofuzz", "ImportPath": "github.com/google/gofuzz",
"Rev": "24818f796faf91cd76ec7bddd72458fbced7a6c1" "Rev": "24818f796faf91cd76ec7bddd72458fbced7a6c1"
}, },
{
"ImportPath": "golang.org/x/net/http/httpguts",
"Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
}, },
{ {
"ImportPath": "golang.org/x/text/secure/bidirule", "ImportPath": "golang.org/x/text/secure/bidirule",

View File

@ -22,21 +22,21 @@
"ImportPath": "github.com/spf13/pflag", "ImportPath": "github.com/spf13/pflag",
"Rev": "583c0c0531f06d5278b7d917446061adc344b5cd" "Rev": "583c0c0531f06d5278b7d917446061adc344b5cd"
}, },
{
"ImportPath": "golang.org/x/net/http/httpguts",
"Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
}, },
{ {
"ImportPath": "golang.org/x/text/secure/bidirule", "ImportPath": "golang.org/x/text/secure/bidirule",

View File

@ -84,23 +84,23 @@
}, },
{ {
"ImportPath": "golang.org/x/net/context", "ImportPath": "golang.org/x/net/context",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/http/httpguts",
"Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
}, },
{ {
"ImportPath": "golang.org/x/oauth2", "ImportPath": "golang.org/x/oauth2",

View File

@ -18,21 +18,21 @@
"ImportPath": "github.com/google/gofuzz", "ImportPath": "github.com/google/gofuzz",
"Rev": "24818f796faf91cd76ec7bddd72458fbced7a6c1" "Rev": "24818f796faf91cd76ec7bddd72458fbced7a6c1"
}, },
{
"ImportPath": "golang.org/x/net/http/httpguts",
"Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
}, },
{ {
"ImportPath": "golang.org/x/text/secure/bidirule", "ImportPath": "golang.org/x/text/secure/bidirule",

View File

@ -268,43 +268,43 @@
}, },
{ {
"ImportPath": "golang.org/x/net/context", "ImportPath": "golang.org/x/net/context",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/html", "ImportPath": "golang.org/x/net/html",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/html/atom", "ImportPath": "golang.org/x/net/html/atom",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/http/httpguts",
"Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/internal/timeseries", "ImportPath": "golang.org/x/net/internal/timeseries",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
}, },
{ {
"ImportPath": "golang.org/x/net/trace", "ImportPath": "golang.org/x/net/trace",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/websocket", "ImportPath": "golang.org/x/net/websocket",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/oauth2", "ImportPath": "golang.org/x/oauth2",

View File

@ -18,21 +18,21 @@
"ImportPath": "github.com/google/gofuzz", "ImportPath": "github.com/google/gofuzz",
"Rev": "24818f796faf91cd76ec7bddd72458fbced7a6c1" "Rev": "24818f796faf91cd76ec7bddd72458fbced7a6c1"
}, },
{
"ImportPath": "golang.org/x/net/http/httpguts",
"Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
}, },
{ {
"ImportPath": "golang.org/x/text/secure/bidirule", "ImportPath": "golang.org/x/text/secure/bidirule",

View File

@ -18,21 +18,21 @@
"ImportPath": "github.com/google/gofuzz", "ImportPath": "github.com/google/gofuzz",
"Rev": "24818f796faf91cd76ec7bddd72458fbced7a6c1" "Rev": "24818f796faf91cd76ec7bddd72458fbced7a6c1"
}, },
{
"ImportPath": "golang.org/x/net/http/httpguts",
"Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
}, },
{ {
"ImportPath": "golang.org/x/text/secure/bidirule", "ImportPath": "golang.org/x/text/secure/bidirule",

View File

@ -18,21 +18,21 @@
"ImportPath": "github.com/google/gofuzz", "ImportPath": "github.com/google/gofuzz",
"Rev": "24818f796faf91cd76ec7bddd72458fbced7a6c1" "Rev": "24818f796faf91cd76ec7bddd72458fbced7a6c1"
}, },
{
"ImportPath": "golang.org/x/net/http/httpguts",
"Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
}, },
{ {
"ImportPath": "golang.org/x/text/secure/bidirule", "ImportPath": "golang.org/x/text/secure/bidirule",

View File

@ -18,21 +18,21 @@
"ImportPath": "github.com/google/gofuzz", "ImportPath": "github.com/google/gofuzz",
"Rev": "24818f796faf91cd76ec7bddd72458fbced7a6c1" "Rev": "24818f796faf91cd76ec7bddd72458fbced7a6c1"
}, },
{
"ImportPath": "golang.org/x/net/http/httpguts",
"Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
}, },
{ {
"ImportPath": "golang.org/x/text/secure/bidirule", "ImportPath": "golang.org/x/text/secure/bidirule",

View File

@ -88,23 +88,23 @@
}, },
{ {
"ImportPath": "golang.org/x/net/context", "ImportPath": "golang.org/x/net/context",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/http/httpguts",
"Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
}, },
{ {
"ImportPath": "golang.org/x/oauth2", "ImportPath": "golang.org/x/oauth2",

View File

@ -84,23 +84,23 @@
}, },
{ {
"ImportPath": "golang.org/x/net/context", "ImportPath": "golang.org/x/net/context",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/http/httpguts",
"Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
}, },
{ {
"ImportPath": "golang.org/x/oauth2", "ImportPath": "golang.org/x/oauth2",

View File

@ -248,35 +248,35 @@
}, },
{ {
"ImportPath": "golang.org/x/net/context", "ImportPath": "golang.org/x/net/context",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/http/httpguts",
"Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/internal/timeseries", "ImportPath": "golang.org/x/net/internal/timeseries",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
}, },
{ {
"ImportPath": "golang.org/x/net/trace", "ImportPath": "golang.org/x/net/trace",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/websocket", "ImportPath": "golang.org/x/net/websocket",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/oauth2", "ImportPath": "golang.org/x/oauth2",

View File

@ -160,23 +160,23 @@
}, },
{ {
"ImportPath": "golang.org/x/net/context", "ImportPath": "golang.org/x/net/context",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/http/httpguts",
"Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
}, },
{ {
"ImportPath": "golang.org/x/oauth2", "ImportPath": "golang.org/x/oauth2",

View File

@ -96,23 +96,23 @@
}, },
{ {
"ImportPath": "golang.org/x/net/context", "ImportPath": "golang.org/x/net/context",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/http/httpguts",
"Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2", "ImportPath": "golang.org/x/net/http2",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/http2/hpack", "ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
}, },
{ {
"ImportPath": "golang.org/x/net/idna", "ImportPath": "golang.org/x/net/idna",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" "Rev": "65e2d4e15006aab9813ff8769e768bbf4bb667a0"
},
{
"ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
}, },
{ {
"ImportPath": "golang.org/x/oauth2", "ImportPath": "golang.org/x/oauth2",

View File

@ -1,8 +1,11 @@
package main package main
import ( import (
"fmt"
"go/build" "go/build"
"os"
"regexp" "regexp"
"sort"
"strings" "strings"
) )
@ -42,9 +45,19 @@ func LoadPackages(names ...string) (a []*Package, err error) {
if len(names) == 0 { if len(names) == 0 {
return nil, nil return nil, nil
} }
pkgs := strings.Split(ignorePackages, ",")
sort.Strings(pkgs)
for _, i := range importPaths(names) { for _, i := range importPaths(names) {
p, err := listPackage(i) p, err := listPackage(i)
if err != nil { if err != nil {
if len(pkgs) > 0 {
idx := sort.SearchStrings(pkgs, i)
if idx < len(pkgs) && pkgs[idx] == i {
fmt.Fprintf(os.Stderr, "warning: ignoring package %q \n", i)
continue
}
}
return nil, err return nil, err
} }
a = append(a, p) a = append(a, p)

View File

@ -64,12 +64,13 @@ For more about specifying packages, see 'go help packages'.
var ( var (
saveR, saveT bool saveR, saveT bool
ignorePackages string
) )
func init() { func init() {
cmdSave.Flag.BoolVar(&saveR, "r", false, "rewrite import paths") cmdSave.Flag.BoolVar(&saveR, "r", false, "rewrite import paths")
cmdSave.Flag.BoolVar(&saveT, "t", false, "save test files") cmdSave.Flag.BoolVar(&saveT, "t", false, "save test files")
cmdSave.Flag.StringVar(&ignorePackages, "i", "", "list of packages to ignore separated by commas")
} }
func runSave(cmd *Command, args []string) { func runSave(cmd *Command, args []string) {

5
vendor/BUILD vendored
View File

@ -400,10 +400,13 @@ filegroup(
"//vendor/golang.org/x/lint:all-srcs", "//vendor/golang.org/x/lint:all-srcs",
"//vendor/golang.org/x/net/context:all-srcs", "//vendor/golang.org/x/net/context:all-srcs",
"//vendor/golang.org/x/net/html:all-srcs", "//vendor/golang.org/x/net/html:all-srcs",
"//vendor/golang.org/x/net/http/httpguts:all-srcs",
"//vendor/golang.org/x/net/http2:all-srcs", "//vendor/golang.org/x/net/http2:all-srcs",
"//vendor/golang.org/x/net/idna:all-srcs", "//vendor/golang.org/x/net/idna:all-srcs",
"//vendor/golang.org/x/net/internal/nettest:all-srcs",
"//vendor/golang.org/x/net/internal/socks:all-srcs",
"//vendor/golang.org/x/net/internal/sockstest:all-srcs",
"//vendor/golang.org/x/net/internal/timeseries:all-srcs", "//vendor/golang.org/x/net/internal/timeseries:all-srcs",
"//vendor/golang.org/x/net/lex/httplex:all-srcs",
"//vendor/golang.org/x/net/proxy:all-srcs", "//vendor/golang.org/x/net/proxy:all-srcs",
"//vendor/golang.org/x/net/trace:all-srcs", "//vendor/golang.org/x/net/trace:all-srcs",
"//vendor/golang.org/x/net/websocket:all-srcs", "//vendor/golang.org/x/net/websocket:all-srcs",

View File

@ -1,7 +1,7 @@
sudo: false sudo: false
language: go language: go
go: go:
- 1.8.x - 1.11.x
env: env:
- DEP_VERSION="0.3.2" - DEP_VERSION="0.3.2"
@ -15,7 +15,6 @@ install:
- dep ensure - dep ensure
script: script:
- make checkdocs
- make test - make test
after_success: after_success:

View File

@ -1,166 +0,0 @@
# grpc_middleware
`import "github.com/grpc-ecosystem/go-grpc-middleware"`
* [Overview](#pkg-overview)
* [Imported Packages](#pkg-imports)
* [Index](#pkg-index)
## <a name="pkg-overview">Overview</a>
`grpc_middleware` is a collection of gRPC middleware packages: interceptors, helpers and tools.
### Middleware
gRPC is a fantastic RPC middleware, which sees a lot of adoption in the Golang world. However, the
upstream gRPC codebase is relatively bare bones.
This package, and most of its child packages provides commonly needed middleware for gRPC:
client-side interceptors for retires, server-side interceptors for input validation and auth,
functions for chaining said interceptors, metadata convenience methods and more.
### Chaining
By default, gRPC doesn't allow one to have more than one interceptor either on the client nor on
the server side. `grpc_middleware` provides convenient chaining methods
Simple way of turning a multiple interceptors into a single interceptor. Here's an example for
server chaining:
myServer := grpc.NewServer(
grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(loggingStream, monitoringStream, authStream)),
grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(loggingUnary, monitoringUnary, authUnary),
)
These interceptors will be executed from left to right: logging, monitoring and auth.
Here's an example for client side chaining:
clientConn, err = grpc.Dial(
address,
grpc.WithUnaryInterceptor(grpc_middleware.ChainUnaryClient(monitoringClientUnary, retryUnary)),
grpc.WithStreamInterceptor(grpc_middleware.ChainStreamClient(monitoringClientStream, retryStream)),
)
client = pb_testproto.NewTestServiceClient(clientConn)
resp, err := client.PingEmpty(s.ctx, &myservice.Request{Msg: "hello"})
These interceptors will be executed from left to right: monitoring and then retry logic.
The retry interceptor will call every interceptor that follows it whenever when a retry happens.
### Writing Your Own
Implementing your own interceptor is pretty trivial: there are interfaces for that. But the interesting
bit exposing common data to handlers (and other middleware), similarly to HTTP Middleware design.
For example, you may want to pass the identity of the caller from the auth interceptor all the way
to the handling function.
For example, a client side interceptor example for auth looks like:
func FakeAuthUnaryInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
newCtx := context.WithValue(ctx, "user_id", "john@example.com")
return handler(newCtx, req)
}
Unfortunately, it's not as easy for streaming RPCs. These have the `context.Context` embedded within
the `grpc.ServerStream` object. To pass values through context, a wrapper (`WrappedServerStream`) is
needed. For example:
func FakeAuthStreamingInterceptor(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
newStream := grpc_middleware.WrapServerStream(stream)
newStream.WrappedContext = context.WithValue(ctx, "user_id", "john@example.com")
return handler(srv, stream)
}
## <a name="pkg-imports">Imported Packages</a>
- [golang.org/x/net/context](https://godoc.org/golang.org/x/net/context)
- [google.golang.org/grpc](https://godoc.org/google.golang.org/grpc)
## <a name="pkg-index">Index</a>
* [func ChainStreamClient(interceptors ...grpc.StreamClientInterceptor) grpc.StreamClientInterceptor](#ChainStreamClient)
* [func ChainStreamServer(interceptors ...grpc.StreamServerInterceptor) grpc.StreamServerInterceptor](#ChainStreamServer)
* [func ChainUnaryClient(interceptors ...grpc.UnaryClientInterceptor) grpc.UnaryClientInterceptor](#ChainUnaryClient)
* [func ChainUnaryServer(interceptors ...grpc.UnaryServerInterceptor) grpc.UnaryServerInterceptor](#ChainUnaryServer)
* [func WithStreamServerChain(interceptors ...grpc.StreamServerInterceptor) grpc.ServerOption](#WithStreamServerChain)
* [func WithUnaryServerChain(interceptors ...grpc.UnaryServerInterceptor) grpc.ServerOption](#WithUnaryServerChain)
* [type WrappedServerStream](#WrappedServerStream)
* [func WrapServerStream(stream grpc.ServerStream) \*WrappedServerStream](#WrapServerStream)
* [func (w \*WrappedServerStream) Context() context.Context](#WrappedServerStream.Context)
#### <a name="pkg-files">Package files</a>
[chain.go](./chain.go) [doc.go](./doc.go) [wrappers.go](./wrappers.go)
## <a name="ChainStreamClient">func</a> [ChainStreamClient](./chain.go#L136)
``` go
func ChainStreamClient(interceptors ...grpc.StreamClientInterceptor) grpc.StreamClientInterceptor
```
ChainStreamClient creates a single interceptor out of a chain of many interceptors.
Execution is done in left-to-right order, including passing of context.
For example ChainStreamClient(one, two, three) will execute one before two before three.
## <a name="ChainStreamServer">func</a> [ChainStreamServer](./chain.go#L58)
``` go
func ChainStreamServer(interceptors ...grpc.StreamServerInterceptor) grpc.StreamServerInterceptor
```
ChainStreamServer creates a single interceptor out of a chain of many interceptors.
Execution is done in left-to-right order, including passing of context.
For example ChainUnaryServer(one, two, three) will execute one before two before three.
If you want to pass context between interceptors, use WrapServerStream.
## <a name="ChainUnaryClient">func</a> [ChainUnaryClient](./chain.go#L97)
``` go
func ChainUnaryClient(interceptors ...grpc.UnaryClientInterceptor) grpc.UnaryClientInterceptor
```
ChainUnaryClient creates a single interceptor out of a chain of many interceptors.
Execution is done in left-to-right order, including passing of context.
For example ChainUnaryClient(one, two, three) will execute one before two before three.
## <a name="ChainUnaryServer">func</a> [ChainUnaryServer](./chain.go#L18)
``` go
func ChainUnaryServer(interceptors ...grpc.UnaryServerInterceptor) grpc.UnaryServerInterceptor
```
ChainUnaryServer creates a single interceptor out of a chain of many interceptors.
Execution is done in left-to-right order, including passing of context.
For example ChainUnaryServer(one, two, three) will execute one before two before three, and three
will see context changes of one and two.
## <a name="WithStreamServerChain">func</a> [WithStreamServerChain](./chain.go#L181)
``` go
func WithStreamServerChain(interceptors ...grpc.StreamServerInterceptor) grpc.ServerOption
```
WithStreamServerChain is a grpc.Server config option that accepts multiple stream interceptors.
Basically syntactic sugar.
## <a name="WithUnaryServerChain">func</a> [WithUnaryServerChain](./chain.go#L175)
``` go
func WithUnaryServerChain(interceptors ...grpc.UnaryServerInterceptor) grpc.ServerOption
```
Chain creates a single interceptor out of a chain of many interceptors.
WithUnaryServerChain is a grpc.Server config option that accepts multiple unary interceptors.
Basically syntactic sugar.
## <a name="WrappedServerStream">type</a> [WrappedServerStream](./wrappers.go#L12-L16)
``` go
type WrappedServerStream struct {
grpc.ServerStream
// WrappedContext is the wrapper's own Context. You can assign it.
WrappedContext context.Context
}
```
WrappedServerStream is a thin wrapper around grpc.ServerStream that allows modifying context.
### <a name="WrapServerStream">func</a> [WrapServerStream](./wrappers.go#L24)
``` go
func WrapServerStream(stream grpc.ServerStream) *WrappedServerStream
```
WrapServerStream returns a ServerStream that has the ability to overwrite context.
### <a name="WrappedServerStream.Context">func</a> (\*WrappedServerStream) [Context](./wrappers.go#L19)
``` go
func (w *WrappedServerStream) Context() context.Context
```
Context returns the wrapper's WrappedContext, overwriting the nested grpc.ServerStream.Context()
- - -
Generated by [godoc2ghmd](https://github.com/GandalfUK/godoc2ghmd)

View File

@ -4,14 +4,14 @@
[[projects]] [[projects]]
name = "cloud.google.com/go" name = "cloud.google.com/go"
packages = ["compute/metadata"] packages = ["compute/metadata"]
revision = "2d3a6656c17a60b0815b7e06ab0be04eacb6e613" revision = "28a4bc8c44b3acbcc482cff0cdf7de29a4688b61"
version = "v0.16.0" version = "v0.35.1"
[[projects]] [[projects]]
name = "github.com/davecgh/go-spew" name = "github.com/davecgh/go-spew"
packages = ["spew"] packages = ["spew"]
revision = "346938d642f2ec3594ed81d874461961cd0faa76" revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73"
version = "v1.1.0" version = "v1.1.1"
[[projects]] [[projects]]
name = "github.com/gogo/protobuf" name = "github.com/gogo/protobuf"
@ -23,7 +23,13 @@
branch = "master" branch = "master"
name = "github.com/golang/protobuf" name = "github.com/golang/protobuf"
packages = ["jsonpb","proto","ptypes","ptypes/any","ptypes/duration","ptypes/struct","ptypes/timestamp"] packages = ["jsonpb","proto","ptypes","ptypes/any","ptypes/duration","ptypes/struct","ptypes/timestamp"]
revision = "1e59b77b52bf8e4b449a57e6f79f21226d571845" revision = "347cf4a86c1cb8d262994d8ef5924d4576c5b331"
[[projects]]
name = "github.com/konsorten/go-windows-terminal-sequences"
packages = ["."]
revision = "5c8c8bd35d3832f5d134ae1e1e375b69a4d25242"
version = "v1.0.1"
[[projects]] [[projects]]
name = "github.com/opentracing/opentracing-go" name = "github.com/opentracing/opentracing-go"
@ -40,20 +46,20 @@
[[projects]] [[projects]]
name = "github.com/sirupsen/logrus" name = "github.com/sirupsen/logrus"
packages = ["."] packages = ["."]
revision = "f006c2ac4710855cf0f916dd6b77acf6b048dc6e" revision = "e1e72e9de974bd926e5c56f83753fba2df402ce5"
version = "v1.0.3" version = "v1.3.0"
[[projects]] [[projects]]
name = "github.com/stretchr/testify" name = "github.com/stretchr/testify"
packages = ["assert","require","suite"] packages = ["assert","require","suite"]
revision = "69483b4bd14f5845b5a1e55bca19e954e827f1d0" revision = "ffdc059bfe9ce6a4e144ba849dbedead332c6053"
version = "v1.1.4" version = "v1.3.0"
[[projects]] [[projects]]
name = "go.uber.org/atomic" name = "go.uber.org/atomic"
packages = ["."] packages = ["."]
revision = "8474b86a5a6f79c443ce4b2992817ff32cf208b8" revision = "1ea20fb1cbb1cc08cbd0d913a96dead89aa18289"
version = "v1.3.1" version = "v1.3.2"
[[projects]] [[projects]]
name = "go.uber.org/multierr" name = "go.uber.org/multierr"
@ -64,56 +70,56 @@
[[projects]] [[projects]]
name = "go.uber.org/zap" name = "go.uber.org/zap"
packages = [".","buffer","internal/bufferpool","internal/color","internal/exit","zapcore"] packages = [".","buffer","internal/bufferpool","internal/color","internal/exit","zapcore"]
revision = "35aad584952c3e7020db7b839f6b102de6271f89" revision = "ff33455a0e382e8a81d14dd7c922020b6b5e7982"
version = "v1.7.1" version = "v1.9.1"
[[projects]] [[projects]]
branch = "master" branch = "master"
name = "golang.org/x/crypto" name = "golang.org/x/crypto"
packages = ["ssh/terminal"] packages = ["ssh/terminal"]
revision = "94eea52f7b742c7cbe0b03b22f0c4c8631ece122" revision = "b01c7a72566457eb1420261cdafef86638fc3861"
[[projects]] [[projects]]
branch = "master" branch = "master"
name = "golang.org/x/net" name = "golang.org/x/net"
packages = ["context","context/ctxhttp","http2","http2/hpack","idna","internal/timeseries","lex/httplex","trace"] packages = ["context","context/ctxhttp","http/httpguts","http2","http2/hpack","idna","internal/timeseries","trace"]
revision = "a8b9294777976932365dabb6640cf1468d95c70f" revision = "d26f9f9a57f3fab6a695bec0d84433c2c50f8bbf"
[[projects]] [[projects]]
branch = "master" branch = "master"
name = "golang.org/x/oauth2" name = "golang.org/x/oauth2"
packages = [".","google","internal","jws","jwt"] packages = [".","google","internal","jws","jwt"]
revision = "f95fa95eaa936d9d87489b15d1d18b97c1ba9c28" revision = "99b60b757ec124ebb7d6b7e97f153b19c10ce163"
[[projects]] [[projects]]
branch = "master" branch = "master"
name = "golang.org/x/sys" name = "golang.org/x/sys"
packages = ["unix","windows"] packages = ["unix","windows"]
revision = "13fcbd661c8ececa8807a29b48407d674b1d8ed8" revision = "302c3dd5f1cc82baae8e44d9c3178e89b6e2b345"
[[projects]] [[projects]]
branch = "master"
name = "golang.org/x/text" name = "golang.org/x/text"
packages = ["collate","collate/build","internal/colltab","internal/gen","internal/tag","internal/triegen","internal/ucd","language","secure/bidirule","transform","unicode/bidi","unicode/cldr","unicode/norm","unicode/rangetable"] packages = ["collate","collate/build","internal/colltab","internal/gen","internal/tag","internal/triegen","internal/ucd","language","secure/bidirule","transform","unicode/bidi","unicode/cldr","unicode/norm","unicode/rangetable"]
revision = "75cc3cad82b5f47d3fb229ddda8c5167da14f294" revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
version = "v0.3.0"
[[projects]] [[projects]]
name = "google.golang.org/appengine" name = "google.golang.org/appengine"
packages = [".","internal","internal/app_identity","internal/base","internal/datastore","internal/log","internal/modules","internal/remote_api","internal/urlfetch","urlfetch"] packages = [".","internal","internal/app_identity","internal/base","internal/datastore","internal/log","internal/modules","internal/remote_api","internal/urlfetch","urlfetch"]
revision = "150dc57a1b433e64154302bdc40b6bb8aefa313a" revision = "e9657d882bb81064595ca3b56cbe2546bbabf7b1"
version = "v1.0.0" version = "v1.4.0"
[[projects]] [[projects]]
branch = "master" branch = "master"
name = "google.golang.org/genproto" name = "google.golang.org/genproto"
packages = ["googleapis/rpc/status"] packages = ["googleapis/rpc/status"]
revision = "7f0da29060c682909f650ad8ed4e515bd74fa12a" revision = "8ac453e89fca495c0d17f98932642f392e2a11f3"
[[projects]] [[projects]]
name = "google.golang.org/grpc" name = "google.golang.org/grpc"
packages = [".","balancer","balancer/roundrobin","codes","connectivity","credentials","credentials/oauth","encoding","grpclb/grpc_lb_v1/messages","grpclog","internal","keepalive","metadata","naming","peer","resolver","resolver/dns","resolver/passthrough","stats","status","tap","transport"] packages = [".","balancer","balancer/base","balancer/roundrobin","binarylog/grpc_binarylog_v1","codes","connectivity","credentials","credentials/internal","credentials/oauth","encoding","encoding/proto","grpclog","internal","internal/backoff","internal/binarylog","internal/channelz","internal/envconfig","internal/grpcrand","internal/grpcsync","internal/syscall","internal/transport","keepalive","metadata","naming","peer","resolver","resolver/dns","resolver/passthrough","stats","status","tap"]
revision = "5a9f7b402fe85096d2e1d0383435ee1876e863d0" revision = "a02b0774206b209466313a0b525d2c738fe407eb"
version = "v1.8.0" version = "v1.18.0"
[solve-meta] [solve-meta]
analyzer-name = "dep" analyzer-name = "dep"

View File

@ -11,8 +11,6 @@
[gRPC Go](https://github.com/grpc/grpc-go) Middleware: interceptors, helpers, utilities. [gRPC Go](https://github.com/grpc/grpc-go) Middleware: interceptors, helpers, utilities.
**Important** The repo recently moved to `github.com/grpc-ecosystem/go-grpc-middleware`, please update your import paths.
## Middleware ## Middleware
[gRPC Go](https://github.com/grpc/grpc-go) recently acquired support for [gRPC Go](https://github.com/grpc/grpc-go) recently acquired support for
@ -24,7 +22,7 @@ These are generic building blocks that make it easy to build multiple microservi
The purpose of this repository is to act as a go-to point for such reusable functionality. It contains The purpose of this repository is to act as a go-to point for such reusable functionality. It contains
some of them itself, but also will link to useful external repos. some of them itself, but also will link to useful external repos.
`grpc_middleware` itself provides support for chaining interceptors. See [Documentation](DOC.md), but here's an example: `grpc_middleware` itself provides support for chaining interceptors, here's an example:
```go ```go
import "github.com/grpc-ecosystem/go-grpc-middleware" import "github.com/grpc-ecosystem/go-grpc-middleware"

View File

@ -1,14 +1,8 @@
SHELL="/bin/bash" SHELL=/bin/bash
GOFILES_NOVENDOR = $(shell go list ./... | grep -v /vendor/) GOFILES_NOVENDOR = $(shell go list ./... | grep -v /vendor/)
all: vet fmt docs test all: vet fmt test
docs:
./scripts/docs.sh generate
checkdocs:
./scripts/docs.sh check
fmt: fmt:
go fmt $(GOFILES_NOVENDOR) go fmt $(GOFILES_NOVENDOR)
@ -19,4 +13,4 @@ vet:
test: vet test: vet
./scripts/test_all.sh ./scripts/test_all.sh
.PHONY: all docs validate test .PHONY: all test

View File

@ -2,14 +2,10 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library( go_library(
name = "go_default_library", name = "go_default_library",
srcs = [ srcs = ["ctxhttp.go"],
"ctxhttp.go",
"ctxhttp_pre17.go",
],
importmap = "k8s.io/kubernetes/vendor/golang.org/x/net/context/ctxhttp", importmap = "k8s.io/kubernetes/vendor/golang.org/x/net/context/ctxhttp",
importpath = "golang.org/x/net/context/ctxhttp", importpath = "golang.org/x/net/context/ctxhttp",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = ["//vendor/golang.org/x/net/context:go_default_library"],
) )
filegroup( filegroup(

View File

@ -2,18 +2,15 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build go1.7
// Package ctxhttp provides helper functions for performing context-aware HTTP requests. // Package ctxhttp provides helper functions for performing context-aware HTTP requests.
package ctxhttp package ctxhttp
import ( import (
"context"
"io" "io"
"net/http" "net/http"
"net/url" "net/url"
"strings" "strings"
"golang.org/x/net/context"
) )
// Do sends an HTTP request with the provided http.Client and returns // Do sends an HTTP request with the provided http.Client and returns

View File

@ -1,147 +0,0 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !go1.7
package ctxhttp
import (
"io"
"net/http"
"net/url"
"strings"
"golang.org/x/net/context"
)
func nop() {}
var (
testHookContextDoneBeforeHeaders = nop
testHookDoReturned = nop
testHookDidBodyClose = nop
)
// Do sends an HTTP request with the provided http.Client and returns an HTTP response.
// If the client is nil, http.DefaultClient is used.
// If the context is canceled or times out, ctx.Err() will be returned.
func Do(ctx context.Context, client *http.Client, req *http.Request) (*http.Response, error) {
if client == nil {
client = http.DefaultClient
}
// TODO(djd): Respect any existing value of req.Cancel.
cancel := make(chan struct{})
req.Cancel = cancel
type responseAndError struct {
resp *http.Response
err error
}
result := make(chan responseAndError, 1)
// Make local copies of test hooks closed over by goroutines below.
// Prevents data races in tests.
testHookDoReturned := testHookDoReturned
testHookDidBodyClose := testHookDidBodyClose
go func() {
resp, err := client.Do(req)
testHookDoReturned()
result <- responseAndError{resp, err}
}()
var resp *http.Response
select {
case <-ctx.Done():
testHookContextDoneBeforeHeaders()
close(cancel)
// Clean up after the goroutine calling client.Do:
go func() {
if r := <-result; r.resp != nil {
testHookDidBodyClose()
r.resp.Body.Close()
}
}()
return nil, ctx.Err()
case r := <-result:
var err error
resp, err = r.resp, r.err
if err != nil {
return resp, err
}
}
c := make(chan struct{})
go func() {
select {
case <-ctx.Done():
close(cancel)
case <-c:
// The response's Body is closed.
}
}()
resp.Body = &notifyingReader{resp.Body, c}
return resp, nil
}
// Get issues a GET request via the Do function.
func Get(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
return Do(ctx, client, req)
}
// Head issues a HEAD request via the Do function.
func Head(ctx context.Context, client *http.Client, url string) (*http.Response, error) {
req, err := http.NewRequest("HEAD", url, nil)
if err != nil {
return nil, err
}
return Do(ctx, client, req)
}
// Post issues a POST request via the Do function.
func Post(ctx context.Context, client *http.Client, url string, bodyType string, body io.Reader) (*http.Response, error) {
req, err := http.NewRequest("POST", url, body)
if err != nil {
return nil, err
}
req.Header.Set("Content-Type", bodyType)
return Do(ctx, client, req)
}
// PostForm issues a POST request via the Do function.
func PostForm(ctx context.Context, client *http.Client, url string, data url.Values) (*http.Response, error) {
return Post(ctx, client, url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
}
// notifyingReader is an io.ReadCloser that closes the notify channel after
// Close is called or a Read fails on the underlying ReadCloser.
type notifyingReader struct {
io.ReadCloser
notify chan<- struct{}
}
func (r *notifyingReader) Read(p []byte) (int, error) {
n, err := r.ReadCloser.Read(p)
if err != nil && r.notify != nil {
close(r.notify)
r.notify = nil
}
return n, err
}
func (r *notifyingReader) Close() error {
err := r.ReadCloser.Close()
if r.notify != nil {
close(r.notify)
r.notify = nil
}
return err
}

View File

@ -306,7 +306,7 @@ func (t *table) push(i uint32, depth int) bool {
// The lists of element names and attribute keys were taken from // The lists of element names and attribute keys were taken from
// https://html.spec.whatwg.org/multipage/indices.html#index // https://html.spec.whatwg.org/multipage/indices.html#index
// as of the "HTML Living Standard - Last Updated 18 September 2017" version. // as of the "HTML Living Standard - Last Updated 16 April 2018" version.
// "command", "keygen" and "menuitem" have been removed from the spec, // "command", "keygen" and "menuitem" have been removed from the spec,
// but are kept here for backwards compatibility. // but are kept here for backwards compatibility.
@ -665,6 +665,7 @@ var eventHandlers = []string{
// extra are ad-hoc values not covered by any of the lists above. // extra are ad-hoc values not covered by any of the lists above.
var extra = []string{ var extra = []string{
"acronym",
"align", "align",
"annotation", "annotation",
"annotation-xml", "annotation-xml",
@ -700,6 +701,8 @@ var extra = []string{
"plaintext", "plaintext",
"prompt", "prompt",
"public", "public",
"rb",
"rtc",
"spacer", "spacer",
"strike", "strike",
"svg", "svg",

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@
package html package html
// Section 12.2.3.2 of the HTML5 specification says "The following elements // Section 12.2.4.2 of the HTML5 specification says "The following elements
// have varying levels of special parsing rules". // have varying levels of special parsing rules".
// https://html.spec.whatwg.org/multipage/syntax.html#the-stack-of-open-elements // https://html.spec.whatwg.org/multipage/syntax.html#the-stack-of-open-elements
var isSpecialElementMap = map[string]bool{ var isSpecialElementMap = map[string]bool{
@ -97,8 +97,16 @@ func isSpecialElement(element *Node) bool {
switch element.Namespace { switch element.Namespace {
case "", "html": case "", "html":
return isSpecialElementMap[element.Data] return isSpecialElementMap[element.Data]
case "math":
switch element.Data {
case "mi", "mo", "mn", "ms", "mtext", "annotation-xml":
return true
}
case "svg": case "svg":
return element.Data == "foreignObject" switch element.Data {
case "foreignObject", "desc", "title":
return true
}
} }
return false return false
} }

4154
vendor/golang.org/x/net/html/entity.go generated vendored

File diff suppressed because it is too large Load Diff

View File

@ -67,7 +67,7 @@ func mathMLTextIntegrationPoint(n *Node) bool {
return false return false
} }
// Section 12.2.5.5. // Section 12.2.6.5.
var breakout = map[string]bool{ var breakout = map[string]bool{
"b": true, "b": true,
"big": true, "big": true,
@ -115,7 +115,7 @@ var breakout = map[string]bool{
"var": true, "var": true,
} }
// Section 12.2.5.5. // Section 12.2.6.5.
var svgTagNameAdjustments = map[string]string{ var svgTagNameAdjustments = map[string]string{
"altglyph": "altGlyph", "altglyph": "altGlyph",
"altglyphdef": "altGlyphDef", "altglyphdef": "altGlyphDef",
@ -155,7 +155,7 @@ var svgTagNameAdjustments = map[string]string{
"textpath": "textPath", "textpath": "textPath",
} }
// Section 12.2.5.1 // Section 12.2.6.1
var mathMLAttributeAdjustments = map[string]string{ var mathMLAttributeAdjustments = map[string]string{
"definitionurl": "definitionURL", "definitionurl": "definitionURL",
} }

33
vendor/golang.org/x/net/html/node.go generated vendored
View File

@ -21,9 +21,10 @@ const (
scopeMarkerNode scopeMarkerNode
) )
// Section 12.2.3.3 says "scope markers are inserted when entering applet // Section 12.2.4.3 says "The markers are inserted when entering applet,
// elements, buttons, object elements, marquees, table cells, and table // object, marquee, template, td, th, and caption elements, and are used
// captions, and are used to prevent formatting from 'leaking'". // to prevent formatting from "leaking" into applet, object, marquee,
// template, td, th, and caption elements".
var scopeMarker = Node{Type: scopeMarkerNode} var scopeMarker = Node{Type: scopeMarkerNode}
// A Node consists of a NodeType and some Data (tag name for element nodes, // A Node consists of a NodeType and some Data (tag name for element nodes,
@ -173,6 +174,16 @@ func (s *nodeStack) index(n *Node) int {
return -1 return -1
} }
// contains returns whether a is within s.
func (s *nodeStack) contains(a atom.Atom) bool {
for _, n := range *s {
if n.DataAtom == a && n.Namespace == "" {
return true
}
}
return false
}
// insert inserts a node at the given index. // insert inserts a node at the given index.
func (s *nodeStack) insert(i int, n *Node) { func (s *nodeStack) insert(i int, n *Node) {
(*s) = append(*s, nil) (*s) = append(*s, nil)
@ -191,3 +202,19 @@ func (s *nodeStack) remove(n *Node) {
(*s)[j] = nil (*s)[j] = nil
*s = (*s)[:j] *s = (*s)[:j]
} }
type insertionModeStack []insertionMode
func (s *insertionModeStack) pop() (im insertionMode) {
i := len(*s)
im = (*s)[i-1]
*s = (*s)[:i-1]
return im
}
func (s *insertionModeStack) top() insertionMode {
if i := len(*s); i > 0 {
return (*s)[i-1]
}
return nil
}

409
vendor/golang.org/x/net/html/parse.go generated vendored
View File

@ -25,20 +25,22 @@ type parser struct {
hasSelfClosingToken bool hasSelfClosingToken bool
// doc is the document root element. // doc is the document root element.
doc *Node doc *Node
// The stack of open elements (section 12.2.3.2) and active formatting // The stack of open elements (section 12.2.4.2) and active formatting
// elements (section 12.2.3.3). // elements (section 12.2.4.3).
oe, afe nodeStack oe, afe nodeStack
// Element pointers (section 12.2.3.4). // Element pointers (section 12.2.4.4).
head, form *Node head, form *Node
// Other parsing state flags (section 12.2.3.5). // Other parsing state flags (section 12.2.4.5).
scripting, framesetOK bool scripting, framesetOK bool
// The stack of template insertion modes
templateStack insertionModeStack
// im is the current insertion mode. // im is the current insertion mode.
im insertionMode im insertionMode
// originalIM is the insertion mode to go back to after completing a text // originalIM is the insertion mode to go back to after completing a text
// or inTableText insertion mode. // or inTableText insertion mode.
originalIM insertionMode originalIM insertionMode
// fosterParenting is whether new elements should be inserted according to // fosterParenting is whether new elements should be inserted according to
// the foster parenting rules (section 12.2.5.3). // the foster parenting rules (section 12.2.6.1).
fosterParenting bool fosterParenting bool
// quirks is whether the parser is operating in "quirks mode." // quirks is whether the parser is operating in "quirks mode."
quirks bool quirks bool
@ -56,7 +58,7 @@ func (p *parser) top() *Node {
return p.doc return p.doc
} }
// Stop tags for use in popUntil. These come from section 12.2.3.2. // Stop tags for use in popUntil. These come from section 12.2.4.2.
var ( var (
defaultScopeStopTags = map[string][]a.Atom{ defaultScopeStopTags = map[string][]a.Atom{
"": {a.Applet, a.Caption, a.Html, a.Table, a.Td, a.Th, a.Marquee, a.Object, a.Template}, "": {a.Applet, a.Caption, a.Html, a.Table, a.Td, a.Th, a.Marquee, a.Object, a.Template},
@ -79,7 +81,7 @@ const (
// popUntil pops the stack of open elements at the highest element whose tag // popUntil pops the stack of open elements at the highest element whose tag
// is in matchTags, provided there is no higher element in the scope's stop // is in matchTags, provided there is no higher element in the scope's stop
// tags (as defined in section 12.2.3.2). It returns whether or not there was // tags (as defined in section 12.2.4.2). It returns whether or not there was
// such an element. If there was not, popUntil leaves the stack unchanged. // such an element. If there was not, popUntil leaves the stack unchanged.
// //
// For example, the set of stop tags for table scope is: "html", "table". If // For example, the set of stop tags for table scope is: "html", "table". If
@ -126,7 +128,7 @@ func (p *parser) indexOfElementInScope(s scope, matchTags ...a.Atom) int {
return -1 return -1
} }
case tableScope: case tableScope:
if tagAtom == a.Html || tagAtom == a.Table { if tagAtom == a.Html || tagAtom == a.Table || tagAtom == a.Template {
return -1 return -1
} }
case selectScope: case selectScope:
@ -162,17 +164,17 @@ func (p *parser) clearStackToContext(s scope) {
tagAtom := p.oe[i].DataAtom tagAtom := p.oe[i].DataAtom
switch s { switch s {
case tableScope: case tableScope:
if tagAtom == a.Html || tagAtom == a.Table { if tagAtom == a.Html || tagAtom == a.Table || tagAtom == a.Template {
p.oe = p.oe[:i+1] p.oe = p.oe[:i+1]
return return
} }
case tableRowScope: case tableRowScope:
if tagAtom == a.Html || tagAtom == a.Tr { if tagAtom == a.Html || tagAtom == a.Tr || tagAtom == a.Template {
p.oe = p.oe[:i+1] p.oe = p.oe[:i+1]
return return
} }
case tableBodyScope: case tableBodyScope:
if tagAtom == a.Html || tagAtom == a.Tbody || tagAtom == a.Tfoot || tagAtom == a.Thead { if tagAtom == a.Html || tagAtom == a.Tbody || tagAtom == a.Tfoot || tagAtom == a.Thead || tagAtom == a.Template {
p.oe = p.oe[:i+1] p.oe = p.oe[:i+1]
return return
} }
@ -183,7 +185,7 @@ func (p *parser) clearStackToContext(s scope) {
} }
// generateImpliedEndTags pops nodes off the stack of open elements as long as // generateImpliedEndTags pops nodes off the stack of open elements as long as
// the top node has a tag name of dd, dt, li, option, optgroup, p, rp, or rt. // the top node has a tag name of dd, dt, li, optgroup, option, p, rb, rp, rt or rtc.
// If exceptions are specified, nodes with that name will not be popped off. // If exceptions are specified, nodes with that name will not be popped off.
func (p *parser) generateImpliedEndTags(exceptions ...string) { func (p *parser) generateImpliedEndTags(exceptions ...string) {
var i int var i int
@ -192,7 +194,7 @@ loop:
n := p.oe[i] n := p.oe[i]
if n.Type == ElementNode { if n.Type == ElementNode {
switch n.DataAtom { switch n.DataAtom {
case a.Dd, a.Dt, a.Li, a.Option, a.Optgroup, a.P, a.Rp, a.Rt: case a.Dd, a.Dt, a.Li, a.Optgroup, a.Option, a.P, a.Rb, a.Rp, a.Rt, a.Rtc:
for _, except := range exceptions { for _, except := range exceptions {
if n.Data == except { if n.Data == except {
break loop break loop
@ -234,9 +236,9 @@ func (p *parser) shouldFosterParent() bool {
} }
// fosterParent adds a child node according to the foster parenting rules. // fosterParent adds a child node according to the foster parenting rules.
// Section 12.2.5.3, "foster parenting". // Section 12.2.6.1, "foster parenting".
func (p *parser) fosterParent(n *Node) { func (p *parser) fosterParent(n *Node) {
var table, parent, prev *Node var table, parent, prev, template *Node
var i int var i int
for i = len(p.oe) - 1; i >= 0; i-- { for i = len(p.oe) - 1; i >= 0; i-- {
if p.oe[i].DataAtom == a.Table { if p.oe[i].DataAtom == a.Table {
@ -245,6 +247,19 @@ func (p *parser) fosterParent(n *Node) {
} }
} }
var j int
for j = len(p.oe) - 1; j >= 0; j-- {
if p.oe[j].DataAtom == a.Template {
template = p.oe[j]
break
}
}
if template != nil && (table == nil || j > i) {
template.AppendChild(n)
return
}
if table == nil { if table == nil {
// The foster parent is the html element. // The foster parent is the html element.
parent = p.oe[0] parent = p.oe[0]
@ -304,7 +319,7 @@ func (p *parser) addElement() {
}) })
} }
// Section 12.2.3.3. // Section 12.2.4.3.
func (p *parser) addFormattingElement() { func (p *parser) addFormattingElement() {
tagAtom, attr := p.tok.DataAtom, p.tok.Attr tagAtom, attr := p.tok.DataAtom, p.tok.Attr
p.addElement() p.addElement()
@ -351,7 +366,7 @@ findIdenticalElements:
p.afe = append(p.afe, p.top()) p.afe = append(p.afe, p.top())
} }
// Section 12.2.3.3. // Section 12.2.4.3.
func (p *parser) clearActiveFormattingElements() { func (p *parser) clearActiveFormattingElements() {
for { for {
n := p.afe.pop() n := p.afe.pop()
@ -361,7 +376,7 @@ func (p *parser) clearActiveFormattingElements() {
} }
} }
// Section 12.2.3.3. // Section 12.2.4.3.
func (p *parser) reconstructActiveFormattingElements() { func (p *parser) reconstructActiveFormattingElements() {
n := p.afe.top() n := p.afe.top()
if n == nil { if n == nil {
@ -390,12 +405,12 @@ func (p *parser) reconstructActiveFormattingElements() {
} }
} }
// Section 12.2.4. // Section 12.2.5.
func (p *parser) acknowledgeSelfClosingTag() { func (p *parser) acknowledgeSelfClosingTag() {
p.hasSelfClosingToken = false p.hasSelfClosingToken = false
} }
// An insertion mode (section 12.2.3.1) is the state transition function from // An insertion mode (section 12.2.4.1) is the state transition function from
// a particular state in the HTML5 parser's state machine. It updates the // a particular state in the HTML5 parser's state machine. It updates the
// parser's fields depending on parser.tok (where ErrorToken means EOF). // parser's fields depending on parser.tok (where ErrorToken means EOF).
// It returns whether the token was consumed. // It returns whether the token was consumed.
@ -403,7 +418,7 @@ type insertionMode func(*parser) bool
// setOriginalIM sets the insertion mode to return to after completing a text or // setOriginalIM sets the insertion mode to return to after completing a text or
// inTableText insertion mode. // inTableText insertion mode.
// Section 12.2.3.1, "using the rules for". // Section 12.2.4.1, "using the rules for".
func (p *parser) setOriginalIM() { func (p *parser) setOriginalIM() {
if p.originalIM != nil { if p.originalIM != nil {
panic("html: bad parser state: originalIM was set twice") panic("html: bad parser state: originalIM was set twice")
@ -411,18 +426,38 @@ func (p *parser) setOriginalIM() {
p.originalIM = p.im p.originalIM = p.im
} }
// Section 12.2.3.1, "reset the insertion mode". // Section 12.2.4.1, "reset the insertion mode".
func (p *parser) resetInsertionMode() { func (p *parser) resetInsertionMode() {
for i := len(p.oe) - 1; i >= 0; i-- { for i := len(p.oe) - 1; i >= 0; i-- {
n := p.oe[i] n := p.oe[i]
if i == 0 && p.context != nil { last := i == 0
if last && p.context != nil {
n = p.context n = p.context
} }
switch n.DataAtom { switch n.DataAtom {
case a.Select: case a.Select:
if !last {
for ancestor, first := n, p.oe[0]; ancestor != first; {
if ancestor == first {
break
}
ancestor = p.oe[p.oe.index(ancestor)-1]
switch ancestor.DataAtom {
case a.Template:
p.im = inSelectIM
return
case a.Table:
p.im = inSelectInTableIM
return
}
}
}
p.im = inSelectIM p.im = inSelectIM
case a.Td, a.Th: case a.Td, a.Th:
// TODO: remove this divergence from the HTML5 spec.
//
// See https://bugs.chromium.org/p/chromium/issues/detail?id=829668
p.im = inCellIM p.im = inCellIM
case a.Tr: case a.Tr:
p.im = inRowIM p.im = inRowIM
@ -434,25 +469,41 @@ func (p *parser) resetInsertionMode() {
p.im = inColumnGroupIM p.im = inColumnGroupIM
case a.Table: case a.Table:
p.im = inTableIM p.im = inTableIM
case a.Template:
// TODO: remove this divergence from the HTML5 spec.
if n.Namespace != "" {
continue
}
p.im = p.templateStack.top()
case a.Head: case a.Head:
p.im = inBodyIM // TODO: remove this divergence from the HTML5 spec.
//
// See https://bugs.chromium.org/p/chromium/issues/detail?id=829668
p.im = inHeadIM
case a.Body: case a.Body:
p.im = inBodyIM p.im = inBodyIM
case a.Frameset: case a.Frameset:
p.im = inFramesetIM p.im = inFramesetIM
case a.Html: case a.Html:
p.im = beforeHeadIM if p.head == nil {
p.im = beforeHeadIM
} else {
p.im = afterHeadIM
}
default: default:
if last {
p.im = inBodyIM
return
}
continue continue
} }
return return
} }
p.im = inBodyIM
} }
const whitespace = " \t\r\n\f" const whitespace = " \t\r\n\f"
// Section 12.2.5.4.1. // Section 12.2.6.4.1.
func initialIM(p *parser) bool { func initialIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case TextToken: case TextToken:
@ -479,7 +530,7 @@ func initialIM(p *parser) bool {
return false return false
} }
// Section 12.2.5.4.2. // Section 12.2.6.4.2.
func beforeHTMLIM(p *parser) bool { func beforeHTMLIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case DoctypeToken: case DoctypeToken:
@ -517,7 +568,7 @@ func beforeHTMLIM(p *parser) bool {
return false return false
} }
// Section 12.2.5.4.3. // Section 12.2.6.4.3.
func beforeHeadIM(p *parser) bool { func beforeHeadIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case TextToken: case TextToken:
@ -560,7 +611,7 @@ func beforeHeadIM(p *parser) bool {
return false return false
} }
// Section 12.2.5.4.4. // Section 12.2.6.4.4.
func inHeadIM(p *parser) bool { func inHeadIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case TextToken: case TextToken:
@ -590,19 +641,41 @@ func inHeadIM(p *parser) bool {
case a.Head: case a.Head:
// Ignore the token. // Ignore the token.
return true return true
case a.Template:
p.addElement()
p.afe = append(p.afe, &scopeMarker)
p.framesetOK = false
p.im = inTemplateIM
p.templateStack = append(p.templateStack, inTemplateIM)
return true
} }
case EndTagToken: case EndTagToken:
switch p.tok.DataAtom { switch p.tok.DataAtom {
case a.Head: case a.Head:
n := p.oe.pop() p.oe.pop()
if n.DataAtom != a.Head {
panic("html: bad parser state: <head> element not found, in the in-head insertion mode")
}
p.im = afterHeadIM p.im = afterHeadIM
return true return true
case a.Body, a.Html, a.Br: case a.Body, a.Html, a.Br:
p.parseImpliedToken(EndTagToken, a.Head, a.Head.String()) p.parseImpliedToken(EndTagToken, a.Head, a.Head.String())
return false return false
case a.Template:
if !p.oe.contains(a.Template) {
return true
}
// TODO: remove this divergence from the HTML5 spec.
//
// See https://bugs.chromium.org/p/chromium/issues/detail?id=829668
p.generateImpliedEndTags()
for i := len(p.oe) - 1; i >= 0; i-- {
if n := p.oe[i]; n.Namespace == "" && n.DataAtom == a.Template {
p.oe = p.oe[:i]
break
}
}
p.clearActiveFormattingElements()
p.templateStack.pop()
p.resetInsertionMode()
return true
default: default:
// Ignore the token. // Ignore the token.
return true return true
@ -622,7 +695,7 @@ func inHeadIM(p *parser) bool {
return false return false
} }
// Section 12.2.5.4.6. // Section 12.2.6.4.6.
func afterHeadIM(p *parser) bool { func afterHeadIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case TextToken: case TextToken:
@ -648,7 +721,7 @@ func afterHeadIM(p *parser) bool {
p.addElement() p.addElement()
p.im = inFramesetIM p.im = inFramesetIM
return true return true
case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Title: case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Template, a.Title:
p.oe = append(p.oe, p.head) p.oe = append(p.oe, p.head)
defer p.oe.remove(p.head) defer p.oe.remove(p.head)
return inHeadIM(p) return inHeadIM(p)
@ -660,6 +733,8 @@ func afterHeadIM(p *parser) bool {
switch p.tok.DataAtom { switch p.tok.DataAtom {
case a.Body, a.Html, a.Br: case a.Body, a.Html, a.Br:
// Drop down to creating an implied <body> tag. // Drop down to creating an implied <body> tag.
case a.Template:
return inHeadIM(p)
default: default:
// Ignore the token. // Ignore the token.
return true return true
@ -697,7 +772,7 @@ func copyAttributes(dst *Node, src Token) {
} }
} }
// Section 12.2.5.4.7. // Section 12.2.6.4.7.
func inBodyIM(p *parser) bool { func inBodyIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case TextToken: case TextToken:
@ -727,10 +802,16 @@ func inBodyIM(p *parser) bool {
case StartTagToken: case StartTagToken:
switch p.tok.DataAtom { switch p.tok.DataAtom {
case a.Html: case a.Html:
if p.oe.contains(a.Template) {
return true
}
copyAttributes(p.oe[0], p.tok) copyAttributes(p.oe[0], p.tok)
case a.Base, a.Basefont, a.Bgsound, a.Command, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Title: case a.Base, a.Basefont, a.Bgsound, a.Command, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Template, a.Title:
return inHeadIM(p) return inHeadIM(p)
case a.Body: case a.Body:
if p.oe.contains(a.Template) {
return true
}
if len(p.oe) >= 2 { if len(p.oe) >= 2 {
body := p.oe[1] body := p.oe[1]
if body.Type == ElementNode && body.DataAtom == a.Body { if body.Type == ElementNode && body.DataAtom == a.Body {
@ -767,9 +848,13 @@ func inBodyIM(p *parser) bool {
// The newline, if any, will be dealt with by the TextToken case. // The newline, if any, will be dealt with by the TextToken case.
p.framesetOK = false p.framesetOK = false
case a.Form: case a.Form:
if p.form == nil { if p.form != nil && !p.oe.contains(a.Template) {
p.popUntil(buttonScope, a.P) // Ignore the token
p.addElement() return true
}
p.popUntil(buttonScope, a.P)
p.addElement()
if !p.oe.contains(a.Template) {
p.form = p.top() p.form = p.top()
} }
case a.Li: case a.Li:
@ -903,6 +988,14 @@ func inBodyIM(p *parser) bool {
p.acknowledgeSelfClosingTag() p.acknowledgeSelfClosingTag()
p.popUntil(buttonScope, a.P) p.popUntil(buttonScope, a.P)
p.parseImpliedToken(StartTagToken, a.Form, a.Form.String()) p.parseImpliedToken(StartTagToken, a.Form, a.Form.String())
if p.form == nil {
// NOTE: The 'isindex' element has been removed,
// and the 'template' element has not been designed to be
// collaborative with the index element.
//
// Ignore the token.
return true
}
if action != "" { if action != "" {
p.form.Attr = []Attribute{{Key: "action", Val: action}} p.form.Attr = []Attribute{{Key: "action", Val: action}}
} }
@ -952,11 +1045,16 @@ func inBodyIM(p *parser) bool {
} }
p.reconstructActiveFormattingElements() p.reconstructActiveFormattingElements()
p.addElement() p.addElement()
case a.Rp, a.Rt: case a.Rb, a.Rtc:
if p.elementInScope(defaultScope, a.Ruby) { if p.elementInScope(defaultScope, a.Ruby) {
p.generateImpliedEndTags() p.generateImpliedEndTags()
} }
p.addElement() p.addElement()
case a.Rp, a.Rt:
if p.elementInScope(defaultScope, a.Ruby) {
p.generateImpliedEndTags("rtc")
}
p.addElement()
case a.Math, a.Svg: case a.Math, a.Svg:
p.reconstructActiveFormattingElements() p.reconstructActiveFormattingElements()
if p.tok.DataAtom == a.Math { if p.tok.DataAtom == a.Math {
@ -993,15 +1091,29 @@ func inBodyIM(p *parser) bool {
case a.Address, a.Article, a.Aside, a.Blockquote, a.Button, a.Center, a.Details, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Listing, a.Menu, a.Nav, a.Ol, a.Pre, a.Section, a.Summary, a.Ul: case a.Address, a.Article, a.Aside, a.Blockquote, a.Button, a.Center, a.Details, a.Dir, a.Div, a.Dl, a.Fieldset, a.Figcaption, a.Figure, a.Footer, a.Header, a.Hgroup, a.Listing, a.Menu, a.Nav, a.Ol, a.Pre, a.Section, a.Summary, a.Ul:
p.popUntil(defaultScope, p.tok.DataAtom) p.popUntil(defaultScope, p.tok.DataAtom)
case a.Form: case a.Form:
node := p.form if p.oe.contains(a.Template) {
p.form = nil i := p.indexOfElementInScope(defaultScope, a.Form)
i := p.indexOfElementInScope(defaultScope, a.Form) if i == -1 {
if node == nil || i == -1 || p.oe[i] != node { // Ignore the token.
// Ignore the token. return true
return true }
p.generateImpliedEndTags()
if p.oe[i].DataAtom != a.Form {
// Ignore the token.
return true
}
p.popUntil(defaultScope, a.Form)
} else {
node := p.form
p.form = nil
i := p.indexOfElementInScope(defaultScope, a.Form)
if node == nil || i == -1 || p.oe[i] != node {
// Ignore the token.
return true
}
p.generateImpliedEndTags()
p.oe.remove(node)
} }
p.generateImpliedEndTags()
p.oe.remove(node)
case a.P: case a.P:
if !p.elementInScope(buttonScope, a.P) { if !p.elementInScope(buttonScope, a.P) {
p.parseImpliedToken(StartTagToken, a.P, a.P.String()) p.parseImpliedToken(StartTagToken, a.P, a.P.String())
@ -1022,6 +1134,8 @@ func inBodyIM(p *parser) bool {
case a.Br: case a.Br:
p.tok.Type = StartTagToken p.tok.Type = StartTagToken
return false return false
case a.Template:
return inHeadIM(p)
default: default:
p.inBodyEndTagOther(p.tok.DataAtom) p.inBodyEndTagOther(p.tok.DataAtom)
} }
@ -1030,6 +1144,21 @@ func inBodyIM(p *parser) bool {
Type: CommentNode, Type: CommentNode,
Data: p.tok.Data, Data: p.tok.Data,
}) })
case ErrorToken:
// TODO: remove this divergence from the HTML5 spec.
if len(p.templateStack) > 0 {
p.im = inTemplateIM
return false
} else {
for _, e := range p.oe {
switch e.DataAtom {
case a.Dd, a.Dt, a.Li, a.Optgroup, a.Option, a.P, a.Rb, a.Rp, a.Rt, a.Rtc, a.Tbody, a.Td, a.Tfoot, a.Th,
a.Thead, a.Tr, a.Body, a.Html:
default:
return true
}
}
}
} }
return true return true
@ -1160,7 +1289,7 @@ func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom) {
} }
// inBodyEndTagOther performs the "any other end tag" algorithm for inBodyIM. // inBodyEndTagOther performs the "any other end tag" algorithm for inBodyIM.
// "Any other end tag" handling from 12.2.5.5 The rules for parsing tokens in foreign content // "Any other end tag" handling from 12.2.6.5 The rules for parsing tokens in foreign content
// https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inforeign // https://html.spec.whatwg.org/multipage/syntax.html#parsing-main-inforeign
func (p *parser) inBodyEndTagOther(tagAtom a.Atom) { func (p *parser) inBodyEndTagOther(tagAtom a.Atom) {
for i := len(p.oe) - 1; i >= 0; i-- { for i := len(p.oe) - 1; i >= 0; i-- {
@ -1174,7 +1303,7 @@ func (p *parser) inBodyEndTagOther(tagAtom a.Atom) {
} }
} }
// Section 12.2.5.4.8. // Section 12.2.6.4.8.
func textIM(p *parser) bool { func textIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case ErrorToken: case ErrorToken:
@ -1203,12 +1332,9 @@ func textIM(p *parser) bool {
return p.tok.Type == EndTagToken return p.tok.Type == EndTagToken
} }
// Section 12.2.5.4.9. // Section 12.2.6.4.9.
func inTableIM(p *parser) bool { func inTableIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case ErrorToken:
// Stop parsing.
return true
case TextToken: case TextToken:
p.tok.Data = strings.Replace(p.tok.Data, "\x00", "", -1) p.tok.Data = strings.Replace(p.tok.Data, "\x00", "", -1)
switch p.oe.top().DataAtom { switch p.oe.top().DataAtom {
@ -1249,7 +1375,7 @@ func inTableIM(p *parser) bool {
} }
// Ignore the token. // Ignore the token.
return true return true
case a.Style, a.Script: case a.Style, a.Script, a.Template:
return inHeadIM(p) return inHeadIM(p)
case a.Input: case a.Input:
for _, t := range p.tok.Attr { for _, t := range p.tok.Attr {
@ -1261,7 +1387,7 @@ func inTableIM(p *parser) bool {
} }
// Otherwise drop down to the default action. // Otherwise drop down to the default action.
case a.Form: case a.Form:
if p.form != nil { if p.oe.contains(a.Template) || p.form != nil {
// Ignore the token. // Ignore the token.
return true return true
} }
@ -1291,6 +1417,8 @@ func inTableIM(p *parser) bool {
case a.Body, a.Caption, a.Col, a.Colgroup, a.Html, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr: case a.Body, a.Caption, a.Col, a.Colgroup, a.Html, a.Tbody, a.Td, a.Tfoot, a.Th, a.Thead, a.Tr:
// Ignore the token. // Ignore the token.
return true return true
case a.Template:
return inHeadIM(p)
} }
case CommentToken: case CommentToken:
p.addChild(&Node{ p.addChild(&Node{
@ -1301,6 +1429,8 @@ func inTableIM(p *parser) bool {
case DoctypeToken: case DoctypeToken:
// Ignore the token. // Ignore the token.
return true return true
case ErrorToken:
return inBodyIM(p)
} }
p.fosterParenting = true p.fosterParenting = true
@ -1309,7 +1439,7 @@ func inTableIM(p *parser) bool {
return inBodyIM(p) return inBodyIM(p)
} }
// Section 12.2.5.4.11. // Section 12.2.6.4.11.
func inCaptionIM(p *parser) bool { func inCaptionIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case StartTagToken: case StartTagToken:
@ -1355,7 +1485,7 @@ func inCaptionIM(p *parser) bool {
return inBodyIM(p) return inBodyIM(p)
} }
// Section 12.2.5.4.12. // Section 12.2.6.4.12.
func inColumnGroupIM(p *parser) bool { func inColumnGroupIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case TextToken: case TextToken:
@ -1386,11 +1516,13 @@ func inColumnGroupIM(p *parser) bool {
p.oe.pop() p.oe.pop()
p.acknowledgeSelfClosingTag() p.acknowledgeSelfClosingTag()
return true return true
case a.Template:
return inHeadIM(p)
} }
case EndTagToken: case EndTagToken:
switch p.tok.DataAtom { switch p.tok.DataAtom {
case a.Colgroup: case a.Colgroup:
if p.oe.top().DataAtom != a.Html { if p.oe.top().DataAtom == a.Colgroup {
p.oe.pop() p.oe.pop()
p.im = inTableIM p.im = inTableIM
} }
@ -1398,17 +1530,21 @@ func inColumnGroupIM(p *parser) bool {
case a.Col: case a.Col:
// Ignore the token. // Ignore the token.
return true return true
case a.Template:
return inHeadIM(p)
} }
case ErrorToken:
return inBodyIM(p)
} }
if p.oe.top().DataAtom != a.Html { if p.oe.top().DataAtom != a.Colgroup {
p.oe.pop() return true
p.im = inTableIM
return false
} }
return true p.oe.pop()
p.im = inTableIM
return false
} }
// Section 12.2.5.4.13. // Section 12.2.6.4.13.
func inTableBodyIM(p *parser) bool { func inTableBodyIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case StartTagToken: case StartTagToken:
@ -1460,7 +1596,7 @@ func inTableBodyIM(p *parser) bool {
return inTableIM(p) return inTableIM(p)
} }
// Section 12.2.5.4.14. // Section 12.2.6.4.14.
func inRowIM(p *parser) bool { func inRowIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case StartTagToken: case StartTagToken:
@ -1511,7 +1647,7 @@ func inRowIM(p *parser) bool {
return inTableIM(p) return inTableIM(p)
} }
// Section 12.2.5.4.15. // Section 12.2.6.4.15.
func inCellIM(p *parser) bool { func inCellIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case StartTagToken: case StartTagToken:
@ -1560,12 +1696,9 @@ func inCellIM(p *parser) bool {
return inBodyIM(p) return inBodyIM(p)
} }
// Section 12.2.5.4.16. // Section 12.2.6.4.16.
func inSelectIM(p *parser) bool { func inSelectIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case ErrorToken:
// Stop parsing.
return true
case TextToken: case TextToken:
p.addText(strings.Replace(p.tok.Data, "\x00", "", -1)) p.addText(strings.Replace(p.tok.Data, "\x00", "", -1))
case StartTagToken: case StartTagToken:
@ -1586,8 +1719,12 @@ func inSelectIM(p *parser) bool {
} }
p.addElement() p.addElement()
case a.Select: case a.Select:
p.tok.Type = EndTagToken if p.popUntil(selectScope, a.Select) {
return false p.resetInsertionMode()
} else {
// Ignore the token.
return true
}
case a.Input, a.Keygen, a.Textarea: case a.Input, a.Keygen, a.Textarea:
if p.elementInScope(selectScope, a.Select) { if p.elementInScope(selectScope, a.Select) {
p.parseImpliedToken(EndTagToken, a.Select, a.Select.String()) p.parseImpliedToken(EndTagToken, a.Select, a.Select.String())
@ -1597,7 +1734,7 @@ func inSelectIM(p *parser) bool {
p.tokenizer.NextIsNotRawText() p.tokenizer.NextIsNotRawText()
// Ignore the token. // Ignore the token.
return true return true
case a.Script: case a.Script, a.Template:
return inHeadIM(p) return inHeadIM(p)
} }
case EndTagToken: case EndTagToken:
@ -1617,7 +1754,12 @@ func inSelectIM(p *parser) bool {
case a.Select: case a.Select:
if p.popUntil(selectScope, a.Select) { if p.popUntil(selectScope, a.Select) {
p.resetInsertionMode() p.resetInsertionMode()
} else {
// Ignore the token.
return true
} }
case a.Template:
return inHeadIM(p)
} }
case CommentToken: case CommentToken:
p.addChild(&Node{ p.addChild(&Node{
@ -1627,30 +1769,107 @@ func inSelectIM(p *parser) bool {
case DoctypeToken: case DoctypeToken:
// Ignore the token. // Ignore the token.
return true return true
case ErrorToken:
return inBodyIM(p)
} }
return true return true
} }
// Section 12.2.5.4.17. // Section 12.2.6.4.17.
func inSelectInTableIM(p *parser) bool { func inSelectInTableIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case StartTagToken, EndTagToken: case StartTagToken, EndTagToken:
switch p.tok.DataAtom { switch p.tok.DataAtom {
case a.Caption, a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr, a.Td, a.Th: case a.Caption, a.Table, a.Tbody, a.Tfoot, a.Thead, a.Tr, a.Td, a.Th:
if p.tok.Type == StartTagToken || p.elementInScope(tableScope, p.tok.DataAtom) { if p.tok.Type == EndTagToken && !p.elementInScope(tableScope, p.tok.DataAtom) {
p.parseImpliedToken(EndTagToken, a.Select, a.Select.String())
return false
} else {
// Ignore the token. // Ignore the token.
return true return true
} }
// This is like p.popUntil(selectScope, a.Select), but it also
// matches <math select>, not just <select>. Matching the MathML
// tag is arguably incorrect (conceptually), but it mimics what
// Chromium does.
for i := len(p.oe) - 1; i >= 0; i-- {
if n := p.oe[i]; n.DataAtom == a.Select {
p.oe = p.oe[:i]
break
}
}
p.resetInsertionMode()
return false
} }
} }
return inSelectIM(p) return inSelectIM(p)
} }
// Section 12.2.5.4.18. // Section 12.2.6.4.18.
func inTemplateIM(p *parser) bool {
switch p.tok.Type {
case TextToken, CommentToken, DoctypeToken:
return inBodyIM(p)
case StartTagToken:
switch p.tok.DataAtom {
case a.Base, a.Basefont, a.Bgsound, a.Link, a.Meta, a.Noframes, a.Script, a.Style, a.Template, a.Title:
return inHeadIM(p)
case a.Caption, a.Colgroup, a.Tbody, a.Tfoot, a.Thead:
p.templateStack.pop()
p.templateStack = append(p.templateStack, inTableIM)
p.im = inTableIM
return false
case a.Col:
p.templateStack.pop()
p.templateStack = append(p.templateStack, inColumnGroupIM)
p.im = inColumnGroupIM
return false
case a.Tr:
p.templateStack.pop()
p.templateStack = append(p.templateStack, inTableBodyIM)
p.im = inTableBodyIM
return false
case a.Td, a.Th:
p.templateStack.pop()
p.templateStack = append(p.templateStack, inRowIM)
p.im = inRowIM
return false
default:
p.templateStack.pop()
p.templateStack = append(p.templateStack, inBodyIM)
p.im = inBodyIM
return false
}
case EndTagToken:
switch p.tok.DataAtom {
case a.Template:
return inHeadIM(p)
default:
// Ignore the token.
return true
}
case ErrorToken:
if !p.oe.contains(a.Template) {
// Ignore the token.
return true
}
// TODO: remove this divergence from the HTML5 spec.
//
// See https://bugs.chromium.org/p/chromium/issues/detail?id=829668
p.generateImpliedEndTags()
for i := len(p.oe) - 1; i >= 0; i-- {
if n := p.oe[i]; n.Namespace == "" && n.DataAtom == a.Template {
p.oe = p.oe[:i]
break
}
}
p.clearActiveFormattingElements()
p.templateStack.pop()
p.resetInsertionMode()
return false
}
return false
}
// Section 12.2.6.4.19.
func afterBodyIM(p *parser) bool { func afterBodyIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case ErrorToken: case ErrorToken:
@ -1688,7 +1907,7 @@ func afterBodyIM(p *parser) bool {
return false return false
} }
// Section 12.2.5.4.19. // Section 12.2.6.4.20.
func inFramesetIM(p *parser) bool { func inFramesetIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case CommentToken: case CommentToken:
@ -1738,7 +1957,7 @@ func inFramesetIM(p *parser) bool {
return true return true
} }
// Section 12.2.5.4.20. // Section 12.2.6.4.21.
func afterFramesetIM(p *parser) bool { func afterFramesetIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case CommentToken: case CommentToken:
@ -1777,7 +1996,7 @@ func afterFramesetIM(p *parser) bool {
return true return true
} }
// Section 12.2.5.4.21. // Section 12.2.6.4.22.
func afterAfterBodyIM(p *parser) bool { func afterAfterBodyIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case ErrorToken: case ErrorToken:
@ -1806,7 +2025,7 @@ func afterAfterBodyIM(p *parser) bool {
return false return false
} }
// Section 12.2.5.4.22. // Section 12.2.6.4.23.
func afterAfterFramesetIM(p *parser) bool { func afterAfterFramesetIM(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case CommentToken: case CommentToken:
@ -1844,7 +2063,7 @@ func afterAfterFramesetIM(p *parser) bool {
const whitespaceOrNUL = whitespace + "\x00" const whitespaceOrNUL = whitespace + "\x00"
// Section 12.2.5.5. // Section 12.2.6.5
func parseForeignContent(p *parser) bool { func parseForeignContent(p *parser) bool {
switch p.tok.Type { switch p.tok.Type {
case TextToken: case TextToken:
@ -1924,7 +2143,7 @@ func parseForeignContent(p *parser) bool {
return true return true
} }
// Section 12.2.5. // Section 12.2.6.
func (p *parser) inForeignContent() bool { func (p *parser) inForeignContent() bool {
if len(p.oe) == 0 { if len(p.oe) == 0 {
return false return false
@ -2012,6 +2231,15 @@ func (p *parser) parse() error {
} }
// Parse returns the parse tree for the HTML from the given Reader. // Parse returns the parse tree for the HTML from the given Reader.
//
// It implements the HTML5 parsing algorithm
// (https://html.spec.whatwg.org/multipage/syntax.html#tree-construction),
// which is very complicated. The resultant tree can contain implicitly created
// nodes that have no explicit <tag> listed in r's data, and nodes' parents can
// differ from the nesting implied by a naive processing of start and end
// <tag>s. Conversely, explicit <tag>s in r's data can be silently dropped,
// with no corresponding node in the resulting tree.
//
// The input is assumed to be UTF-8 encoded. // The input is assumed to be UTF-8 encoded.
func Parse(r io.Reader) (*Node, error) { func Parse(r io.Reader) (*Node, error) {
p := &parser{ p := &parser{
@ -2033,6 +2261,8 @@ func Parse(r io.Reader) (*Node, error) {
// ParseFragment parses a fragment of HTML and returns the nodes that were // ParseFragment parses a fragment of HTML and returns the nodes that were
// found. If the fragment is the InnerHTML for an existing element, pass that // found. If the fragment is the InnerHTML for an existing element, pass that
// element in context. // element in context.
//
// It has the same intricacies as Parse.
func ParseFragment(r io.Reader, context *Node) ([]*Node, error) { func ParseFragment(r io.Reader, context *Node) ([]*Node, error) {
contextTag := "" contextTag := ""
if context != nil { if context != nil {
@ -2064,6 +2294,9 @@ func ParseFragment(r io.Reader, context *Node) ([]*Node, error) {
} }
p.doc.AppendChild(root) p.doc.AppendChild(root)
p.oe = nodeStack{root} p.oe = nodeStack{root}
if context != nil && context.DataAtom == a.Template {
p.templateStack = append(p.templateStack, inTemplateIM)
}
p.resetInsertionMode() p.resetInsertionMode()
for n := context; n != nil; n = n.Parent { for n := context; n != nil; n = n.Parent {

View File

@ -2,9 +2,12 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library( go_library(
name = "go_default_library", name = "go_default_library",
srcs = ["httplex.go"], srcs = [
importmap = "k8s.io/kubernetes/vendor/golang.org/x/net/lex/httplex", "guts.go",
importpath = "golang.org/x/net/lex/httplex", "httplex.go",
],
importmap = "k8s.io/kubernetes/vendor/golang.org/x/net/http/httpguts",
importpath = "golang.org/x/net/http/httpguts",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = ["//vendor/golang.org/x/net/idna:go_default_library"], deps = ["//vendor/golang.org/x/net/idna:go_default_library"],
) )

50
vendor/golang.org/x/net/http/httpguts/guts.go generated vendored Normal file
View File

@ -0,0 +1,50 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package httpguts provides functions implementing various details
// of the HTTP specification.
//
// This package is shared by the standard library (which vendors it)
// and x/net/http2. It comes with no API stability promise.
package httpguts
import (
"net/textproto"
"strings"
)
// ValidTrailerHeader reports whether name is a valid header field name to appear
// in trailers.
// See RFC 7230, Section 4.1.2
func ValidTrailerHeader(name string) bool {
name = textproto.CanonicalMIMEHeaderKey(name)
if strings.HasPrefix(name, "If-") || badTrailer[name] {
return false
}
return true
}
var badTrailer = map[string]bool{
"Authorization": true,
"Cache-Control": true,
"Connection": true,
"Content-Encoding": true,
"Content-Length": true,
"Content-Range": true,
"Content-Type": true,
"Expect": true,
"Host": true,
"Keep-Alive": true,
"Max-Forwards": true,
"Pragma": true,
"Proxy-Authenticate": true,
"Proxy-Authorization": true,
"Proxy-Connection": true,
"Range": true,
"Realm": true,
"Te": true,
"Trailer": true,
"Transfer-Encoding": true,
"Www-Authenticate": true,
}

View File

@ -2,12 +2,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// Package httplex contains rules around lexical matters of various package httpguts
// HTTP-related specifications.
//
// This package is shared by the standard library (which vendors it)
// and x/net/http2. It comes with no API stability promise.
package httplex
import ( import (
"net" "net"

14
vendor/golang.org/x/net/http2/BUILD generated vendored
View File

@ -5,23 +5,15 @@ go_library(
srcs = [ srcs = [
"ciphers.go", "ciphers.go",
"client_conn_pool.go", "client_conn_pool.go",
"configure_transport.go",
"databuffer.go", "databuffer.go",
"errors.go", "errors.go",
"flow.go", "flow.go",
"frame.go", "frame.go",
"go16.go", "go111.go",
"go17.go",
"go17_not18.go",
"go18.go",
"go19.go",
"gotrack.go", "gotrack.go",
"headermap.go", "headermap.go",
"http2.go", "http2.go",
"not_go16.go", "not_go111.go",
"not_go17.go",
"not_go18.go",
"not_go19.go",
"pipe.go", "pipe.go",
"server.go", "server.go",
"transport.go", "transport.go",
@ -34,9 +26,9 @@ go_library(
importpath = "golang.org/x/net/http2", importpath = "golang.org/x/net/http2",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = [
"//vendor/golang.org/x/net/http/httpguts:go_default_library",
"//vendor/golang.org/x/net/http2/hpack:go_default_library", "//vendor/golang.org/x/net/http2/hpack:go_default_library",
"//vendor/golang.org/x/net/idna:go_default_library", "//vendor/golang.org/x/net/idna:go_default_library",
"//vendor/golang.org/x/net/lex/httplex:go_default_library",
], ],
) )

View File

@ -52,9 +52,31 @@ const (
noDialOnMiss = false noDialOnMiss = false
) )
// shouldTraceGetConn reports whether getClientConn should call any
// ClientTrace.GetConn hook associated with the http.Request.
//
// This complexity is needed to avoid double calls of the GetConn hook
// during the back-and-forth between net/http and x/net/http2 (when the
// net/http.Transport is upgraded to also speak http2), as well as support
// the case where x/net/http2 is being used directly.
func (p *clientConnPool) shouldTraceGetConn(st clientConnIdleState) bool {
// If our Transport wasn't made via ConfigureTransport, always
// trace the GetConn hook if provided, because that means the
// http2 package is being used directly and it's the one
// dialing, as opposed to net/http.
if _, ok := p.t.ConnPool.(noDialClientConnPool); !ok {
return true
}
// Otherwise, only use the GetConn hook if this connection has
// been used previously for other requests. For fresh
// connections, the net/http package does the dialing.
return !st.freshConn
}
func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMiss bool) (*ClientConn, error) { func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMiss bool) (*ClientConn, error) {
if isConnectionCloseRequest(req) && dialOnMiss { if isConnectionCloseRequest(req) && dialOnMiss {
// It gets its own connection. // It gets its own connection.
traceGetConn(req, addr)
const singleUse = true const singleUse = true
cc, err := p.t.dialClientConn(addr, singleUse) cc, err := p.t.dialClientConn(addr, singleUse)
if err != nil { if err != nil {
@ -64,7 +86,10 @@ func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMis
} }
p.mu.Lock() p.mu.Lock()
for _, cc := range p.conns[addr] { for _, cc := range p.conns[addr] {
if cc.CanTakeNewRequest() { if st := cc.idleState(); st.canTakeNewRequest {
if p.shouldTraceGetConn(st) {
traceGetConn(req, addr)
}
p.mu.Unlock() p.mu.Unlock()
return cc, nil return cc, nil
} }
@ -73,6 +98,7 @@ func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMis
p.mu.Unlock() p.mu.Unlock()
return nil, ErrNoCachedConn return nil, ErrNoCachedConn
} }
traceGetConn(req, addr)
call := p.getStartDialLocked(addr) call := p.getStartDialLocked(addr)
p.mu.Unlock() p.mu.Unlock()
<-call.done <-call.done

View File

@ -1,80 +0,0 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.6
package http2
import (
"crypto/tls"
"fmt"
"net/http"
)
func configureTransport(t1 *http.Transport) (*Transport, error) {
connPool := new(clientConnPool)
t2 := &Transport{
ConnPool: noDialClientConnPool{connPool},
t1: t1,
}
connPool.t = t2
if err := registerHTTPSProtocol(t1, noDialH2RoundTripper{t2}); err != nil {
return nil, err
}
if t1.TLSClientConfig == nil {
t1.TLSClientConfig = new(tls.Config)
}
if !strSliceContains(t1.TLSClientConfig.NextProtos, "h2") {
t1.TLSClientConfig.NextProtos = append([]string{"h2"}, t1.TLSClientConfig.NextProtos...)
}
if !strSliceContains(t1.TLSClientConfig.NextProtos, "http/1.1") {
t1.TLSClientConfig.NextProtos = append(t1.TLSClientConfig.NextProtos, "http/1.1")
}
upgradeFn := func(authority string, c *tls.Conn) http.RoundTripper {
addr := authorityAddr("https", authority)
if used, err := connPool.addConnIfNeeded(addr, t2, c); err != nil {
go c.Close()
return erringRoundTripper{err}
} else if !used {
// Turns out we don't need this c.
// For example, two goroutines made requests to the same host
// at the same time, both kicking off TCP dials. (since protocol
// was unknown)
go c.Close()
}
return t2
}
if m := t1.TLSNextProto; len(m) == 0 {
t1.TLSNextProto = map[string]func(string, *tls.Conn) http.RoundTripper{
"h2": upgradeFn,
}
} else {
m["h2"] = upgradeFn
}
return t2, nil
}
// registerHTTPSProtocol calls Transport.RegisterProtocol but
// converting panics into errors.
func registerHTTPSProtocol(t *http.Transport, rt http.RoundTripper) (err error) {
defer func() {
if e := recover(); e != nil {
err = fmt.Errorf("%v", e)
}
}()
t.RegisterProtocol("https", rt)
return nil
}
// noDialH2RoundTripper is a RoundTripper which only tries to complete the request
// if there's already has a cached connection to the host.
type noDialH2RoundTripper struct{ t *Transport }
func (rt noDialH2RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
res, err := rt.t.RoundTrip(req)
if isNoCachedConnError(err) {
return nil, http.ErrSkipAltProtocol
}
return res, err
}

View File

@ -41,10 +41,10 @@ func (f *flow) take(n int32) {
// add adds n bytes (positive or negative) to the flow control window. // add adds n bytes (positive or negative) to the flow control window.
// It returns false if the sum would exceed 2^31-1. // It returns false if the sum would exceed 2^31-1.
func (f *flow) add(n int32) bool { func (f *flow) add(n int32) bool {
remain := (1<<31 - 1) - f.n sum := f.n + n
if n > remain { if (sum > n) == (f.n > 0) {
return false f.n = sum
return true
} }
f.n += n return false
return true
} }

View File

@ -14,8 +14,8 @@ import (
"strings" "strings"
"sync" "sync"
"golang.org/x/net/http/httpguts"
"golang.org/x/net/http2/hpack" "golang.org/x/net/http2/hpack"
"golang.org/x/net/lex/httplex"
) )
const frameHeaderLen = 9 const frameHeaderLen = 9
@ -733,32 +733,67 @@ func (f *SettingsFrame) IsAck() bool {
return f.FrameHeader.Flags.Has(FlagSettingsAck) return f.FrameHeader.Flags.Has(FlagSettingsAck)
} }
func (f *SettingsFrame) Value(s SettingID) (v uint32, ok bool) { func (f *SettingsFrame) Value(id SettingID) (v uint32, ok bool) {
f.checkValid() f.checkValid()
buf := f.p for i := 0; i < f.NumSettings(); i++ {
for len(buf) > 0 { if s := f.Setting(i); s.ID == id {
settingID := SettingID(binary.BigEndian.Uint16(buf[:2])) return s.Val, true
if settingID == s {
return binary.BigEndian.Uint32(buf[2:6]), true
} }
buf = buf[6:]
} }
return 0, false return 0, false
} }
// Setting returns the setting from the frame at the given 0-based index.
// The index must be >= 0 and less than f.NumSettings().
func (f *SettingsFrame) Setting(i int) Setting {
buf := f.p
return Setting{
ID: SettingID(binary.BigEndian.Uint16(buf[i*6 : i*6+2])),
Val: binary.BigEndian.Uint32(buf[i*6+2 : i*6+6]),
}
}
func (f *SettingsFrame) NumSettings() int { return len(f.p) / 6 }
// HasDuplicates reports whether f contains any duplicate setting IDs.
func (f *SettingsFrame) HasDuplicates() bool {
num := f.NumSettings()
if num == 0 {
return false
}
// If it's small enough (the common case), just do the n^2
// thing and avoid a map allocation.
if num < 10 {
for i := 0; i < num; i++ {
idi := f.Setting(i).ID
for j := i + 1; j < num; j++ {
idj := f.Setting(j).ID
if idi == idj {
return true
}
}
}
return false
}
seen := map[SettingID]bool{}
for i := 0; i < num; i++ {
id := f.Setting(i).ID
if seen[id] {
return true
}
seen[id] = true
}
return false
}
// ForeachSetting runs fn for each setting. // ForeachSetting runs fn for each setting.
// It stops and returns the first error. // It stops and returns the first error.
func (f *SettingsFrame) ForeachSetting(fn func(Setting) error) error { func (f *SettingsFrame) ForeachSetting(fn func(Setting) error) error {
f.checkValid() f.checkValid()
buf := f.p for i := 0; i < f.NumSettings(); i++ {
for len(buf) > 0 { if err := fn(f.Setting(i)); err != nil {
if err := fn(Setting{
SettingID(binary.BigEndian.Uint16(buf[:2])),
binary.BigEndian.Uint32(buf[2:6]),
}); err != nil {
return err return err
} }
buf = buf[6:]
} }
return nil return nil
} }
@ -1442,7 +1477,7 @@ func (fr *Framer) maxHeaderStringLen() int {
} }
// readMetaFrame returns 0 or more CONTINUATION frames from fr and // readMetaFrame returns 0 or more CONTINUATION frames from fr and
// merge them into into the provided hf and returns a MetaHeadersFrame // merge them into the provided hf and returns a MetaHeadersFrame
// with the decoded hpack values. // with the decoded hpack values.
func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) { func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) {
if fr.AllowIllegalReads { if fr.AllowIllegalReads {
@ -1462,7 +1497,7 @@ func (fr *Framer) readMetaFrame(hf *HeadersFrame) (*MetaHeadersFrame, error) {
if VerboseLogs && fr.logReads { if VerboseLogs && fr.logReads {
fr.debugReadLoggerf("http2: decoded hpack field %+v", hf) fr.debugReadLoggerf("http2: decoded hpack field %+v", hf)
} }
if !httplex.ValidHeaderFieldValue(hf.Value) { if !httpguts.ValidHeaderFieldValue(hf.Value) {
invalid = headerFieldValueError(hf.Value) invalid = headerFieldValueError(hf.Value)
} }
isPseudo := strings.HasPrefix(hf.Name, ":") isPseudo := strings.HasPrefix(hf.Name, ":")

29
vendor/golang.org/x/net/http2/go111.go generated vendored Normal file
View File

@ -0,0 +1,29 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.11
package http2
import (
"net/http/httptrace"
"net/textproto"
)
func traceHasWroteHeaderField(trace *httptrace.ClientTrace) bool {
return trace != nil && trace.WroteHeaderField != nil
}
func traceWroteHeaderField(trace *httptrace.ClientTrace, k, v string) {
if trace != nil && trace.WroteHeaderField != nil {
trace.WroteHeaderField(k, []string{v})
}
}
func traceGot1xxResponseFunc(trace *httptrace.ClientTrace) func(int, textproto.MIMEHeader) error {
if trace != nil {
return trace.Got1xxResponse
}
return nil
}

View File

@ -1,16 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.6
package http2
import (
"net/http"
"time"
)
func transportExpectContinueTimeout(t1 *http.Transport) time.Duration {
return t1.ExpectContinueTimeout
}

106
vendor/golang.org/x/net/http2/go17.go generated vendored
View File

@ -1,106 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.7
package http2
import (
"context"
"net"
"net/http"
"net/http/httptrace"
"time"
)
type contextContext interface {
context.Context
}
func serverConnBaseContext(c net.Conn, opts *ServeConnOpts) (ctx contextContext, cancel func()) {
ctx, cancel = context.WithCancel(context.Background())
ctx = context.WithValue(ctx, http.LocalAddrContextKey, c.LocalAddr())
if hs := opts.baseConfig(); hs != nil {
ctx = context.WithValue(ctx, http.ServerContextKey, hs)
}
return
}
func contextWithCancel(ctx contextContext) (_ contextContext, cancel func()) {
return context.WithCancel(ctx)
}
func requestWithContext(req *http.Request, ctx contextContext) *http.Request {
return req.WithContext(ctx)
}
type clientTrace httptrace.ClientTrace
func reqContext(r *http.Request) context.Context { return r.Context() }
func (t *Transport) idleConnTimeout() time.Duration {
if t.t1 != nil {
return t.t1.IdleConnTimeout
}
return 0
}
func setResponseUncompressed(res *http.Response) { res.Uncompressed = true }
func traceGotConn(req *http.Request, cc *ClientConn) {
trace := httptrace.ContextClientTrace(req.Context())
if trace == nil || trace.GotConn == nil {
return
}
ci := httptrace.GotConnInfo{Conn: cc.tconn}
cc.mu.Lock()
ci.Reused = cc.nextStreamID > 1
ci.WasIdle = len(cc.streams) == 0 && ci.Reused
if ci.WasIdle && !cc.lastActive.IsZero() {
ci.IdleTime = time.Now().Sub(cc.lastActive)
}
cc.mu.Unlock()
trace.GotConn(ci)
}
func traceWroteHeaders(trace *clientTrace) {
if trace != nil && trace.WroteHeaders != nil {
trace.WroteHeaders()
}
}
func traceGot100Continue(trace *clientTrace) {
if trace != nil && trace.Got100Continue != nil {
trace.Got100Continue()
}
}
func traceWait100Continue(trace *clientTrace) {
if trace != nil && trace.Wait100Continue != nil {
trace.Wait100Continue()
}
}
func traceWroteRequest(trace *clientTrace, err error) {
if trace != nil && trace.WroteRequest != nil {
trace.WroteRequest(httptrace.WroteRequestInfo{Err: err})
}
}
func traceFirstResponseByte(trace *clientTrace) {
if trace != nil && trace.GotFirstResponseByte != nil {
trace.GotFirstResponseByte()
}
}
func requestTrace(req *http.Request) *clientTrace {
trace := httptrace.ContextClientTrace(req.Context())
return (*clientTrace)(trace)
}
// Ping sends a PING frame to the server and waits for the ack.
func (cc *ClientConn) Ping(ctx context.Context) error {
return cc.ping(ctx)
}

View File

@ -1,36 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.7,!go1.8
package http2
import "crypto/tls"
// temporary copy of Go 1.7's private tls.Config.clone:
func cloneTLSConfig(c *tls.Config) *tls.Config {
return &tls.Config{
Rand: c.Rand,
Time: c.Time,
Certificates: c.Certificates,
NameToCertificate: c.NameToCertificate,
GetCertificate: c.GetCertificate,
RootCAs: c.RootCAs,
NextProtos: c.NextProtos,
ServerName: c.ServerName,
ClientAuth: c.ClientAuth,
ClientCAs: c.ClientCAs,
InsecureSkipVerify: c.InsecureSkipVerify,
CipherSuites: c.CipherSuites,
PreferServerCipherSuites: c.PreferServerCipherSuites,
SessionTicketsDisabled: c.SessionTicketsDisabled,
SessionTicketKey: c.SessionTicketKey,
ClientSessionCache: c.ClientSessionCache,
MinVersion: c.MinVersion,
MaxVersion: c.MaxVersion,
CurvePreferences: c.CurvePreferences,
DynamicRecordSizingDisabled: c.DynamicRecordSizingDisabled,
Renegotiation: c.Renegotiation,
}
}

View File

@ -1,56 +0,0 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.8
package http2
import (
"crypto/tls"
"io"
"net/http"
)
func cloneTLSConfig(c *tls.Config) *tls.Config {
c2 := c.Clone()
c2.GetClientCertificate = c.GetClientCertificate // golang.org/issue/19264
return c2
}
var _ http.Pusher = (*responseWriter)(nil)
// Push implements http.Pusher.
func (w *responseWriter) Push(target string, opts *http.PushOptions) error {
internalOpts := pushOptions{}
if opts != nil {
internalOpts.Method = opts.Method
internalOpts.Header = opts.Header
}
return w.push(target, internalOpts)
}
func configureServer18(h1 *http.Server, h2 *Server) error {
if h2.IdleTimeout == 0 {
if h1.IdleTimeout != 0 {
h2.IdleTimeout = h1.IdleTimeout
} else {
h2.IdleTimeout = h1.ReadTimeout
}
}
return nil
}
func shouldLogPanic(panicValue interface{}) bool {
return panicValue != nil && panicValue != http.ErrAbortHandler
}
func reqGetBody(req *http.Request) func() (io.ReadCloser, error) {
return req.GetBody
}
func reqBodyIsNoBody(body io.ReadCloser) bool {
return body == http.NoBody
}
func go18httpNoBody() io.ReadCloser { return http.NoBody } // for tests only

View File

@ -1,16 +0,0 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.9
package http2
import (
"net/http"
)
func configureServer19(s *http.Server, conf *Server) error {
s.RegisterOnShutdown(conf.state.startGracefulShutdown)
return nil
}

View File

@ -7,15 +7,21 @@ package http2
import ( import (
"net/http" "net/http"
"strings" "strings"
"sync"
) )
var ( var (
commonLowerHeader = map[string]string{} // Go-Canonical-Case -> lower-case commonBuildOnce sync.Once
commonCanonHeader = map[string]string{} // lower-case -> Go-Canonical-Case commonLowerHeader map[string]string // Go-Canonical-Case -> lower-case
commonCanonHeader map[string]string // lower-case -> Go-Canonical-Case
) )
func init() { func buildCommonHeaderMapsOnce() {
for _, v := range []string{ commonBuildOnce.Do(buildCommonHeaderMaps)
}
func buildCommonHeaderMaps() {
common := []string{
"accept", "accept",
"accept-charset", "accept-charset",
"accept-encoding", "accept-encoding",
@ -63,7 +69,10 @@ func init() {
"vary", "vary",
"via", "via",
"www-authenticate", "www-authenticate",
} { }
commonLowerHeader = make(map[string]string, len(common))
commonCanonHeader = make(map[string]string, len(common))
for _, v := range common {
chk := http.CanonicalHeaderKey(v) chk := http.CanonicalHeaderKey(v)
commonLowerHeader[chk] = v commonLowerHeader[chk] = v
commonCanonHeader[v] = chk commonCanonHeader[v] = chk
@ -71,6 +80,7 @@ func init() {
} }
func lowerHeader(v string) string { func lowerHeader(v string) string {
buildCommonHeaderMapsOnce()
if s, ok := commonLowerHeader[v]; ok { if s, ok := commonLowerHeader[v]; ok {
return s return s
} }

View File

@ -206,7 +206,7 @@ func appendVarInt(dst []byte, n byte, i uint64) []byte {
} }
// appendHpackString appends s, as encoded in "String Literal" // appendHpackString appends s, as encoded in "String Literal"
// representation, to dst and returns the the extended buffer. // representation, to dst and returns the extended buffer.
// //
// s will be encoded in Huffman codes only when it produces strictly // s will be encoded in Huffman codes only when it produces strictly
// shorter byte string. // shorter byte string.

View File

@ -92,6 +92,8 @@ type Decoder struct {
// saveBuf is previous data passed to Write which we weren't able // saveBuf is previous data passed to Write which we weren't able
// to fully parse before. Unlike buf, we own this data. // to fully parse before. Unlike buf, we own this data.
saveBuf bytes.Buffer saveBuf bytes.Buffer
firstField bool // processing the first field of the header block
} }
// NewDecoder returns a new decoder with the provided maximum dynamic // NewDecoder returns a new decoder with the provided maximum dynamic
@ -101,6 +103,7 @@ func NewDecoder(maxDynamicTableSize uint32, emitFunc func(f HeaderField)) *Decod
d := &Decoder{ d := &Decoder{
emit: emitFunc, emit: emitFunc,
emitEnabled: true, emitEnabled: true,
firstField: true,
} }
d.dynTab.table.init() d.dynTab.table.init()
d.dynTab.allowedMaxSize = maxDynamicTableSize d.dynTab.allowedMaxSize = maxDynamicTableSize
@ -226,11 +229,15 @@ func (d *Decoder) DecodeFull(p []byte) ([]HeaderField, error) {
return hf, nil return hf, nil
} }
// Close declares that the decoding is complete and resets the Decoder
// to be reused again for a new header block. If there is any remaining
// data in the decoder's buffer, Close returns an error.
func (d *Decoder) Close() error { func (d *Decoder) Close() error {
if d.saveBuf.Len() > 0 { if d.saveBuf.Len() > 0 {
d.saveBuf.Reset() d.saveBuf.Reset()
return DecodingError{errors.New("truncated headers")} return DecodingError{errors.New("truncated headers")}
} }
d.firstField = true
return nil return nil
} }
@ -266,6 +273,7 @@ func (d *Decoder) Write(p []byte) (n int, err error) {
d.saveBuf.Write(d.buf) d.saveBuf.Write(d.buf)
return len(p), nil return len(p), nil
} }
d.firstField = false
if err != nil { if err != nil {
break break
} }
@ -389,6 +397,12 @@ func (d *Decoder) callEmit(hf HeaderField) error {
// (same invariants and behavior as parseHeaderFieldRepr) // (same invariants and behavior as parseHeaderFieldRepr)
func (d *Decoder) parseDynamicTableSizeUpdate() error { func (d *Decoder) parseDynamicTableSizeUpdate() error {
// RFC 7541, sec 4.2: This dynamic table size update MUST occur at the
// beginning of the first header block following the change to the dynamic table size.
if !d.firstField && d.dynTab.size > 0 {
return DecodingError{errors.New("dynamic table size update MUST occur at the beginning of a header block")}
}
buf := d.buf buf := d.buf
size, buf, err := readVarInt(5, buf) size, buf, err := readVarInt(5, buf)
if err != nil { if err != nil {

View File

@ -47,6 +47,7 @@ var ErrInvalidHuffman = errors.New("hpack: invalid Huffman-encoded data")
// If maxLen is greater than 0, attempts to write more to buf than // If maxLen is greater than 0, attempts to write more to buf than
// maxLen bytes will return ErrStringLength. // maxLen bytes will return ErrStringLength.
func huffmanDecode(buf *bytes.Buffer, maxLen int, v []byte) error { func huffmanDecode(buf *bytes.Buffer, maxLen int, v []byte) error {
rootHuffmanNode := getRootHuffmanNode()
n := rootHuffmanNode n := rootHuffmanNode
// cur is the bit buffer that has not been fed into n. // cur is the bit buffer that has not been fed into n.
// cbits is the number of low order bits in cur that are valid. // cbits is the number of low order bits in cur that are valid.
@ -106,7 +107,7 @@ func huffmanDecode(buf *bytes.Buffer, maxLen int, v []byte) error {
type node struct { type node struct {
// children is non-nil for internal nodes // children is non-nil for internal nodes
children []*node children *[256]*node
// The following are only valid if children is nil: // The following are only valid if children is nil:
codeLen uint8 // number of bits that led to the output of sym codeLen uint8 // number of bits that led to the output of sym
@ -114,22 +115,31 @@ type node struct {
} }
func newInternalNode() *node { func newInternalNode() *node {
return &node{children: make([]*node, 256)} return &node{children: new([256]*node)}
} }
var rootHuffmanNode = newInternalNode() var (
buildRootOnce sync.Once
lazyRootHuffmanNode *node
)
func init() { func getRootHuffmanNode() *node {
buildRootOnce.Do(buildRootHuffmanNode)
return lazyRootHuffmanNode
}
func buildRootHuffmanNode() {
if len(huffmanCodes) != 256 { if len(huffmanCodes) != 256 {
panic("unexpected size") panic("unexpected size")
} }
lazyRootHuffmanNode = newInternalNode()
for i, code := range huffmanCodes { for i, code := range huffmanCodes {
addDecoderNode(byte(i), code, huffmanCodeLen[i]) addDecoderNode(byte(i), code, huffmanCodeLen[i])
} }
} }
func addDecoderNode(sym byte, code uint32, codeLen uint8) { func addDecoderNode(sym byte, code uint32, codeLen uint8) {
cur := rootHuffmanNode cur := lazyRootHuffmanNode
for codeLen > 8 { for codeLen > 8 {
codeLen -= 8 codeLen -= 8
i := uint8(code >> codeLen) i := uint8(code >> codeLen)

View File

@ -29,7 +29,7 @@ import (
"strings" "strings"
"sync" "sync"
"golang.org/x/net/lex/httplex" "golang.org/x/net/http/httpguts"
) )
var ( var (
@ -179,7 +179,7 @@ var (
) )
// validWireHeaderFieldName reports whether v is a valid header field // validWireHeaderFieldName reports whether v is a valid header field
// name (key). See httplex.ValidHeaderName for the base rules. // name (key). See httpguts.ValidHeaderName for the base rules.
// //
// Further, http2 says: // Further, http2 says:
// "Just as in HTTP/1.x, header field names are strings of ASCII // "Just as in HTTP/1.x, header field names are strings of ASCII
@ -191,7 +191,7 @@ func validWireHeaderFieldName(v string) bool {
return false return false
} }
for _, r := range v { for _, r := range v {
if !httplex.IsTokenRune(r) { if !httpguts.IsTokenRune(r) {
return false return false
} }
if 'A' <= r && r <= 'Z' { if 'A' <= r && r <= 'Z' {
@ -201,19 +201,12 @@ func validWireHeaderFieldName(v string) bool {
return true return true
} }
var httpCodeStringCommon = map[int]string{} // n -> strconv.Itoa(n)
func init() {
for i := 100; i <= 999; i++ {
if v := http.StatusText(i); v != "" {
httpCodeStringCommon[i] = strconv.Itoa(i)
}
}
}
func httpCodeString(code int) string { func httpCodeString(code int) string {
if s, ok := httpCodeStringCommon[code]; ok { switch code {
return s case 200:
return "200"
case 404:
return "404"
} }
return strconv.Itoa(code) return strconv.Itoa(code)
} }
@ -312,7 +305,7 @@ func mustUint31(v int32) uint32 {
} }
// bodyAllowedForStatus reports whether a given response status code // bodyAllowedForStatus reports whether a given response status code
// permits a body. See RFC 2616, section 4.4. // permits a body. See RFC 7230, section 3.3.
func bodyAllowedForStatus(status int) bool { func bodyAllowedForStatus(status int) bool {
switch { switch {
case status >= 100 && status <= 199: case status >= 100 && status <= 199:

20
vendor/golang.org/x/net/http2/not_go111.go generated vendored Normal file
View File

@ -0,0 +1,20 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !go1.11
package http2
import (
"net/http/httptrace"
"net/textproto"
)
func traceHasWroteHeaderField(trace *httptrace.ClientTrace) bool { return false }
func traceWroteHeaderField(trace *httptrace.ClientTrace, k, v string) {}
func traceGot1xxResponseFunc(trace *httptrace.ClientTrace) func(int, textproto.MIMEHeader) error {
return nil
}

View File

@ -1,21 +0,0 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !go1.6
package http2
import (
"net/http"
"time"
)
func configureTransport(t1 *http.Transport) (*Transport, error) {
return nil, errTransportVersion
}
func transportExpectContinueTimeout(t1 *http.Transport) time.Duration {
return 0
}

View File

@ -1,87 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !go1.7
package http2
import (
"crypto/tls"
"net"
"net/http"
"time"
)
type contextContext interface {
Done() <-chan struct{}
Err() error
}
type fakeContext struct{}
func (fakeContext) Done() <-chan struct{} { return nil }
func (fakeContext) Err() error { panic("should not be called") }
func reqContext(r *http.Request) fakeContext {
return fakeContext{}
}
func setResponseUncompressed(res *http.Response) {
// Nothing.
}
type clientTrace struct{}
func requestTrace(*http.Request) *clientTrace { return nil }
func traceGotConn(*http.Request, *ClientConn) {}
func traceFirstResponseByte(*clientTrace) {}
func traceWroteHeaders(*clientTrace) {}
func traceWroteRequest(*clientTrace, error) {}
func traceGot100Continue(trace *clientTrace) {}
func traceWait100Continue(trace *clientTrace) {}
func nop() {}
func serverConnBaseContext(c net.Conn, opts *ServeConnOpts) (ctx contextContext, cancel func()) {
return nil, nop
}
func contextWithCancel(ctx contextContext) (_ contextContext, cancel func()) {
return ctx, nop
}
func requestWithContext(req *http.Request, ctx contextContext) *http.Request {
return req
}
// temporary copy of Go 1.6's private tls.Config.clone:
func cloneTLSConfig(c *tls.Config) *tls.Config {
return &tls.Config{
Rand: c.Rand,
Time: c.Time,
Certificates: c.Certificates,
NameToCertificate: c.NameToCertificate,
GetCertificate: c.GetCertificate,
RootCAs: c.RootCAs,
NextProtos: c.NextProtos,
ServerName: c.ServerName,
ClientAuth: c.ClientAuth,
ClientCAs: c.ClientCAs,
InsecureSkipVerify: c.InsecureSkipVerify,
CipherSuites: c.CipherSuites,
PreferServerCipherSuites: c.PreferServerCipherSuites,
SessionTicketsDisabled: c.SessionTicketsDisabled,
SessionTicketKey: c.SessionTicketKey,
ClientSessionCache: c.ClientSessionCache,
MinVersion: c.MinVersion,
MaxVersion: c.MaxVersion,
CurvePreferences: c.CurvePreferences,
}
}
func (cc *ClientConn) Ping(ctx contextContext) error {
return cc.ping(ctx)
}
func (t *Transport) idleConnTimeout() time.Duration { return 0 }

View File

@ -1,29 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !go1.8
package http2
import (
"io"
"net/http"
)
func configureServer18(h1 *http.Server, h2 *Server) error {
// No IdleTimeout to sync prior to Go 1.8.
return nil
}
func shouldLogPanic(panicValue interface{}) bool {
return panicValue != nil
}
func reqGetBody(req *http.Request) func() (io.ReadCloser, error) {
return nil
}
func reqBodyIsNoBody(io.ReadCloser) bool { return false }
func go18httpNoBody() io.ReadCloser { return nil } // for tests only

View File

@ -28,6 +28,7 @@ package http2
import ( import (
"bufio" "bufio"
"bytes" "bytes"
"context"
"crypto/tls" "crypto/tls"
"errors" "errors"
"fmt" "fmt"
@ -46,6 +47,7 @@ import (
"sync" "sync"
"time" "time"
"golang.org/x/net/http/httpguts"
"golang.org/x/net/http2/hpack" "golang.org/x/net/http2/hpack"
) )
@ -208,12 +210,14 @@ func ConfigureServer(s *http.Server, conf *Server) error {
conf = new(Server) conf = new(Server)
} }
conf.state = &serverInternalState{activeConns: make(map[*serverConn]struct{})} conf.state = &serverInternalState{activeConns: make(map[*serverConn]struct{})}
if err := configureServer18(s, conf); err != nil { if h1, h2 := s, conf; h2.IdleTimeout == 0 {
return err if h1.IdleTimeout != 0 {
} h2.IdleTimeout = h1.IdleTimeout
if err := configureServer19(s, conf); err != nil { } else {
return err h2.IdleTimeout = h1.ReadTimeout
}
} }
s.RegisterOnShutdown(conf.state.startGracefulShutdown)
if s.TLSConfig == nil { if s.TLSConfig == nil {
s.TLSConfig = new(tls.Config) s.TLSConfig = new(tls.Config)
@ -406,7 +410,7 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
// addresses during development. // addresses during development.
// //
// TODO: optionally enforce? Or enforce at the time we receive // TODO: optionally enforce? Or enforce at the time we receive
// a new request, and verify the the ServerName matches the :authority? // a new request, and verify the ServerName matches the :authority?
// But that precludes proxy situations, perhaps. // But that precludes proxy situations, perhaps.
// //
// So for now, do nothing here again. // So for now, do nothing here again.
@ -434,6 +438,15 @@ func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
sc.serve() sc.serve()
} }
func serverConnBaseContext(c net.Conn, opts *ServeConnOpts) (ctx context.Context, cancel func()) {
ctx, cancel = context.WithCancel(context.Background())
ctx = context.WithValue(ctx, http.LocalAddrContextKey, c.LocalAddr())
if hs := opts.baseConfig(); hs != nil {
ctx = context.WithValue(ctx, http.ServerContextKey, hs)
}
return
}
func (sc *serverConn) rejectConn(err ErrCode, debug string) { func (sc *serverConn) rejectConn(err ErrCode, debug string) {
sc.vlogf("http2: server rejecting conn: %v, %s", err, debug) sc.vlogf("http2: server rejecting conn: %v, %s", err, debug)
// ignoring errors. hanging up anyway. // ignoring errors. hanging up anyway.
@ -449,7 +462,7 @@ type serverConn struct {
conn net.Conn conn net.Conn
bw *bufferedWriter // writing to conn bw *bufferedWriter // writing to conn
handler http.Handler handler http.Handler
baseCtx contextContext baseCtx context.Context
framer *Framer framer *Framer
doneServing chan struct{} // closed when serverConn.serve ends doneServing chan struct{} // closed when serverConn.serve ends
readFrameCh chan readFrameResult // written by serverConn.readFrames readFrameCh chan readFrameResult // written by serverConn.readFrames
@ -529,7 +542,7 @@ type stream struct {
id uint32 id uint32
body *pipe // non-nil if expecting DATA frames body *pipe // non-nil if expecting DATA frames
cw closeWaiter // closed wait stream transitions to closed state cw closeWaiter // closed wait stream transitions to closed state
ctx contextContext ctx context.Context
cancelCtx func() cancelCtx func()
// owned by serverConn's serve loop: // owned by serverConn's serve loop:
@ -662,6 +675,7 @@ func (sc *serverConn) condlogf(err error, format string, args ...interface{}) {
func (sc *serverConn) canonicalHeader(v string) string { func (sc *serverConn) canonicalHeader(v string) string {
sc.serveG.check() sc.serveG.check()
buildCommonHeaderMapsOnce()
cv, ok := commonCanonHeader[v] cv, ok := commonCanonHeader[v]
if ok { if ok {
return cv return cv
@ -1108,7 +1122,7 @@ func (sc *serverConn) startFrameWrite(wr FrameWriteRequest) {
// errHandlerPanicked is the error given to any callers blocked in a read from // errHandlerPanicked is the error given to any callers blocked in a read from
// Request.Body when the main goroutine panics. Since most handlers read in the // Request.Body when the main goroutine panics. Since most handlers read in the
// the main ServeHTTP goroutine, this will show up rarely. // main ServeHTTP goroutine, this will show up rarely.
var errHandlerPanicked = errors.New("http2: handler panicked") var errHandlerPanicked = errors.New("http2: handler panicked")
// wroteFrame is called on the serve goroutine with the result of // wroteFrame is called on the serve goroutine with the result of
@ -1486,6 +1500,12 @@ func (sc *serverConn) processSettings(f *SettingsFrame) error {
} }
return nil return nil
} }
if f.NumSettings() > 100 || f.HasDuplicates() {
// This isn't actually in the spec, but hang up on
// suspiciously large settings frames or those with
// duplicate entries.
return ConnectionError(ErrCodeProtocol)
}
if err := f.ForeachSetting(sc.processSetting); err != nil { if err := f.ForeachSetting(sc.processSetting); err != nil {
return err return err
} }
@ -1607,7 +1627,10 @@ func (sc *serverConn) processData(f *DataFrame) error {
// Sender sending more than they'd declared? // Sender sending more than they'd declared?
if st.declBodyBytes != -1 && st.bodyBytes+int64(len(data)) > st.declBodyBytes { if st.declBodyBytes != -1 && st.bodyBytes+int64(len(data)) > st.declBodyBytes {
st.body.CloseWithError(fmt.Errorf("sender tried to send more than declared Content-Length of %d bytes", st.declBodyBytes)) st.body.CloseWithError(fmt.Errorf("sender tried to send more than declared Content-Length of %d bytes", st.declBodyBytes))
return streamError(id, ErrCodeStreamClosed) // RFC 7540, sec 8.1.2.6: A request or response is also malformed if the
// value of a content-length header field does not equal the sum of the
// DATA frame payload lengths that form the body.
return streamError(id, ErrCodeProtocol)
} }
if f.Length > 0 { if f.Length > 0 {
// Check whether the client has flow control quota. // Check whether the client has flow control quota.
@ -1717,6 +1740,13 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
// processing this frame. // processing this frame.
return nil return nil
} }
// RFC 7540, sec 5.1: If an endpoint receives additional frames, other than
// WINDOW_UPDATE, PRIORITY, or RST_STREAM, for a stream that is in
// this state, it MUST respond with a stream error (Section 5.4.2) of
// type STREAM_CLOSED.
if st.state == stateHalfClosedRemote {
return streamError(id, ErrCodeStreamClosed)
}
return st.processTrailerHeaders(f) return st.processTrailerHeaders(f)
} }
@ -1817,7 +1847,7 @@ func (st *stream) processTrailerHeaders(f *MetaHeadersFrame) error {
if st.trailer != nil { if st.trailer != nil {
for _, hf := range f.RegularFields() { for _, hf := range f.RegularFields() {
key := sc.canonicalHeader(hf.Name) key := sc.canonicalHeader(hf.Name)
if !ValidTrailerHeader(key) { if !httpguts.ValidTrailerHeader(key) {
// TODO: send more details to the peer somehow. But http2 has // TODO: send more details to the peer somehow. But http2 has
// no way to send debug data at a stream level. Discuss with // no way to send debug data at a stream level. Discuss with
// HTTP folk. // HTTP folk.
@ -1858,7 +1888,7 @@ func (sc *serverConn) newStream(id, pusherID uint32, state streamState) *stream
panic("internal error: cannot create stream with id 0") panic("internal error: cannot create stream with id 0")
} }
ctx, cancelCtx := contextWithCancel(sc.baseCtx) ctx, cancelCtx := context.WithCancel(sc.baseCtx)
st := &stream{ st := &stream{
sc: sc, sc: sc,
id: id, id: id,
@ -2024,7 +2054,7 @@ func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp requestParam) (*r
Body: body, Body: body,
Trailer: trailer, Trailer: trailer,
} }
req = requestWithContext(req, st.ctx) req = req.WithContext(st.ctx)
rws := responseWriterStatePool.Get().(*responseWriterState) rws := responseWriterStatePool.Get().(*responseWriterState)
bwSave := rws.bw bwSave := rws.bw
@ -2052,7 +2082,7 @@ func (sc *serverConn) runHandler(rw *responseWriter, req *http.Request, handler
stream: rw.rws.stream, stream: rw.rws.stream,
}) })
// Same as net/http: // Same as net/http:
if shouldLogPanic(e) { if e != nil && e != http.ErrAbortHandler {
const size = 64 << 10 const size = 64 << 10
buf := make([]byte, size) buf := make([]byte, size)
buf = buf[:runtime.Stack(buf, false)] buf = buf[:runtime.Stack(buf, false)]
@ -2284,8 +2314,8 @@ func (rws *responseWriterState) hasTrailers() bool { return len(rws.trailers) !=
// written in the trailers at the end of the response. // written in the trailers at the end of the response.
func (rws *responseWriterState) declareTrailer(k string) { func (rws *responseWriterState) declareTrailer(k string) {
k = http.CanonicalHeaderKey(k) k = http.CanonicalHeaderKey(k)
if !ValidTrailerHeader(k) { if !httpguts.ValidTrailerHeader(k) {
// Forbidden by RFC 2616 14.40. // Forbidden by RFC 7230, section 4.1.2.
rws.conn.logf("ignoring invalid trailer %q", k) rws.conn.logf("ignoring invalid trailer %q", k)
return return
} }
@ -2335,6 +2365,19 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
foreachHeaderElement(v, rws.declareTrailer) foreachHeaderElement(v, rws.declareTrailer)
} }
// "Connection" headers aren't allowed in HTTP/2 (RFC 7540, 8.1.2.2),
// but respect "Connection" == "close" to mean sending a GOAWAY and tearing
// down the TCP connection when idle, like we do for HTTP/1.
// TODO: remove more Connection-specific header fields here, in addition
// to "Connection".
if _, ok := rws.snapHeader["Connection"]; ok {
v := rws.snapHeader.Get("Connection")
delete(rws.snapHeader, "Connection")
if v == "close" {
rws.conn.startGracefulShutdown()
}
}
endStream := (rws.handlerDone && !rws.hasTrailers() && len(p) == 0) || isHeadResp endStream := (rws.handlerDone && !rws.hasTrailers() && len(p) == 0) || isHeadResp
err = rws.conn.writeHeaders(rws.stream, &writeResHeaders{ err = rws.conn.writeHeaders(rws.stream, &writeResHeaders{
streamID: rws.stream.id, streamID: rws.stream.id,
@ -2406,7 +2449,7 @@ const TrailerPrefix = "Trailer:"
// after the header has already been flushed. Because the Go // after the header has already been flushed. Because the Go
// ResponseWriter interface has no way to set Trailers (only the // ResponseWriter interface has no way to set Trailers (only the
// Header), and because we didn't want to expand the ResponseWriter // Header), and because we didn't want to expand the ResponseWriter
// interface, and because nobody used trailers, and because RFC 2616 // interface, and because nobody used trailers, and because RFC 7230
// says you SHOULD (but not must) predeclare any trailers in the // says you SHOULD (but not must) predeclare any trailers in the
// header, the official ResponseWriter rules said trailers in Go must // header, the official ResponseWriter rules said trailers in Go must
// be predeclared, and then we reuse the same ResponseWriter.Header() // be predeclared, and then we reuse the same ResponseWriter.Header()
@ -2601,14 +2644,9 @@ var (
ErrPushLimitReached = errors.New("http2: push would exceed peer's SETTINGS_MAX_CONCURRENT_STREAMS") ErrPushLimitReached = errors.New("http2: push would exceed peer's SETTINGS_MAX_CONCURRENT_STREAMS")
) )
// pushOptions is the internal version of http.PushOptions, which we var _ http.Pusher = (*responseWriter)(nil)
// cannot include here because it's only defined in Go 1.8 and later.
type pushOptions struct {
Method string
Header http.Header
}
func (w *responseWriter) push(target string, opts pushOptions) error { func (w *responseWriter) Push(target string, opts *http.PushOptions) error {
st := w.rws.stream st := w.rws.stream
sc := st.sc sc := st.sc
sc.serveG.checkNotOn() sc.serveG.checkNotOn()
@ -2619,6 +2657,10 @@ func (w *responseWriter) push(target string, opts pushOptions) error {
return ErrRecursivePush return ErrRecursivePush
} }
if opts == nil {
opts = new(http.PushOptions)
}
// Default options. // Default options.
if opts.Method == "" { if opts.Method == "" {
opts.Method = "GET" opts.Method = "GET"
@ -2790,7 +2832,7 @@ func (sc *serverConn) startPush(msg *startPushRequest) {
} }
// foreachHeaderElement splits v according to the "#rule" construction // foreachHeaderElement splits v according to the "#rule" construction
// in RFC 2616 section 2.1 and calls fn for each non-empty element. // in RFC 7230 section 7 and calls fn for each non-empty element.
func foreachHeaderElement(v string, fn func(string)) { func foreachHeaderElement(v string, fn func(string)) {
v = textproto.TrimString(v) v = textproto.TrimString(v)
if v == "" { if v == "" {
@ -2838,41 +2880,6 @@ func new400Handler(err error) http.HandlerFunc {
} }
} }
// ValidTrailerHeader reports whether name is a valid header field name to appear
// in trailers.
// See: http://tools.ietf.org/html/rfc7230#section-4.1.2
func ValidTrailerHeader(name string) bool {
name = http.CanonicalHeaderKey(name)
if strings.HasPrefix(name, "If-") || badTrailer[name] {
return false
}
return true
}
var badTrailer = map[string]bool{
"Authorization": true,
"Cache-Control": true,
"Connection": true,
"Content-Encoding": true,
"Content-Length": true,
"Content-Range": true,
"Content-Type": true,
"Expect": true,
"Host": true,
"Keep-Alive": true,
"Max-Forwards": true,
"Pragma": true,
"Proxy-Authenticate": true,
"Proxy-Authorization": true,
"Proxy-Connection": true,
"Range": true,
"Realm": true,
"Te": true,
"Trailer": true,
"Transfer-Encoding": true,
"Www-Authenticate": true,
}
// h1ServerKeepAlivesDisabled reports whether hs has its keep-alives // h1ServerKeepAlivesDisabled reports whether hs has its keep-alives
// disabled. See comments on h1ServerShutdownChan above for why // disabled. See comments on h1ServerShutdownChan above for why
// the code is written this way. // the code is written this way.

View File

@ -10,6 +10,7 @@ import (
"bufio" "bufio"
"bytes" "bytes"
"compress/gzip" "compress/gzip"
"context"
"crypto/rand" "crypto/rand"
"crypto/tls" "crypto/tls"
"errors" "errors"
@ -21,15 +22,17 @@ import (
mathrand "math/rand" mathrand "math/rand"
"net" "net"
"net/http" "net/http"
"net/http/httptrace"
"net/textproto"
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
"time" "time"
"golang.org/x/net/http/httpguts"
"golang.org/x/net/http2/hpack" "golang.org/x/net/http2/hpack"
"golang.org/x/net/idna" "golang.org/x/net/idna"
"golang.org/x/net/lex/httplex"
) )
const ( const (
@ -94,6 +97,16 @@ type Transport struct {
// to mean no limit. // to mean no limit.
MaxHeaderListSize uint32 MaxHeaderListSize uint32
// StrictMaxConcurrentStreams controls whether the server's
// SETTINGS_MAX_CONCURRENT_STREAMS should be respected
// globally. If false, new TCP connections are created to the
// server as needed to keep each under the per-connection
// SETTINGS_MAX_CONCURRENT_STREAMS limit. If true, the
// server's SETTINGS_MAX_CONCURRENT_STREAMS is interpreted as
// a global limit and callers of RoundTrip block when needed,
// waiting for their turn.
StrictMaxConcurrentStreams bool
// t1, if non-nil, is the standard library Transport using // t1, if non-nil, is the standard library Transport using
// this transport. Its settings are used (but not its // this transport. Its settings are used (but not its
// RoundTrip method, etc). // RoundTrip method, etc).
@ -117,16 +130,56 @@ func (t *Transport) disableCompression() bool {
return t.DisableCompression || (t.t1 != nil && t.t1.DisableCompression) return t.DisableCompression || (t.t1 != nil && t.t1.DisableCompression)
} }
var errTransportVersion = errors.New("http2: ConfigureTransport is only supported starting at Go 1.6")
// ConfigureTransport configures a net/http HTTP/1 Transport to use HTTP/2. // ConfigureTransport configures a net/http HTTP/1 Transport to use HTTP/2.
// It requires Go 1.6 or later and returns an error if the net/http package is too old // It returns an error if t1 has already been HTTP/2-enabled.
// or if t1 has already been HTTP/2-enabled.
func ConfigureTransport(t1 *http.Transport) error { func ConfigureTransport(t1 *http.Transport) error {
_, err := configureTransport(t1) // in configure_transport.go (go1.6) or not_go16.go _, err := configureTransport(t1)
return err return err
} }
func configureTransport(t1 *http.Transport) (*Transport, error) {
connPool := new(clientConnPool)
t2 := &Transport{
ConnPool: noDialClientConnPool{connPool},
t1: t1,
}
connPool.t = t2
if err := registerHTTPSProtocol(t1, noDialH2RoundTripper{t2}); err != nil {
return nil, err
}
if t1.TLSClientConfig == nil {
t1.TLSClientConfig = new(tls.Config)
}
if !strSliceContains(t1.TLSClientConfig.NextProtos, "h2") {
t1.TLSClientConfig.NextProtos = append([]string{"h2"}, t1.TLSClientConfig.NextProtos...)
}
if !strSliceContains(t1.TLSClientConfig.NextProtos, "http/1.1") {
t1.TLSClientConfig.NextProtos = append(t1.TLSClientConfig.NextProtos, "http/1.1")
}
upgradeFn := func(authority string, c *tls.Conn) http.RoundTripper {
addr := authorityAddr("https", authority)
if used, err := connPool.addConnIfNeeded(addr, t2, c); err != nil {
go c.Close()
return erringRoundTripper{err}
} else if !used {
// Turns out we don't need this c.
// For example, two goroutines made requests to the same host
// at the same time, both kicking off TCP dials. (since protocol
// was unknown)
go c.Close()
}
return t2
}
if m := t1.TLSNextProto; len(m) == 0 {
t1.TLSNextProto = map[string]func(string, *tls.Conn) http.RoundTripper{
"h2": upgradeFn,
}
} else {
m["h2"] = upgradeFn
}
return t2, nil
}
func (t *Transport) connPool() ClientConnPool { func (t *Transport) connPool() ClientConnPool {
t.connPoolOnce.Do(t.initConnPool) t.connPoolOnce.Do(t.initConnPool)
return t.connPoolOrDef return t.connPoolOrDef
@ -159,6 +212,7 @@ type ClientConn struct {
cond *sync.Cond // hold mu; broadcast on flow/closed changes cond *sync.Cond // hold mu; broadcast on flow/closed changes
flow flow // our conn-level flow control quota (cs.flow is per stream) flow flow // our conn-level flow control quota (cs.flow is per stream)
inflow flow // peer's conn-level flow control inflow flow // peer's conn-level flow control
closing bool
closed bool closed bool
wantSettingsAck bool // we sent a SETTINGS frame and haven't heard back wantSettingsAck bool // we sent a SETTINGS frame and haven't heard back
goAway *GoAwayFrame // if non-nil, the GoAwayFrame we received goAway *GoAwayFrame // if non-nil, the GoAwayFrame we received
@ -190,7 +244,7 @@ type ClientConn struct {
type clientStream struct { type clientStream struct {
cc *ClientConn cc *ClientConn
req *http.Request req *http.Request
trace *clientTrace // or nil trace *httptrace.ClientTrace // or nil
ID uint32 ID uint32
resc chan resAndError resc chan resAndError
bufPipe pipe // buffered pipe with the flow-controlled response payload bufPipe pipe // buffered pipe with the flow-controlled response payload
@ -211,9 +265,10 @@ type clientStream struct {
done chan struct{} // closed when stream remove from cc.streams map; close calls guarded by cc.mu done chan struct{} // closed when stream remove from cc.streams map; close calls guarded by cc.mu
// owned by clientConnReadLoop: // owned by clientConnReadLoop:
firstByte bool // got the first response byte firstByte bool // got the first response byte
pastHeaders bool // got first MetaHeadersFrame (actual headers) pastHeaders bool // got first MetaHeadersFrame (actual headers)
pastTrailers bool // got optional second MetaHeadersFrame (trailers) pastTrailers bool // got optional second MetaHeadersFrame (trailers)
num1xx uint8 // number of 1xx responses seen
trailer http.Header // accumulated trailers trailer http.Header // accumulated trailers
resTrailer *http.Header // client's Response.Trailer resTrailer *http.Header // client's Response.Trailer
@ -223,7 +278,7 @@ type clientStream struct {
// channel to be signaled. A non-nil error is returned only if the request was // channel to be signaled. A non-nil error is returned only if the request was
// canceled. // canceled.
func awaitRequestCancel(req *http.Request, done <-chan struct{}) error { func awaitRequestCancel(req *http.Request, done <-chan struct{}) error {
ctx := reqContext(req) ctx := req.Context()
if req.Cancel == nil && ctx.Done() == nil { if req.Cancel == nil && ctx.Done() == nil {
return nil return nil
} }
@ -237,6 +292,17 @@ func awaitRequestCancel(req *http.Request, done <-chan struct{}) error {
} }
} }
var got1xxFuncForTests func(int, textproto.MIMEHeader) error
// get1xxTraceFunc returns the value of request's httptrace.ClientTrace.Got1xxResponse func,
// if any. It returns nil if not set or if the Go version is too old.
func (cs *clientStream) get1xxTraceFunc() func(int, textproto.MIMEHeader) error {
if fn := got1xxFuncForTests; fn != nil {
return fn
}
return traceGot1xxResponseFunc(cs.trace)
}
// awaitRequestCancel waits for the user to cancel a request, its context to // awaitRequestCancel waits for the user to cancel a request, its context to
// expire, or for the request to be done (any way it might be removed from the // expire, or for the request to be done (any way it might be removed from the
// cc.streams map: peer reset, successful completion, TCP connection breakage, // cc.streams map: peer reset, successful completion, TCP connection breakage,
@ -387,8 +453,8 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Res
select { select {
case <-time.After(time.Second * time.Duration(backoff)): case <-time.After(time.Second * time.Duration(backoff)):
continue continue
case <-reqContext(req).Done(): case <-req.Context().Done():
return nil, reqContext(req).Err() return nil, req.Context().Err()
} }
} }
} }
@ -423,27 +489,35 @@ func shouldRetryRequest(req *http.Request, err error, afterBodyWrite bool) (*htt
if !canRetryError(err) { if !canRetryError(err) {
return nil, err return nil, err
} }
// If the Body is nil (or http.NoBody), it's safe to reuse
// this request and its Body.
if req.Body == nil || req.Body == http.NoBody {
return req, nil
}
// If the request body can be reset back to its original
// state via the optional req.GetBody, do that.
if req.GetBody != nil {
// TODO: consider a req.Body.Close here? or audit that all caller paths do?
body, err := req.GetBody()
if err != nil {
return nil, err
}
newReq := *req
newReq.Body = body
return &newReq, nil
}
// The Request.Body can't reset back to the beginning, but we
// don't seem to have started to read from it yet, so reuse
// the request directly. The "afterBodyWrite" means the
// bodyWrite process has started, which becomes true before
// the first Read.
if !afterBodyWrite { if !afterBodyWrite {
return req, nil return req, nil
} }
// If the Body is nil (or http.NoBody), it's safe to reuse
// this request and its Body. return nil, fmt.Errorf("http2: Transport: cannot retry err [%v] after Request.Body was written; define Request.GetBody to avoid this error", err)
if req.Body == nil || reqBodyIsNoBody(req.Body) {
return req, nil
}
// Otherwise we depend on the Request having its GetBody
// func defined.
getBody := reqGetBody(req) // Go 1.8: getBody = req.GetBody
if getBody == nil {
return nil, fmt.Errorf("http2: Transport: cannot retry err [%v] after Request.Body was written; define Request.GetBody to avoid this error", err)
}
body, err := getBody()
if err != nil {
return nil, err
}
newReq := *req
newReq.Body = body
return &newReq, nil
} }
func canRetryError(err error) bool { func canRetryError(err error) bool {
@ -471,7 +545,7 @@ func (t *Transport) dialClientConn(addr string, singleUse bool) (*ClientConn, er
func (t *Transport) newTLSConfig(host string) *tls.Config { func (t *Transport) newTLSConfig(host string) *tls.Config {
cfg := new(tls.Config) cfg := new(tls.Config)
if t.TLSClientConfig != nil { if t.TLSClientConfig != nil {
*cfg = *cloneTLSConfig(t.TLSClientConfig) *cfg = *t.TLSClientConfig.Clone()
} }
if !strSliceContains(cfg.NextProtos, NextProtoTLS) { if !strSliceContains(cfg.NextProtos, NextProtoTLS) {
cfg.NextProtos = append([]string{NextProtoTLS}, cfg.NextProtos...) cfg.NextProtos = append([]string{NextProtoTLS}, cfg.NextProtos...)
@ -522,7 +596,7 @@ func (t *Transport) expectContinueTimeout() time.Duration {
if t.t1 == nil { if t.t1 == nil {
return 0 return 0
} }
return transportExpectContinueTimeout(t.t1) return t.t1.ExpectContinueTimeout
} }
func (t *Transport) NewClientConn(c net.Conn) (*ClientConn, error) { func (t *Transport) NewClientConn(c net.Conn) (*ClientConn, error) {
@ -567,6 +641,10 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, erro
// henc in response to SETTINGS frames? // henc in response to SETTINGS frames?
cc.henc = hpack.NewEncoder(&cc.hbuf) cc.henc = hpack.NewEncoder(&cc.hbuf)
if t.AllowHTTP {
cc.nextStreamID = 3
}
if cs, ok := c.(connectionStater); ok { if cs, ok := c.(connectionStater); ok {
state := cs.ConnectionState() state := cs.ConnectionState()
cc.tlsState = &state cc.tlsState = &state
@ -626,12 +704,43 @@ func (cc *ClientConn) CanTakeNewRequest() bool {
return cc.canTakeNewRequestLocked() return cc.canTakeNewRequestLocked()
} }
func (cc *ClientConn) canTakeNewRequestLocked() bool { // clientConnIdleState describes the suitability of a client
// connection to initiate a new RoundTrip request.
type clientConnIdleState struct {
canTakeNewRequest bool
freshConn bool // whether it's unused by any previous request
}
func (cc *ClientConn) idleState() clientConnIdleState {
cc.mu.Lock()
defer cc.mu.Unlock()
return cc.idleStateLocked()
}
func (cc *ClientConn) idleStateLocked() (st clientConnIdleState) {
if cc.singleUse && cc.nextStreamID > 1 { if cc.singleUse && cc.nextStreamID > 1 {
return false return
} }
return cc.goAway == nil && !cc.closed && var maxConcurrentOkay bool
int64(cc.nextStreamID)+int64(cc.pendingRequests) < math.MaxInt32 if cc.t.StrictMaxConcurrentStreams {
// We'll tell the caller we can take a new request to
// prevent the caller from dialing a new TCP
// connection, but then we'll block later before
// writing it.
maxConcurrentOkay = true
} else {
maxConcurrentOkay = int64(len(cc.streams)+1) < int64(cc.maxConcurrentStreams)
}
st.canTakeNewRequest = cc.goAway == nil && !cc.closed && !cc.closing && maxConcurrentOkay &&
int64(cc.nextStreamID)+2*int64(cc.pendingRequests) < math.MaxInt32
st.freshConn = cc.nextStreamID == 1 && st.canTakeNewRequest
return
}
func (cc *ClientConn) canTakeNewRequestLocked() bool {
st := cc.idleStateLocked()
return st.canTakeNewRequest
} }
// onIdleTimeout is called from a time.AfterFunc goroutine. It will // onIdleTimeout is called from a time.AfterFunc goroutine. It will
@ -661,6 +770,87 @@ func (cc *ClientConn) closeIfIdle() {
cc.tconn.Close() cc.tconn.Close()
} }
var shutdownEnterWaitStateHook = func() {}
// Shutdown gracefully close the client connection, waiting for running streams to complete.
func (cc *ClientConn) Shutdown(ctx context.Context) error {
if err := cc.sendGoAway(); err != nil {
return err
}
// Wait for all in-flight streams to complete or connection to close
done := make(chan error, 1)
cancelled := false // guarded by cc.mu
go func() {
cc.mu.Lock()
defer cc.mu.Unlock()
for {
if len(cc.streams) == 0 || cc.closed {
cc.closed = true
done <- cc.tconn.Close()
break
}
if cancelled {
break
}
cc.cond.Wait()
}
}()
shutdownEnterWaitStateHook()
select {
case err := <-done:
return err
case <-ctx.Done():
cc.mu.Lock()
// Free the goroutine above
cancelled = true
cc.cond.Broadcast()
cc.mu.Unlock()
return ctx.Err()
}
}
func (cc *ClientConn) sendGoAway() error {
cc.mu.Lock()
defer cc.mu.Unlock()
cc.wmu.Lock()
defer cc.wmu.Unlock()
if cc.closing {
// GOAWAY sent already
return nil
}
// Send a graceful shutdown frame to server
maxStreamID := cc.nextStreamID
if err := cc.fr.WriteGoAway(maxStreamID, ErrCodeNo, nil); err != nil {
return err
}
if err := cc.bw.Flush(); err != nil {
return err
}
// Prevent new requests
cc.closing = true
return nil
}
// Close closes the client connection immediately.
//
// In-flight requests are interrupted. For a graceful shutdown, use Shutdown instead.
func (cc *ClientConn) Close() error {
cc.mu.Lock()
defer cc.cond.Broadcast()
defer cc.mu.Unlock()
err := errors.New("http2: client connection force closed via ClientConn.Close")
for id, cs := range cc.streams {
select {
case cs.resc <- resAndError{err: err}:
default:
}
cs.bufPipe.CloseWithError(err)
delete(cc.streams, id)
}
cc.closed = true
return cc.tconn.Close()
}
const maxAllocFrameSize = 512 << 10 const maxAllocFrameSize = 512 << 10
// frameBuffer returns a scratch buffer suitable for writing DATA frames. // frameBuffer returns a scratch buffer suitable for writing DATA frames.
@ -743,7 +933,7 @@ func checkConnHeaders(req *http.Request) error {
if vv := req.Header["Transfer-Encoding"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && vv[0] != "chunked") { if vv := req.Header["Transfer-Encoding"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && vv[0] != "chunked") {
return fmt.Errorf("http2: invalid Transfer-Encoding request header: %q", vv) return fmt.Errorf("http2: invalid Transfer-Encoding request header: %q", vv)
} }
if vv := req.Header["Connection"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && vv[0] != "close" && vv[0] != "keep-alive") { if vv := req.Header["Connection"]; len(vv) > 0 && (len(vv) > 1 || vv[0] != "" && !strings.EqualFold(vv[0], "close") && !strings.EqualFold(vv[0], "keep-alive")) {
return fmt.Errorf("http2: invalid Connection request header: %q", vv) return fmt.Errorf("http2: invalid Connection request header: %q", vv)
} }
return nil return nil
@ -753,7 +943,7 @@ func checkConnHeaders(req *http.Request) error {
// req.ContentLength, where 0 actually means zero (not unknown) and -1 // req.ContentLength, where 0 actually means zero (not unknown) and -1
// means unknown. // means unknown.
func actualContentLength(req *http.Request) int64 { func actualContentLength(req *http.Request) int64 {
if req.Body == nil || reqBodyIsNoBody(req.Body) { if req.Body == nil || req.Body == http.NoBody {
return 0 return 0
} }
if req.ContentLength != 0 { if req.ContentLength != 0 {
@ -823,7 +1013,7 @@ func (cc *ClientConn) roundTrip(req *http.Request) (res *http.Response, gotErrAf
cs := cc.newStream() cs := cc.newStream()
cs.req = req cs.req = req
cs.trace = requestTrace(req) cs.trace = httptrace.ContextClientTrace(req.Context())
cs.requestedGzip = requestedGzip cs.requestedGzip = requestedGzip
bodyWriter := cc.t.getBodyWriterState(cs, body) bodyWriter := cc.t.getBodyWriterState(cs, body)
cs.on100 = bodyWriter.on100 cs.on100 = bodyWriter.on100
@ -861,7 +1051,7 @@ func (cc *ClientConn) roundTrip(req *http.Request) (res *http.Response, gotErrAf
readLoopResCh := cs.resc readLoopResCh := cs.resc
bodyWritten := false bodyWritten := false
ctx := reqContext(req) ctx := req.Context()
handleReadLoopResponse := func(re resAndError) (*http.Response, bool, error) { handleReadLoopResponse := func(re resAndError) (*http.Response, bool, error) {
res := re.res res := re.res
@ -931,6 +1121,7 @@ func (cc *ClientConn) roundTrip(req *http.Request) (res *http.Response, gotErrAf
default: default:
} }
if err != nil { if err != nil {
cc.forgetStreamID(cs.ID)
return nil, cs.getStartedWrite(), err return nil, cs.getStartedWrite(), err
} }
bodyWritten = true bodyWritten = true
@ -951,6 +1142,9 @@ func (cc *ClientConn) awaitOpenSlotForRequest(req *http.Request) error {
for { for {
cc.lastActive = time.Now() cc.lastActive = time.Now()
if cc.closed || !cc.canTakeNewRequestLocked() { if cc.closed || !cc.canTakeNewRequestLocked() {
if waitingForConn != nil {
close(waitingForConn)
}
return errClientConnUnusable return errClientConnUnusable
} }
if int64(len(cc.streams))+1 <= int64(cc.maxConcurrentStreams) { if int64(len(cc.streams))+1 <= int64(cc.maxConcurrentStreams) {
@ -1049,6 +1243,7 @@ func (cs *clientStream) writeRequestBody(body io.Reader, bodyCloser io.Closer) (
sawEOF = true sawEOF = true
err = nil err = nil
} else if err != nil { } else if err != nil {
cc.writeStreamReset(cs.ID, ErrCodeCancel, err)
return err return err
} }
@ -1174,7 +1369,7 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail
if host == "" { if host == "" {
host = req.URL.Host host = req.URL.Host
} }
host, err := httplex.PunycodeHostPort(host) host, err := httpguts.PunycodeHostPort(host)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -1199,11 +1394,11 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail
// potentially pollute our hpack state. (We want to be able to // potentially pollute our hpack state. (We want to be able to
// continue to reuse the hpack encoder for future requests) // continue to reuse the hpack encoder for future requests)
for k, vv := range req.Header { for k, vv := range req.Header {
if !httplex.ValidHeaderFieldName(k) { if !httpguts.ValidHeaderFieldName(k) {
return nil, fmt.Errorf("invalid HTTP header name %q", k) return nil, fmt.Errorf("invalid HTTP header name %q", k)
} }
for _, v := range vv { for _, v := range vv {
if !httplex.ValidHeaderFieldValue(v) { if !httpguts.ValidHeaderFieldValue(v) {
return nil, fmt.Errorf("invalid HTTP header value %q for header %q", v, k) return nil, fmt.Errorf("invalid HTTP header value %q for header %q", v, k)
} }
} }
@ -1284,9 +1479,16 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail
return nil, errRequestHeaderListSize return nil, errRequestHeaderListSize
} }
trace := httptrace.ContextClientTrace(req.Context())
traceHeaders := traceHasWroteHeaderField(trace)
// Header list size is ok. Write the headers. // Header list size is ok. Write the headers.
enumerateHeaders(func(name, value string) { enumerateHeaders(func(name, value string) {
cc.writeHeader(strings.ToLower(name), value) name = strings.ToLower(name)
cc.writeHeader(name, value)
if traceHeaders {
traceWroteHeaderField(trace, name, value)
}
}) })
return cc.hbuf.Bytes(), nil return cc.hbuf.Bytes(), nil
@ -1608,8 +1810,7 @@ func (rl *clientConnReadLoop) processHeaders(f *MetaHeadersFrame) error {
// is the detail. // is the detail.
// //
// As a special case, handleResponse may return (nil, nil) to skip the // As a special case, handleResponse may return (nil, nil) to skip the
// frame (currently only used for 100 expect continue). This special // frame (currently only used for 1xx responses).
// case is going away after Issue 13851 is fixed.
func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFrame) (*http.Response, error) { func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFrame) (*http.Response, error) {
if f.Truncated { if f.Truncated {
return nil, errResponseHeaderListSize return nil, errResponseHeaderListSize
@ -1624,15 +1825,6 @@ func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFra
return nil, errors.New("malformed response from server: malformed non-numeric status pseudo header") return nil, errors.New("malformed response from server: malformed non-numeric status pseudo header")
} }
if statusCode == 100 {
traceGot100Continue(cs.trace)
if cs.on100 != nil {
cs.on100() // forces any write delay timer to fire
}
cs.pastHeaders = false // do it all again
return nil, nil
}
header := make(http.Header) header := make(http.Header)
res := &http.Response{ res := &http.Response{
Proto: "HTTP/2.0", Proto: "HTTP/2.0",
@ -1657,6 +1849,27 @@ func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFra
} }
} }
if statusCode >= 100 && statusCode <= 199 {
cs.num1xx++
const max1xxResponses = 5 // arbitrary bound on number of informational responses, same as net/http
if cs.num1xx > max1xxResponses {
return nil, errors.New("http2: too many 1xx informational responses")
}
if fn := cs.get1xxTraceFunc(); fn != nil {
if err := fn(statusCode, textproto.MIMEHeader(header)); err != nil {
return nil, err
}
}
if statusCode == 100 {
traceGot100Continue(cs.trace)
if cs.on100 != nil {
cs.on100() // forces any write delay timer to fire
}
}
cs.pastHeaders = false // do it all again
return nil, nil
}
streamEnded := f.StreamEnded() streamEnded := f.StreamEnded()
isHead := cs.req.Method == "HEAD" isHead := cs.req.Method == "HEAD"
if !streamEnded || isHead { if !streamEnded || isHead {
@ -1689,7 +1902,7 @@ func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFra
res.Header.Del("Content-Length") res.Header.Del("Content-Length")
res.ContentLength = -1 res.ContentLength = -1
res.Body = &gzipReader{body: res.Body} res.Body = &gzipReader{body: res.Body}
setResponseUncompressed(res) res.Uncompressed = true
} }
return res, nil return res, nil
} }
@ -2066,8 +2279,7 @@ func (rl *clientConnReadLoop) processResetStream(f *RSTStreamFrame) error {
} }
// Ping sends a PING frame to the server and waits for the ack. // Ping sends a PING frame to the server and waits for the ack.
// Public implementation is in go17.go and not_go17.go func (cc *ClientConn) Ping(ctx context.Context) error {
func (cc *ClientConn) ping(ctx contextContext) error {
c := make(chan struct{}) c := make(chan struct{})
// Generate a random payload // Generate a random payload
var p [8]byte var p [8]byte
@ -2244,7 +2456,7 @@ func (t *Transport) getBodyWriterState(cs *clientStream, body io.Reader) (s body
} }
s.delay = t.expectContinueTimeout() s.delay = t.expectContinueTimeout()
if s.delay == 0 || if s.delay == 0 ||
!httplex.HeaderValuesContainsToken( !httpguts.HeaderValuesContainsToken(
cs.req.Header["Expect"], cs.req.Header["Expect"],
"100-continue") { "100-continue") {
return return
@ -2299,5 +2511,93 @@ func (s bodyWriterState) scheduleBodyWrite() {
// isConnectionCloseRequest reports whether req should use its own // isConnectionCloseRequest reports whether req should use its own
// connection for a single request and then close the connection. // connection for a single request and then close the connection.
func isConnectionCloseRequest(req *http.Request) bool { func isConnectionCloseRequest(req *http.Request) bool {
return req.Close || httplex.HeaderValuesContainsToken(req.Header["Connection"], "close") return req.Close || httpguts.HeaderValuesContainsToken(req.Header["Connection"], "close")
}
// registerHTTPSProtocol calls Transport.RegisterProtocol but
// converting panics into errors.
func registerHTTPSProtocol(t *http.Transport, rt noDialH2RoundTripper) (err error) {
defer func() {
if e := recover(); e != nil {
err = fmt.Errorf("%v", e)
}
}()
t.RegisterProtocol("https", rt)
return nil
}
// noDialH2RoundTripper is a RoundTripper which only tries to complete the request
// if there's already has a cached connection to the host.
// (The field is exported so it can be accessed via reflect from net/http; tested
// by TestNoDialH2RoundTripperType)
type noDialH2RoundTripper struct{ *Transport }
func (rt noDialH2RoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
res, err := rt.Transport.RoundTrip(req)
if isNoCachedConnError(err) {
return nil, http.ErrSkipAltProtocol
}
return res, err
}
func (t *Transport) idleConnTimeout() time.Duration {
if t.t1 != nil {
return t.t1.IdleConnTimeout
}
return 0
}
func traceGetConn(req *http.Request, hostPort string) {
trace := httptrace.ContextClientTrace(req.Context())
if trace == nil || trace.GetConn == nil {
return
}
trace.GetConn(hostPort)
}
func traceGotConn(req *http.Request, cc *ClientConn) {
trace := httptrace.ContextClientTrace(req.Context())
if trace == nil || trace.GotConn == nil {
return
}
ci := httptrace.GotConnInfo{Conn: cc.tconn}
cc.mu.Lock()
ci.Reused = cc.nextStreamID > 1
ci.WasIdle = len(cc.streams) == 0 && ci.Reused
if ci.WasIdle && !cc.lastActive.IsZero() {
ci.IdleTime = time.Now().Sub(cc.lastActive)
}
cc.mu.Unlock()
trace.GotConn(ci)
}
func traceWroteHeaders(trace *httptrace.ClientTrace) {
if trace != nil && trace.WroteHeaders != nil {
trace.WroteHeaders()
}
}
func traceGot100Continue(trace *httptrace.ClientTrace) {
if trace != nil && trace.Got100Continue != nil {
trace.Got100Continue()
}
}
func traceWait100Continue(trace *httptrace.ClientTrace) {
if trace != nil && trace.Wait100Continue != nil {
trace.Wait100Continue()
}
}
func traceWroteRequest(trace *httptrace.ClientTrace, err error) {
if trace != nil && trace.WroteRequest != nil {
trace.WroteRequest(httptrace.WroteRequestInfo{Err: err})
}
}
func traceFirstResponseByte(trace *httptrace.ClientTrace) {
if trace != nil && trace.GotFirstResponseByte != nil {
trace.GotFirstResponseByte()
}
} }

View File

@ -11,8 +11,8 @@ import (
"net/http" "net/http"
"net/url" "net/url"
"golang.org/x/net/http/httpguts"
"golang.org/x/net/http2/hpack" "golang.org/x/net/http2/hpack"
"golang.org/x/net/lex/httplex"
) )
// writeFramer is implemented by any type that is used to write frames. // writeFramer is implemented by any type that is used to write frames.
@ -199,7 +199,7 @@ func (w *writeResHeaders) staysWithinBuffer(max int) bool {
// TODO: this is a common one. It'd be nice to return true // TODO: this is a common one. It'd be nice to return true
// here and get into the fast path if we could be clever and // here and get into the fast path if we could be clever and
// calculate the size fast enough, or at least a conservative // calculate the size fast enough, or at least a conservative
// uppper bound that usually fires. (Maybe if w.h and // upper bound that usually fires. (Maybe if w.h and
// w.trailers are nil, so we don't need to enumerate it.) // w.trailers are nil, so we don't need to enumerate it.)
// Otherwise I'm afraid that just calculating the length to // Otherwise I'm afraid that just calculating the length to
// answer this question would be slower than the ~2µs benefit. // answer this question would be slower than the ~2µs benefit.
@ -329,7 +329,7 @@ func (wu writeWindowUpdate) writeFrame(ctx writeContext) error {
} }
// encodeHeaders encodes an http.Header. If keys is not nil, then (k, h[k]) // encodeHeaders encodes an http.Header. If keys is not nil, then (k, h[k])
// is encoded only only if k is in keys. // is encoded only if k is in keys.
func encodeHeaders(enc *hpack.Encoder, h http.Header, keys []string) { func encodeHeaders(enc *hpack.Encoder, h http.Header, keys []string) {
if keys == nil { if keys == nil {
sorter := sorterPool.Get().(*sorter) sorter := sorterPool.Get().(*sorter)
@ -350,7 +350,7 @@ func encodeHeaders(enc *hpack.Encoder, h http.Header, keys []string) {
} }
isTE := k == "transfer-encoding" isTE := k == "transfer-encoding"
for _, v := range vv { for _, v := range vv {
if !httplex.ValidHeaderFieldValue(v) { if !httpguts.ValidHeaderFieldValue(v) {
// TODO: return an error? golang.org/issue/14048 // TODO: return an error? golang.org/issue/14048
// For now just omit it. // For now just omit it.
continue continue

33
vendor/golang.org/x/net/internal/nettest/BUILD generated vendored Normal file
View File

@ -0,0 +1,33 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"helper_bsd.go",
"helper_nobsd.go",
"helper_posix.go",
"helper_stub.go",
"helper_unix.go",
"helper_windows.go",
"interface.go",
"rlimit.go",
"stack.go",
],
importmap = "k8s.io/kubernetes/vendor/golang.org/x/net/internal/nettest",
importpath = "golang.org/x/net/internal/nettest",
visibility = ["//vendor/golang.org/x/net:__subpackages__"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

24
vendor/golang.org/x/net/internal/nettest/helper_bsd.go generated vendored Normal file
View File

@ -0,0 +1,24 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build darwin dragonfly freebsd netbsd openbsd
package nettest
import (
"runtime"
)
func supportsIPv6MulticastDeliveryOnLoopback() bool {
switch runtime.GOOS {
case "freebsd":
// See http://www.freebsd.org/cgi/query-pr.cgi?pr=180065.
// Even after the fix, it looks like the latest
// kernels don't deliver link-local scoped multicast
// packets correctly.
return false
default:
return true
}
}

View File

@ -2,15 +2,10 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build !go1.9 // +build aix linux solaris
package http2 package nettest
import ( func supportsIPv6MulticastDeliveryOnLoopback() bool {
"net/http" return true
)
func configureServer19(s *http.Server, conf *Server) error {
// not supported prior to go1.9
return nil
} }

View File

@ -0,0 +1,31 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris windows
package nettest
import (
"os"
"syscall"
)
func protocolNotSupported(err error) bool {
switch err := err.(type) {
case syscall.Errno:
switch err {
case syscall.EPROTONOSUPPORT, syscall.ENOPROTOOPT:
return true
}
case *os.SyscallError:
switch err := err.Err.(type) {
case syscall.Errno:
switch err {
case syscall.EPROTONOSUPPORT, syscall.ENOPROTOOPT:
return true
}
}
}
return false
}

View File

@ -0,0 +1,28 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build js nacl plan9
package nettest
import (
"fmt"
"runtime"
)
func maxOpenFiles() int {
return defaultMaxOpenFiles
}
func supportsRawIPSocket() (string, bool) {
return fmt.Sprintf("not supported on %s", runtime.GOOS), false
}
func supportsIPv6MulticastDeliveryOnLoopback() bool {
return false
}
func protocolNotSupported(err error) bool {
return false
}

View File

@ -0,0 +1,29 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
package nettest
import (
"fmt"
"os"
"runtime"
"syscall"
)
func maxOpenFiles() int {
var rlim syscall.Rlimit
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlim); err != nil {
return defaultMaxOpenFiles
}
return int(rlim.Cur)
}
func supportsRawIPSocket() (string, bool) {
if os.Getuid() != 0 {
return fmt.Sprintf("must be root on %s", runtime.GOOS), false
}
return "", true
}

View File

@ -0,0 +1,38 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package nettest
import (
"fmt"
"runtime"
"syscall"
)
func maxOpenFiles() int {
return 4 * defaultMaxOpenFiles /* actually it's 16581375 */
}
func supportsRawIPSocket() (string, bool) {
// From http://msdn.microsoft.com/en-us/library/windows/desktop/ms740548.aspx:
// Note: To use a socket of type SOCK_RAW requires administrative privileges.
// Users running Winsock applications that use raw sockets must be a member of
// the Administrators group on the local computer, otherwise raw socket calls
// will fail with an error code of WSAEACCES. On Windows Vista and later, access
// for raw sockets is enforced at socket creation. In earlier versions of Windows,
// access for raw sockets is enforced during other socket operations.
s, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, 0)
if err == syscall.WSAEACCES {
return fmt.Sprintf("no access to raw socket allowed on %s", runtime.GOOS), false
}
if err != nil {
return err.Error(), false
}
syscall.Closesocket(s)
return "", true
}
func supportsIPv6MulticastDeliveryOnLoopback() bool {
return true
}

94
vendor/golang.org/x/net/internal/nettest/interface.go generated vendored Normal file
View File

@ -0,0 +1,94 @@
// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package nettest
import "net"
// IsMulticastCapable reports whether ifi is an IP multicast-capable
// network interface. Network must be "ip", "ip4" or "ip6".
func IsMulticastCapable(network string, ifi *net.Interface) (net.IP, bool) {
switch network {
case "ip", "ip4", "ip6":
default:
return nil, false
}
if ifi == nil || ifi.Flags&net.FlagUp == 0 || ifi.Flags&net.FlagMulticast == 0 {
return nil, false
}
return hasRoutableIP(network, ifi)
}
// RoutedInterface returns a network interface that can route IP
// traffic and satisfies flags. It returns nil when an appropriate
// network interface is not found. Network must be "ip", "ip4" or
// "ip6".
func RoutedInterface(network string, flags net.Flags) *net.Interface {
switch network {
case "ip", "ip4", "ip6":
default:
return nil
}
ift, err := net.Interfaces()
if err != nil {
return nil
}
for _, ifi := range ift {
if ifi.Flags&flags != flags {
continue
}
if _, ok := hasRoutableIP(network, &ifi); !ok {
continue
}
return &ifi
}
return nil
}
func hasRoutableIP(network string, ifi *net.Interface) (net.IP, bool) {
ifat, err := ifi.Addrs()
if err != nil {
return nil, false
}
for _, ifa := range ifat {
switch ifa := ifa.(type) {
case *net.IPAddr:
if ip := routableIP(network, ifa.IP); ip != nil {
return ip, true
}
case *net.IPNet:
if ip := routableIP(network, ifa.IP); ip != nil {
return ip, true
}
}
}
return nil, false
}
func routableIP(network string, ip net.IP) net.IP {
if !ip.IsLoopback() && !ip.IsLinkLocalUnicast() && !ip.IsGlobalUnicast() {
return nil
}
switch network {
case "ip4":
if ip := ip.To4(); ip != nil {
return ip
}
case "ip6":
if ip.IsLoopback() { // addressing scope of the loopback address depends on each implementation
return nil
}
if ip := ip.To16(); ip != nil && ip.To4() == nil {
return ip
}
default:
if ip := ip.To4(); ip != nil {
return ip
}
if ip := ip.To16(); ip != nil {
return ip
}
}
return nil
}

11
vendor/golang.org/x/net/internal/nettest/rlimit.go generated vendored Normal file
View File

@ -0,0 +1,11 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package nettest
const defaultMaxOpenFiles = 256
// MaxOpenFiles returns the maximum number of open files for the
// caller's process.
func MaxOpenFiles() int { return maxOpenFiles() }

152
vendor/golang.org/x/net/internal/nettest/stack.go generated vendored Normal file
View File

@ -0,0 +1,152 @@
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package nettest provides utilities for network testing.
package nettest
import (
"fmt"
"io/ioutil"
"net"
"os"
"runtime"
)
var (
supportsIPv4 bool
supportsIPv6 bool
)
func init() {
if ln, err := net.Listen("tcp4", "127.0.0.1:0"); err == nil {
ln.Close()
supportsIPv4 = true
}
if ln, err := net.Listen("tcp6", "[::1]:0"); err == nil {
ln.Close()
supportsIPv6 = true
}
}
// SupportsIPv4 reports whether the platform supports IPv4 networking
// functionality.
func SupportsIPv4() bool { return supportsIPv4 }
// SupportsIPv6 reports whether the platform supports IPv6 networking
// functionality.
func SupportsIPv6() bool { return supportsIPv6 }
// SupportsRawIPSocket reports whether the platform supports raw IP
// sockets.
func SupportsRawIPSocket() (string, bool) {
return supportsRawIPSocket()
}
// SupportsIPv6MulticastDeliveryOnLoopback reports whether the
// platform supports IPv6 multicast packet delivery on software
// loopback interface.
func SupportsIPv6MulticastDeliveryOnLoopback() bool {
return supportsIPv6MulticastDeliveryOnLoopback()
}
// ProtocolNotSupported reports whether err is a protocol not
// supported error.
func ProtocolNotSupported(err error) bool {
return protocolNotSupported(err)
}
// TestableNetwork reports whether network is testable on the current
// platform configuration.
func TestableNetwork(network string) bool {
// This is based on logic from standard library's
// net/platform_test.go.
switch network {
case "unix", "unixgram":
switch runtime.GOOS {
case "android", "js", "nacl", "plan9", "windows":
return false
}
if runtime.GOOS == "darwin" && (runtime.GOARCH == "arm" || runtime.GOARCH == "arm64") {
return false
}
case "unixpacket":
switch runtime.GOOS {
case "aix", "android", "darwin", "freebsd", "js", "nacl", "plan9", "windows":
return false
case "netbsd":
// It passes on amd64 at least. 386 fails (Issue 22927). arm is unknown.
if runtime.GOARCH == "386" {
return false
}
}
}
return true
}
// NewLocalListener returns a listener which listens to a loopback IP
// address or local file system path.
// Network must be "tcp", "tcp4", "tcp6", "unix" or "unixpacket".
func NewLocalListener(network string) (net.Listener, error) {
switch network {
case "tcp":
if supportsIPv4 {
if ln, err := net.Listen("tcp4", "127.0.0.1:0"); err == nil {
return ln, nil
}
}
if supportsIPv6 {
return net.Listen("tcp6", "[::1]:0")
}
case "tcp4":
if supportsIPv4 {
return net.Listen("tcp4", "127.0.0.1:0")
}
case "tcp6":
if supportsIPv6 {
return net.Listen("tcp6", "[::1]:0")
}
case "unix", "unixpacket":
return net.Listen(network, localPath())
}
return nil, fmt.Errorf("%s is not supported", network)
}
// NewLocalPacketListener returns a packet listener which listens to a
// loopback IP address or local file system path.
// Network must be "udp", "udp4", "udp6" or "unixgram".
func NewLocalPacketListener(network string) (net.PacketConn, error) {
switch network {
case "udp":
if supportsIPv4 {
if c, err := net.ListenPacket("udp4", "127.0.0.1:0"); err == nil {
return c, nil
}
}
if supportsIPv6 {
return net.ListenPacket("udp6", "[::1]:0")
}
case "udp4":
if supportsIPv4 {
return net.ListenPacket("udp4", "127.0.0.1:0")
}
case "udp6":
if supportsIPv6 {
return net.ListenPacket("udp6", "[::1]:0")
}
case "unixgram":
return net.ListenPacket(network, localPath())
}
return nil, fmt.Errorf("%s is not supported", network)
}
func localPath() string {
f, err := ioutil.TempFile("", "nettest")
if err != nil {
panic(err)
}
path := f.Name()
f.Close()
os.Remove(path)
return path
}

26
vendor/golang.org/x/net/internal/socks/BUILD generated vendored Normal file
View File

@ -0,0 +1,26 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"client.go",
"socks.go",
],
importmap = "k8s.io/kubernetes/vendor/golang.org/x/net/internal/socks",
importpath = "golang.org/x/net/internal/socks",
visibility = ["//vendor/golang.org/x/net:__subpackages__"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

168
vendor/golang.org/x/net/internal/socks/client.go generated vendored Normal file
View File

@ -0,0 +1,168 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package socks
import (
"context"
"errors"
"io"
"net"
"strconv"
"time"
)
var (
noDeadline = time.Time{}
aLongTimeAgo = time.Unix(1, 0)
)
func (d *Dialer) connect(ctx context.Context, c net.Conn, address string) (_ net.Addr, ctxErr error) {
host, port, err := splitHostPort(address)
if err != nil {
return nil, err
}
if deadline, ok := ctx.Deadline(); ok && !deadline.IsZero() {
c.SetDeadline(deadline)
defer c.SetDeadline(noDeadline)
}
if ctx != context.Background() {
errCh := make(chan error, 1)
done := make(chan struct{})
defer func() {
close(done)
if ctxErr == nil {
ctxErr = <-errCh
}
}()
go func() {
select {
case <-ctx.Done():
c.SetDeadline(aLongTimeAgo)
errCh <- ctx.Err()
case <-done:
errCh <- nil
}
}()
}
b := make([]byte, 0, 6+len(host)) // the size here is just an estimate
b = append(b, Version5)
if len(d.AuthMethods) == 0 || d.Authenticate == nil {
b = append(b, 1, byte(AuthMethodNotRequired))
} else {
ams := d.AuthMethods
if len(ams) > 255 {
return nil, errors.New("too many authentication methods")
}
b = append(b, byte(len(ams)))
for _, am := range ams {
b = append(b, byte(am))
}
}
if _, ctxErr = c.Write(b); ctxErr != nil {
return
}
if _, ctxErr = io.ReadFull(c, b[:2]); ctxErr != nil {
return
}
if b[0] != Version5 {
return nil, errors.New("unexpected protocol version " + strconv.Itoa(int(b[0])))
}
am := AuthMethod(b[1])
if am == AuthMethodNoAcceptableMethods {
return nil, errors.New("no acceptable authentication methods")
}
if d.Authenticate != nil {
if ctxErr = d.Authenticate(ctx, c, am); ctxErr != nil {
return
}
}
b = b[:0]
b = append(b, Version5, byte(d.cmd), 0)
if ip := net.ParseIP(host); ip != nil {
if ip4 := ip.To4(); ip4 != nil {
b = append(b, AddrTypeIPv4)
b = append(b, ip4...)
} else if ip6 := ip.To16(); ip6 != nil {
b = append(b, AddrTypeIPv6)
b = append(b, ip6...)
} else {
return nil, errors.New("unknown address type")
}
} else {
if len(host) > 255 {
return nil, errors.New("FQDN too long")
}
b = append(b, AddrTypeFQDN)
b = append(b, byte(len(host)))
b = append(b, host...)
}
b = append(b, byte(port>>8), byte(port))
if _, ctxErr = c.Write(b); ctxErr != nil {
return
}
if _, ctxErr = io.ReadFull(c, b[:4]); ctxErr != nil {
return
}
if b[0] != Version5 {
return nil, errors.New("unexpected protocol version " + strconv.Itoa(int(b[0])))
}
if cmdErr := Reply(b[1]); cmdErr != StatusSucceeded {
return nil, errors.New("unknown error " + cmdErr.String())
}
if b[2] != 0 {
return nil, errors.New("non-zero reserved field")
}
l := 2
var a Addr
switch b[3] {
case AddrTypeIPv4:
l += net.IPv4len
a.IP = make(net.IP, net.IPv4len)
case AddrTypeIPv6:
l += net.IPv6len
a.IP = make(net.IP, net.IPv6len)
case AddrTypeFQDN:
if _, err := io.ReadFull(c, b[:1]); err != nil {
return nil, err
}
l += int(b[0])
default:
return nil, errors.New("unknown address type " + strconv.Itoa(int(b[3])))
}
if cap(b) < l {
b = make([]byte, l)
} else {
b = b[:l]
}
if _, ctxErr = io.ReadFull(c, b); ctxErr != nil {
return
}
if a.IP != nil {
copy(a.IP, b)
} else {
a.Name = string(b[:len(b)-2])
}
a.Port = int(b[len(b)-2])<<8 | int(b[len(b)-1])
return &a, nil
}
func splitHostPort(address string) (string, int, error) {
host, port, err := net.SplitHostPort(address)
if err != nil {
return "", 0, err
}
portnum, err := strconv.Atoi(port)
if err != nil {
return "", 0, err
}
if 1 > portnum || portnum > 0xffff {
return "", 0, errors.New("port number out of range " + port)
}
return host, portnum, nil
}

317
vendor/golang.org/x/net/internal/socks/socks.go generated vendored Normal file
View File

@ -0,0 +1,317 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package socks provides a SOCKS version 5 client implementation.
//
// SOCKS protocol version 5 is defined in RFC 1928.
// Username/Password authentication for SOCKS version 5 is defined in
// RFC 1929.
package socks
import (
"context"
"errors"
"io"
"net"
"strconv"
)
// A Command represents a SOCKS command.
type Command int
func (cmd Command) String() string {
switch cmd {
case CmdConnect:
return "socks connect"
case cmdBind:
return "socks bind"
default:
return "socks " + strconv.Itoa(int(cmd))
}
}
// An AuthMethod represents a SOCKS authentication method.
type AuthMethod int
// A Reply represents a SOCKS command reply code.
type Reply int
func (code Reply) String() string {
switch code {
case StatusSucceeded:
return "succeeded"
case 0x01:
return "general SOCKS server failure"
case 0x02:
return "connection not allowed by ruleset"
case 0x03:
return "network unreachable"
case 0x04:
return "host unreachable"
case 0x05:
return "connection refused"
case 0x06:
return "TTL expired"
case 0x07:
return "command not supported"
case 0x08:
return "address type not supported"
default:
return "unknown code: " + strconv.Itoa(int(code))
}
}
// Wire protocol constants.
const (
Version5 = 0x05
AddrTypeIPv4 = 0x01
AddrTypeFQDN = 0x03
AddrTypeIPv6 = 0x04
CmdConnect Command = 0x01 // establishes an active-open forward proxy connection
cmdBind Command = 0x02 // establishes a passive-open forward proxy connection
AuthMethodNotRequired AuthMethod = 0x00 // no authentication required
AuthMethodUsernamePassword AuthMethod = 0x02 // use username/password
AuthMethodNoAcceptableMethods AuthMethod = 0xff // no acceptable authentication methods
StatusSucceeded Reply = 0x00
)
// An Addr represents a SOCKS-specific address.
// Either Name or IP is used exclusively.
type Addr struct {
Name string // fully-qualified domain name
IP net.IP
Port int
}
func (a *Addr) Network() string { return "socks" }
func (a *Addr) String() string {
if a == nil {
return "<nil>"
}
port := strconv.Itoa(a.Port)
if a.IP == nil {
return net.JoinHostPort(a.Name, port)
}
return net.JoinHostPort(a.IP.String(), port)
}
// A Conn represents a forward proxy connection.
type Conn struct {
net.Conn
boundAddr net.Addr
}
// BoundAddr returns the address assigned by the proxy server for
// connecting to the command target address from the proxy server.
func (c *Conn) BoundAddr() net.Addr {
if c == nil {
return nil
}
return c.boundAddr
}
// A Dialer holds SOCKS-specific options.
type Dialer struct {
cmd Command // either CmdConnect or cmdBind
proxyNetwork string // network between a proxy server and a client
proxyAddress string // proxy server address
// ProxyDial specifies the optional dial function for
// establishing the transport connection.
ProxyDial func(context.Context, string, string) (net.Conn, error)
// AuthMethods specifies the list of request authention
// methods.
// If empty, SOCKS client requests only AuthMethodNotRequired.
AuthMethods []AuthMethod
// Authenticate specifies the optional authentication
// function. It must be non-nil when AuthMethods is not empty.
// It must return an error when the authentication is failed.
Authenticate func(context.Context, io.ReadWriter, AuthMethod) error
}
// DialContext connects to the provided address on the provided
// network.
//
// The returned error value may be a net.OpError. When the Op field of
// net.OpError contains "socks", the Source field contains a proxy
// server address and the Addr field contains a command target
// address.
//
// See func Dial of the net package of standard library for a
// description of the network and address parameters.
func (d *Dialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
if err := d.validateTarget(network, address); err != nil {
proxy, dst, _ := d.pathAddrs(address)
return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
}
if ctx == nil {
proxy, dst, _ := d.pathAddrs(address)
return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: errors.New("nil context")}
}
var err error
var c net.Conn
if d.ProxyDial != nil {
c, err = d.ProxyDial(ctx, d.proxyNetwork, d.proxyAddress)
} else {
var dd net.Dialer
c, err = dd.DialContext(ctx, d.proxyNetwork, d.proxyAddress)
}
if err != nil {
proxy, dst, _ := d.pathAddrs(address)
return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
}
a, err := d.connect(ctx, c, address)
if err != nil {
c.Close()
proxy, dst, _ := d.pathAddrs(address)
return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
}
return &Conn{Conn: c, boundAddr: a}, nil
}
// DialWithConn initiates a connection from SOCKS server to the target
// network and address using the connection c that is already
// connected to the SOCKS server.
//
// It returns the connection's local address assigned by the SOCKS
// server.
func (d *Dialer) DialWithConn(ctx context.Context, c net.Conn, network, address string) (net.Addr, error) {
if err := d.validateTarget(network, address); err != nil {
proxy, dst, _ := d.pathAddrs(address)
return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
}
if ctx == nil {
proxy, dst, _ := d.pathAddrs(address)
return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: errors.New("nil context")}
}
a, err := d.connect(ctx, c, address)
if err != nil {
proxy, dst, _ := d.pathAddrs(address)
return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
}
return a, nil
}
// Dial connects to the provided address on the provided network.
//
// Unlike DialContext, it returns a raw transport connection instead
// of a forward proxy connection.
//
// Deprecated: Use DialContext or DialWithConn instead.
func (d *Dialer) Dial(network, address string) (net.Conn, error) {
if err := d.validateTarget(network, address); err != nil {
proxy, dst, _ := d.pathAddrs(address)
return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
}
var err error
var c net.Conn
if d.ProxyDial != nil {
c, err = d.ProxyDial(context.Background(), d.proxyNetwork, d.proxyAddress)
} else {
c, err = net.Dial(d.proxyNetwork, d.proxyAddress)
}
if err != nil {
proxy, dst, _ := d.pathAddrs(address)
return nil, &net.OpError{Op: d.cmd.String(), Net: network, Source: proxy, Addr: dst, Err: err}
}
if _, err := d.DialWithConn(context.Background(), c, network, address); err != nil {
c.Close()
return nil, err
}
return c, nil
}
func (d *Dialer) validateTarget(network, address string) error {
switch network {
case "tcp", "tcp6", "tcp4":
default:
return errors.New("network not implemented")
}
switch d.cmd {
case CmdConnect, cmdBind:
default:
return errors.New("command not implemented")
}
return nil
}
func (d *Dialer) pathAddrs(address string) (proxy, dst net.Addr, err error) {
for i, s := range []string{d.proxyAddress, address} {
host, port, err := splitHostPort(s)
if err != nil {
return nil, nil, err
}
a := &Addr{Port: port}
a.IP = net.ParseIP(host)
if a.IP == nil {
a.Name = host
}
if i == 0 {
proxy = a
} else {
dst = a
}
}
return
}
// NewDialer returns a new Dialer that dials through the provided
// proxy server's network and address.
func NewDialer(network, address string) *Dialer {
return &Dialer{proxyNetwork: network, proxyAddress: address, cmd: CmdConnect}
}
const (
authUsernamePasswordVersion = 0x01
authStatusSucceeded = 0x00
)
// UsernamePassword are the credentials for the username/password
// authentication method.
type UsernamePassword struct {
Username string
Password string
}
// Authenticate authenticates a pair of username and password with the
// proxy server.
func (up *UsernamePassword) Authenticate(ctx context.Context, rw io.ReadWriter, auth AuthMethod) error {
switch auth {
case AuthMethodNotRequired:
return nil
case AuthMethodUsernamePassword:
if len(up.Username) == 0 || len(up.Username) > 255 || len(up.Password) == 0 || len(up.Password) > 255 {
return errors.New("invalid username/password")
}
b := []byte{authUsernamePasswordVersion}
b = append(b, byte(len(up.Username)))
b = append(b, up.Username...)
b = append(b, byte(len(up.Password)))
b = append(b, up.Password...)
// TODO(mikio): handle IO deadlines and cancelation if
// necessary
if _, err := rw.Write(b); err != nil {
return err
}
if _, err := io.ReadFull(rw, b[:2]); err != nil {
return err
}
if b[0] != authUsernamePasswordVersion {
return errors.New("invalid username/password version")
}
if b[1] != authStatusSucceeded {
return errors.New("username/password authentication failed")
}
return nil
}
return errors.New("unsupported authentication method " + strconv.Itoa(int(auth)))
}

27
vendor/golang.org/x/net/internal/sockstest/BUILD generated vendored Normal file
View File

@ -0,0 +1,27 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["server.go"],
importmap = "k8s.io/kubernetes/vendor/golang.org/x/net/internal/sockstest",
importpath = "golang.org/x/net/internal/sockstest",
visibility = ["//vendor/golang.org/x/net:__subpackages__"],
deps = [
"//vendor/golang.org/x/net/internal/nettest:go_default_library",
"//vendor/golang.org/x/net/internal/socks:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

241
vendor/golang.org/x/net/internal/sockstest/server.go generated vendored Normal file
View File

@ -0,0 +1,241 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package sockstest provides utilities for SOCKS testing.
package sockstest
import (
"errors"
"io"
"net"
"golang.org/x/net/internal/nettest"
"golang.org/x/net/internal/socks"
)
// An AuthRequest represents an authentication request.
type AuthRequest struct {
Version int
Methods []socks.AuthMethod
}
// ParseAuthRequest parses an authentication request.
func ParseAuthRequest(b []byte) (*AuthRequest, error) {
if len(b) < 2 {
return nil, errors.New("short auth request")
}
if b[0] != socks.Version5 {
return nil, errors.New("unexpected protocol version")
}
if len(b)-2 < int(b[1]) {
return nil, errors.New("short auth request")
}
req := &AuthRequest{Version: int(b[0])}
if b[1] > 0 {
req.Methods = make([]socks.AuthMethod, b[1])
for i, m := range b[2 : 2+b[1]] {
req.Methods[i] = socks.AuthMethod(m)
}
}
return req, nil
}
// MarshalAuthReply returns an authentication reply in wire format.
func MarshalAuthReply(ver int, m socks.AuthMethod) ([]byte, error) {
return []byte{byte(ver), byte(m)}, nil
}
// A CmdRequest repesents a command request.
type CmdRequest struct {
Version int
Cmd socks.Command
Addr socks.Addr
}
// ParseCmdRequest parses a command request.
func ParseCmdRequest(b []byte) (*CmdRequest, error) {
if len(b) < 7 {
return nil, errors.New("short cmd request")
}
if b[0] != socks.Version5 {
return nil, errors.New("unexpected protocol version")
}
if socks.Command(b[1]) != socks.CmdConnect {
return nil, errors.New("unexpected command")
}
if b[2] != 0 {
return nil, errors.New("non-zero reserved field")
}
req := &CmdRequest{Version: int(b[0]), Cmd: socks.Command(b[1])}
l := 2
off := 4
switch b[3] {
case socks.AddrTypeIPv4:
l += net.IPv4len
req.Addr.IP = make(net.IP, net.IPv4len)
case socks.AddrTypeIPv6:
l += net.IPv6len
req.Addr.IP = make(net.IP, net.IPv6len)
case socks.AddrTypeFQDN:
l += int(b[4])
off = 5
default:
return nil, errors.New("unknown address type")
}
if len(b[off:]) < l {
return nil, errors.New("short cmd request")
}
if req.Addr.IP != nil {
copy(req.Addr.IP, b[off:])
} else {
req.Addr.Name = string(b[off : off+l-2])
}
req.Addr.Port = int(b[off+l-2])<<8 | int(b[off+l-1])
return req, nil
}
// MarshalCmdReply returns a command reply in wire format.
func MarshalCmdReply(ver int, reply socks.Reply, a *socks.Addr) ([]byte, error) {
b := make([]byte, 4)
b[0] = byte(ver)
b[1] = byte(reply)
if a.Name != "" {
if len(a.Name) > 255 {
return nil, errors.New("fqdn too long")
}
b[3] = socks.AddrTypeFQDN
b = append(b, byte(len(a.Name)))
b = append(b, a.Name...)
} else if ip4 := a.IP.To4(); ip4 != nil {
b[3] = socks.AddrTypeIPv4
b = append(b, ip4...)
} else if ip6 := a.IP.To16(); ip6 != nil {
b[3] = socks.AddrTypeIPv6
b = append(b, ip6...)
} else {
return nil, errors.New("unknown address type")
}
b = append(b, byte(a.Port>>8), byte(a.Port))
return b, nil
}
// A Server repesents a server for handshake testing.
type Server struct {
ln net.Listener
}
// Addr rerurns a server address.
func (s *Server) Addr() net.Addr {
return s.ln.Addr()
}
// TargetAddr returns a fake final destination address.
//
// The returned address is only valid for testing with Server.
func (s *Server) TargetAddr() net.Addr {
a := s.ln.Addr()
switch a := a.(type) {
case *net.TCPAddr:
if a.IP.To4() != nil {
return &net.TCPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 5963}
}
if a.IP.To16() != nil && a.IP.To4() == nil {
return &net.TCPAddr{IP: net.IPv6loopback, Port: 5963}
}
}
return nil
}
// Close closes the server.
func (s *Server) Close() error {
return s.ln.Close()
}
func (s *Server) serve(authFunc, cmdFunc func(io.ReadWriter, []byte) error) {
c, err := s.ln.Accept()
if err != nil {
return
}
defer c.Close()
go s.serve(authFunc, cmdFunc)
b := make([]byte, 512)
n, err := c.Read(b)
if err != nil {
return
}
if err := authFunc(c, b[:n]); err != nil {
return
}
n, err = c.Read(b)
if err != nil {
return
}
if err := cmdFunc(c, b[:n]); err != nil {
return
}
}
// NewServer returns a new server.
//
// The provided authFunc and cmdFunc must parse requests and return
// appropriate replies to clients.
func NewServer(authFunc, cmdFunc func(io.ReadWriter, []byte) error) (*Server, error) {
var err error
s := new(Server)
s.ln, err = nettest.NewLocalListener("tcp")
if err != nil {
return nil, err
}
go s.serve(authFunc, cmdFunc)
return s, nil
}
// NoAuthRequired handles a no-authentication-required signaling.
func NoAuthRequired(rw io.ReadWriter, b []byte) error {
req, err := ParseAuthRequest(b)
if err != nil {
return err
}
b, err = MarshalAuthReply(req.Version, socks.AuthMethodNotRequired)
if err != nil {
return err
}
n, err := rw.Write(b)
if err != nil {
return err
}
if n != len(b) {
return errors.New("short write")
}
return nil
}
// NoProxyRequired handles a command signaling without constructing a
// proxy connection to the final destination.
func NoProxyRequired(rw io.ReadWriter, b []byte) error {
req, err := ParseCmdRequest(b)
if err != nil {
return err
}
req.Addr.Port += 1
if req.Addr.Name != "" {
req.Addr.Name = "boundaddr.doesnotexist"
} else if req.Addr.IP.To4() != nil {
req.Addr.IP = net.IPv4(127, 0, 0, 1)
} else {
req.Addr.IP = net.IPv6loopback
}
b, err = MarshalCmdReply(socks.Version5, socks.StatusSucceeded, &req.Addr)
if err != nil {
return err
}
n, err := rw.Write(b)
if err != nil {
return err
}
if n != len(b) {
return errors.New("short write")
}
return nil
}

View File

@ -11,6 +11,7 @@ go_library(
importmap = "k8s.io/kubernetes/vendor/golang.org/x/net/proxy", importmap = "k8s.io/kubernetes/vendor/golang.org/x/net/proxy",
importpath = "golang.org/x/net/proxy", importpath = "golang.org/x/net/proxy",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = ["//vendor/golang.org/x/net/internal/socks:go_default_library"],
) )
filegroup( filegroup(

View File

@ -79,8 +79,13 @@ func FromURL(u *url.URL, forward Dialer) (Dialer, error) {
} }
switch u.Scheme { switch u.Scheme {
case "socks5": case "socks5", "socks5h":
return SOCKS5("tcp", u.Host, auth, forward) addr := u.Hostname()
port := u.Port()
if port == "" {
port = "1080"
}
return SOCKS5("tcp", net.JoinHostPort(addr, port), auth, forward)
} }
// If the scheme doesn't match any of the built-in schemes, see if it // If the scheme doesn't match any of the built-in schemes, see if it

View File

@ -5,210 +5,32 @@
package proxy package proxy
import ( import (
"errors" "context"
"io"
"net" "net"
"strconv"
"golang.org/x/net/internal/socks"
) )
// SOCKS5 returns a Dialer that makes SOCKSv5 connections to the given address // SOCKS5 returns a Dialer that makes SOCKSv5 connections to the given
// with an optional username and password. See RFC 1928 and RFC 1929. // address with an optional username and password.
func SOCKS5(network, addr string, auth *Auth, forward Dialer) (Dialer, error) { // See RFC 1928 and RFC 1929.
s := &socks5{ func SOCKS5(network, address string, auth *Auth, forward Dialer) (Dialer, error) {
network: network, d := socks.NewDialer(network, address)
addr: addr, if forward != nil {
forward: forward, d.ProxyDial = func(_ context.Context, network string, address string) (net.Conn, error) {
return forward.Dial(network, address)
}
} }
if auth != nil { if auth != nil {
s.user = auth.User up := socks.UsernamePassword{
s.password = auth.Password Username: auth.User,
Password: auth.Password,
}
d.AuthMethods = []socks.AuthMethod{
socks.AuthMethodNotRequired,
socks.AuthMethodUsernamePassword,
}
d.Authenticate = up.Authenticate
} }
return d, nil
return s, nil
}
type socks5 struct {
user, password string
network, addr string
forward Dialer
}
const socks5Version = 5
const (
socks5AuthNone = 0
socks5AuthPassword = 2
)
const socks5Connect = 1
const (
socks5IP4 = 1
socks5Domain = 3
socks5IP6 = 4
)
var socks5Errors = []string{
"",
"general failure",
"connection forbidden",
"network unreachable",
"host unreachable",
"connection refused",
"TTL expired",
"command not supported",
"address type not supported",
}
// Dial connects to the address addr on the given network via the SOCKS5 proxy.
func (s *socks5) Dial(network, addr string) (net.Conn, error) {
switch network {
case "tcp", "tcp6", "tcp4":
default:
return nil, errors.New("proxy: no support for SOCKS5 proxy connections of type " + network)
}
conn, err := s.forward.Dial(s.network, s.addr)
if err != nil {
return nil, err
}
if err := s.connect(conn, addr); err != nil {
conn.Close()
return nil, err
}
return conn, nil
}
// connect takes an existing connection to a socks5 proxy server,
// and commands the server to extend that connection to target,
// which must be a canonical address with a host and port.
func (s *socks5) connect(conn net.Conn, target string) error {
host, portStr, err := net.SplitHostPort(target)
if err != nil {
return err
}
port, err := strconv.Atoi(portStr)
if err != nil {
return errors.New("proxy: failed to parse port number: " + portStr)
}
if port < 1 || port > 0xffff {
return errors.New("proxy: port number out of range: " + portStr)
}
// the size here is just an estimate
buf := make([]byte, 0, 6+len(host))
buf = append(buf, socks5Version)
if len(s.user) > 0 && len(s.user) < 256 && len(s.password) < 256 {
buf = append(buf, 2 /* num auth methods */, socks5AuthNone, socks5AuthPassword)
} else {
buf = append(buf, 1 /* num auth methods */, socks5AuthNone)
}
if _, err := conn.Write(buf); err != nil {
return errors.New("proxy: failed to write greeting to SOCKS5 proxy at " + s.addr + ": " + err.Error())
}
if _, err := io.ReadFull(conn, buf[:2]); err != nil {
return errors.New("proxy: failed to read greeting from SOCKS5 proxy at " + s.addr + ": " + err.Error())
}
if buf[0] != 5 {
return errors.New("proxy: SOCKS5 proxy at " + s.addr + " has unexpected version " + strconv.Itoa(int(buf[0])))
}
if buf[1] == 0xff {
return errors.New("proxy: SOCKS5 proxy at " + s.addr + " requires authentication")
}
// See RFC 1929
if buf[1] == socks5AuthPassword {
buf = buf[:0]
buf = append(buf, 1 /* password protocol version */)
buf = append(buf, uint8(len(s.user)))
buf = append(buf, s.user...)
buf = append(buf, uint8(len(s.password)))
buf = append(buf, s.password...)
if _, err := conn.Write(buf); err != nil {
return errors.New("proxy: failed to write authentication request to SOCKS5 proxy at " + s.addr + ": " + err.Error())
}
if _, err := io.ReadFull(conn, buf[:2]); err != nil {
return errors.New("proxy: failed to read authentication reply from SOCKS5 proxy at " + s.addr + ": " + err.Error())
}
if buf[1] != 0 {
return errors.New("proxy: SOCKS5 proxy at " + s.addr + " rejected username/password")
}
}
buf = buf[:0]
buf = append(buf, socks5Version, socks5Connect, 0 /* reserved */)
if ip := net.ParseIP(host); ip != nil {
if ip4 := ip.To4(); ip4 != nil {
buf = append(buf, socks5IP4)
ip = ip4
} else {
buf = append(buf, socks5IP6)
}
buf = append(buf, ip...)
} else {
if len(host) > 255 {
return errors.New("proxy: destination host name too long: " + host)
}
buf = append(buf, socks5Domain)
buf = append(buf, byte(len(host)))
buf = append(buf, host...)
}
buf = append(buf, byte(port>>8), byte(port))
if _, err := conn.Write(buf); err != nil {
return errors.New("proxy: failed to write connect request to SOCKS5 proxy at " + s.addr + ": " + err.Error())
}
if _, err := io.ReadFull(conn, buf[:4]); err != nil {
return errors.New("proxy: failed to read connect reply from SOCKS5 proxy at " + s.addr + ": " + err.Error())
}
failure := "unknown error"
if int(buf[1]) < len(socks5Errors) {
failure = socks5Errors[buf[1]]
}
if len(failure) > 0 {
return errors.New("proxy: SOCKS5 proxy at " + s.addr + " failed to connect: " + failure)
}
bytesToDiscard := 0
switch buf[3] {
case socks5IP4:
bytesToDiscard = net.IPv4len
case socks5IP6:
bytesToDiscard = net.IPv6len
case socks5Domain:
_, err := io.ReadFull(conn, buf[:1])
if err != nil {
return errors.New("proxy: failed to read domain length from SOCKS5 proxy at " + s.addr + ": " + err.Error())
}
bytesToDiscard = int(buf[0])
default:
return errors.New("proxy: got unknown address type " + strconv.Itoa(int(buf[3])) + " from SOCKS5 proxy at " + s.addr)
}
if cap(buf) < bytesToDiscard {
buf = make([]byte, bytesToDiscard)
} else {
buf = buf[:bytesToDiscard]
}
if _, err := io.ReadFull(conn, buf); err != nil {
return errors.New("proxy: failed to read address from SOCKS5 proxy at " + s.addr + ": " + err.Error())
}
// Also need to discard the port number
if _, err := io.ReadFull(conn, buf[:2]); err != nil {
return errors.New("proxy: failed to read port from SOCKS5 proxy at " + s.addr + ": " + err.Error())
}
return nil
} }

View File

@ -6,16 +6,11 @@ go_library(
"events.go", "events.go",
"histogram.go", "histogram.go",
"trace.go", "trace.go",
"trace_go16.go",
"trace_go17.go",
], ],
importmap = "k8s.io/kubernetes/vendor/golang.org/x/net/trace", importmap = "k8s.io/kubernetes/vendor/golang.org/x/net/trace",
importpath = "golang.org/x/net/trace", importpath = "golang.org/x/net/trace",
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
deps = [ deps = ["//vendor/golang.org/x/net/internal/timeseries:go_default_library"],
"//vendor/golang.org/x/net/context:go_default_library",
"//vendor/golang.org/x/net/internal/timeseries:go_default_library",
],
) )
filegroup( filegroup(

View File

@ -64,12 +64,14 @@ package trace
import ( import (
"bytes" "bytes"
"context"
"fmt" "fmt"
"html/template" "html/template"
"io" "io"
"log" "log"
"net" "net"
"net/http" "net/http"
"net/url"
"runtime" "runtime"
"sort" "sort"
"strconv" "strconv"
@ -84,6 +86,12 @@ import (
// FOR DEBUGGING ONLY. This will slow down the program. // FOR DEBUGGING ONLY. This will slow down the program.
var DebugUseAfterFinish = false var DebugUseAfterFinish = false
// HTTP ServeMux paths.
const (
debugRequestsPath = "/debug/requests"
debugEventsPath = "/debug/events"
)
// AuthRequest determines whether a specific request is permitted to load the // AuthRequest determines whether a specific request is permitted to load the
// /debug/requests or /debug/events pages. // /debug/requests or /debug/events pages.
// //
@ -110,10 +118,29 @@ var AuthRequest = func(req *http.Request) (any, sensitive bool) {
} }
func init() { func init() {
_, pat := http.DefaultServeMux.Handler(&http.Request{URL: &url.URL{Path: debugRequestsPath}})
if pat == debugRequestsPath {
panic("/debug/requests is already registered. You may have two independent copies of " +
"golang.org/x/net/trace in your binary, trying to maintain separate state. This may " +
"involve a vendored copy of golang.org/x/net/trace.")
}
// TODO(jbd): Serve Traces from /debug/traces in the future? // TODO(jbd): Serve Traces from /debug/traces in the future?
// There is no requirement for a request to be present to have traces. // There is no requirement for a request to be present to have traces.
http.HandleFunc("/debug/requests", Traces) http.HandleFunc(debugRequestsPath, Traces)
http.HandleFunc("/debug/events", Events) http.HandleFunc(debugEventsPath, Events)
}
// NewContext returns a copy of the parent context
// and associates it with a Trace.
func NewContext(ctx context.Context, tr Trace) context.Context {
return context.WithValue(ctx, contextKey, tr)
}
// FromContext returns the Trace bound to the context, if any.
func FromContext(ctx context.Context) (tr Trace, ok bool) {
tr, ok = ctx.Value(contextKey).(Trace)
return
} }
// Traces responds with traces from the program. // Traces responds with traces from the program.
@ -368,7 +395,11 @@ func New(family, title string) Trace {
} }
func (tr *trace) Finish() { func (tr *trace) Finish() {
tr.Elapsed = time.Now().Sub(tr.Start) elapsed := time.Now().Sub(tr.Start)
tr.mu.Lock()
tr.Elapsed = elapsed
tr.mu.Unlock()
if DebugUseAfterFinish { if DebugUseAfterFinish {
buf := make([]byte, 4<<10) // 4 KB should be enough buf := make([]byte, 4<<10) // 4 KB should be enough
n := runtime.Stack(buf, false) n := runtime.Stack(buf, false)
@ -381,14 +412,17 @@ func (tr *trace) Finish() {
m.Remove(tr) m.Remove(tr)
f := getFamily(tr.Family, true) f := getFamily(tr.Family, true)
tr.mu.RLock() // protects tr fields in Cond.match calls
for _, b := range f.Buckets { for _, b := range f.Buckets {
if b.Cond.match(tr) { if b.Cond.match(tr) {
b.Add(tr) b.Add(tr)
} }
} }
tr.mu.RUnlock()
// Add a sample of elapsed time as microseconds to the family's timeseries // Add a sample of elapsed time as microseconds to the family's timeseries
h := new(histogram) h := new(histogram)
h.addMeasurement(tr.Elapsed.Nanoseconds() / 1e3) h.addMeasurement(elapsed.Nanoseconds() / 1e3)
f.LatencyMu.Lock() f.LatencyMu.Lock()
f.Latency.Add(h) f.Latency.Add(h)
f.LatencyMu.Unlock() f.LatencyMu.Unlock()
@ -684,25 +718,20 @@ type trace struct {
// Title is the title of this trace. // Title is the title of this trace.
Title string Title string
// Timing information. // Start time of the this trace.
Start time.Time Start time.Time
Elapsed time.Duration // zero while active
// Trace information if non-zero.
traceID uint64
spanID uint64
// Whether this trace resulted in an error.
IsError bool
// Append-only sequence of events (modulo discards).
mu sync.RWMutex mu sync.RWMutex
events []event events []event // Append-only sequence of events (modulo discards).
maxEvents int maxEvents int
recycler func(interface{})
IsError bool // Whether this trace resulted in an error.
Elapsed time.Duration // Elapsed time for this trace, zero while active.
traceID uint64 // Trace information if non-zero.
spanID uint64
refs int32 // how many buckets this is in refs int32 // how many buckets this is in
recycler func(interface{}) disc discarded // scratch space to avoid allocation
disc discarded // scratch space to avoid allocation
finishStack []byte // where finish was called, if DebugUseAfterFinish is set finishStack []byte // where finish was called, if DebugUseAfterFinish is set
@ -714,14 +743,18 @@ func (tr *trace) reset() {
tr.Family = "" tr.Family = ""
tr.Title = "" tr.Title = ""
tr.Start = time.Time{} tr.Start = time.Time{}
tr.mu.Lock()
tr.Elapsed = 0 tr.Elapsed = 0
tr.traceID = 0 tr.traceID = 0
tr.spanID = 0 tr.spanID = 0
tr.IsError = false tr.IsError = false
tr.maxEvents = 0 tr.maxEvents = 0
tr.events = nil tr.events = nil
tr.refs = 0
tr.recycler = nil tr.recycler = nil
tr.mu.Unlock()
tr.refs = 0
tr.disc = 0 tr.disc = 0
tr.finishStack = nil tr.finishStack = nil
for i := range tr.eventsBuf { for i := range tr.eventsBuf {
@ -801,21 +834,31 @@ func (tr *trace) LazyPrintf(format string, a ...interface{}) {
tr.addEvent(&lazySprintf{format, a}, false, false) tr.addEvent(&lazySprintf{format, a}, false, false)
} }
func (tr *trace) SetError() { tr.IsError = true } func (tr *trace) SetError() {
tr.mu.Lock()
tr.IsError = true
tr.mu.Unlock()
}
func (tr *trace) SetRecycler(f func(interface{})) { func (tr *trace) SetRecycler(f func(interface{})) {
tr.mu.Lock()
tr.recycler = f tr.recycler = f
tr.mu.Unlock()
} }
func (tr *trace) SetTraceInfo(traceID, spanID uint64) { func (tr *trace) SetTraceInfo(traceID, spanID uint64) {
tr.mu.Lock()
tr.traceID, tr.spanID = traceID, spanID tr.traceID, tr.spanID = traceID, spanID
tr.mu.Unlock()
} }
func (tr *trace) SetMaxEvents(m int) { func (tr *trace) SetMaxEvents(m int) {
tr.mu.Lock()
// Always keep at least three events: first, discarded count, last. // Always keep at least three events: first, discarded count, last.
if len(tr.events) == 0 && m > 3 { if len(tr.events) == 0 && m > 3 {
tr.maxEvents = m tr.maxEvents = m
} }
tr.mu.Unlock()
} }
func (tr *trace) ref() { func (tr *trace) ref() {
@ -824,6 +867,7 @@ func (tr *trace) ref() {
func (tr *trace) unref() { func (tr *trace) unref() {
if atomic.AddInt32(&tr.refs, -1) == 0 { if atomic.AddInt32(&tr.refs, -1) == 0 {
tr.mu.RLock()
if tr.recycler != nil { if tr.recycler != nil {
// freeTrace clears tr, so we hold tr.recycler and tr.events here. // freeTrace clears tr, so we hold tr.recycler and tr.events here.
go func(f func(interface{}), es []event) { go func(f func(interface{}), es []event) {
@ -834,6 +878,7 @@ func (tr *trace) unref() {
} }
}(tr.recycler, tr.events) }(tr.recycler, tr.events)
} }
tr.mu.RUnlock()
freeTrace(tr) freeTrace(tr)
} }
@ -844,7 +889,10 @@ func (tr *trace) When() string {
} }
func (tr *trace) ElapsedTime() string { func (tr *trace) ElapsedTime() string {
tr.mu.RLock()
t := tr.Elapsed t := tr.Elapsed
tr.mu.RUnlock()
if t == 0 { if t == 0 {
// Active trace. // Active trace.
t = time.Since(tr.Start) t = time.Since(tr.Start)

View File

@ -1,21 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build !go1.7
package trace
import "golang.org/x/net/context"
// NewContext returns a copy of the parent context
// and associates it with a Trace.
func NewContext(ctx context.Context, tr Trace) context.Context {
return context.WithValue(ctx, contextKey, tr)
}
// FromContext returns the Trace bound to the context, if any.
func FromContext(ctx context.Context) (tr Trace, ok bool) {
tr, ok = ctx.Value(contextKey).(Trace)
return
}

View File

@ -1,21 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build go1.7
package trace
import "context"
// NewContext returns a copy of the parent context
// and associates it with a Trace.
func NewContext(ctx context.Context, tr Trace) context.Context {
return context.WithValue(ctx, contextKey, tr)
}
// FromContext returns the Trace bound to the context, if any.
func FromContext(ctx context.Context) (tr Trace, ok bool) {
tr, ok = ctx.Value(contextKey).(Trace)
return
}

View File

@ -241,7 +241,10 @@ func (ws *Conn) Close() error {
return err1 return err1
} }
// IsClientConn reports whether ws is a client-side connection.
func (ws *Conn) IsClientConn() bool { return ws.request == nil } func (ws *Conn) IsClientConn() bool { return ws.request == nil }
// IsServerConn reports whether ws is a server-side connection.
func (ws *Conn) IsServerConn() bool { return ws.request != nil } func (ws *Conn) IsServerConn() bool { return ws.request != nil }
// LocalAddr returns the WebSocket Origin for the connection for client, or // LocalAddr returns the WebSocket Origin for the connection for client, or