Merge pull request #16473 from containers/dependabot/go_modules/github.com/onsi/gomega-1.24.1

Bump github.com/onsi/gomega from 1.24.0 to 1.24.1
This commit is contained in:
OpenShift Merge Robot
2022-11-13 12:17:14 +00:00
committed by GitHub
14 changed files with 422 additions and 185 deletions

4
go.mod
View File

@ -41,7 +41,7 @@ require (
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6
github.com/nxadm/tail v1.4.8 github.com/nxadm/tail v1.4.8
github.com/onsi/ginkgo v1.16.5 github.com/onsi/ginkgo v1.16.5
github.com/onsi/gomega v1.24.0 github.com/onsi/gomega v1.24.1
github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/go-digest v1.0.0
github.com/opencontainers/image-spec v1.1.0-rc2 github.com/opencontainers/image-spec v1.1.0-rc2
github.com/opencontainers/runc v1.1.4 github.com/opencontainers/runc v1.1.4
@ -134,7 +134,7 @@ require (
go.opencensus.io v0.23.0 // indirect go.opencensus.io v0.23.0 // indirect
golang.org/x/crypto v0.1.0 // indirect golang.org/x/crypto v0.1.0 // indirect
golang.org/x/mod v0.6.0 // indirect golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect golang.org/x/net v0.2.0 // indirect
golang.org/x/tools v0.2.0 // indirect golang.org/x/tools v0.2.0 // indirect
google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a // indirect google.golang.org/genproto v0.0.0-20221014213838-99cd37c6964a // indirect
google.golang.org/grpc v1.50.1 // indirect google.golang.org/grpc v1.50.1 // indirect

8
go.sum
View File

@ -739,8 +739,8 @@ github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoT
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.24.0 h1:+0glovB9Jd6z3VR+ScSwQqXVTIfJcGA9UBM8yzQxhqg= github.com/onsi/gomega v1.24.1 h1:KORJXNNTzJXzu4ScJWssJfJMnJ+2QJqhoQSRwNlze9E=
github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM=
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
@ -1109,8 +1109,8 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0= golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=

View File

@ -1,3 +1,15 @@
## 1.24.1
### Fixes
- maintain backward compatibility for Eventually and Consisntetly's signatures [4c7df5e]
- fix small typo (#601) [ea0ebe6]
### Maintenance
- Bump golang.org/x/net from 0.1.0 to 0.2.0 (#603) [1ba8372]
- Bump github.com/onsi/ginkgo/v2 from 2.4.0 to 2.5.0 (#602) [f9426cb]
- fix label-filter in test.yml [d795db6]
- stop running flakey tests and rely on external network dependencies in CI [7133290]
## 1.24.0 ## 1.24.0
### Features ### Features

View File

@ -121,7 +121,6 @@ To assert that the command has exited it is more convenient to use the Exit matc
When the process exits because it has received a particular signal, the exit code will be 128+signal-value When the process exits because it has received a particular signal, the exit code will be 128+signal-value
(See http://www.tldp.org/LDP/abs/html/exitcodes.html and http://man7.org/linux/man-pages/man7/signal.7.html) (See http://www.tldp.org/LDP/abs/html/exitcodes.html and http://man7.org/linux/man-pages/man7/signal.7.html)
*/ */
func (s *Session) ExitCode() int { func (s *Session) ExitCode() int {
s.lock.Lock() s.lock.Lock()
@ -142,9 +141,7 @@ will wait for the command to exit then return the entirety of Out's contents.
Wait uses eventually under the hood and accepts the same timeout/polling intervals that eventually does. Wait uses eventually under the hood and accepts the same timeout/polling intervals that eventually does.
*/ */
func (s *Session) Wait(timeout ...interface{}) *Session { func (s *Session) Wait(timeout ...interface{}) *Session {
args := []any{s} EventuallyWithOffset(1, s, timeout...).Should(Exit())
args = append(args, timeout...)
EventuallyWithOffset(1, args...).Should(Exit())
return s return s
} }

View File

@ -22,7 +22,7 @@ import (
"github.com/onsi/gomega/types" "github.com/onsi/gomega/types"
) )
const GOMEGA_VERSION = "1.24.0" const GOMEGA_VERSION = "1.24.1"
const nilGomegaPanic = `You are trying to make an assertion, but haven't registered Gomega's fail handler. const nilGomegaPanic = `You are trying to make an assertion, but haven't registered Gomega's fail handler.
If you're using Ginkgo then you probably forgot to put your assertion in an It(). If you're using Ginkgo then you probably forgot to put your assertion in an It().
@ -368,9 +368,9 @@ is equivalent to
Eventually(...).WithTimeout(time.Second).WithPolling(2*time.Second).WithContext(ctx).Should(...) Eventually(...).WithTimeout(time.Second).WithPolling(2*time.Second).WithContext(ctx).Should(...)
*/ */
func Eventually(args ...interface{}) AsyncAssertion { func Eventually(actualOrCtx interface{}, args ...interface{}) AsyncAssertion {
ensureDefaultGomegaIsConfigured() ensureDefaultGomegaIsConfigured()
return Default.Eventually(args...) return Default.Eventually(actualOrCtx, args...)
} }
// EventuallyWithOffset operates like Eventually but takes an additional // EventuallyWithOffset operates like Eventually but takes an additional
@ -382,9 +382,9 @@ func Eventually(args ...interface{}) AsyncAssertion {
// `EventuallyWithOffset` specifying a timeout interval (and an optional polling interval) are // `EventuallyWithOffset` specifying a timeout interval (and an optional polling interval) are
// the same as `Eventually(...).WithOffset(...).WithTimeout` or // the same as `Eventually(...).WithOffset(...).WithTimeout` or
// `Eventually(...).WithOffset(...).WithTimeout(...).WithPolling`. // `Eventually(...).WithOffset(...).WithTimeout(...).WithPolling`.
func EventuallyWithOffset(offset int, args ...interface{}) AsyncAssertion { func EventuallyWithOffset(offset int, actualOrCtx interface{}, args ...interface{}) AsyncAssertion {
ensureDefaultGomegaIsConfigured() ensureDefaultGomegaIsConfigured()
return Default.EventuallyWithOffset(offset, args...) return Default.EventuallyWithOffset(offset, actualOrCtx, args...)
} }
/* /*
@ -402,9 +402,9 @@ Consistently is useful in cases where you want to assert that something *does no
This will block for 200 milliseconds and repeatedly check the channel and ensure nothing has been received. This will block for 200 milliseconds and repeatedly check the channel and ensure nothing has been received.
*/ */
func Consistently(args ...interface{}) AsyncAssertion { func Consistently(actualOrCtx interface{}, args ...interface{}) AsyncAssertion {
ensureDefaultGomegaIsConfigured() ensureDefaultGomegaIsConfigured()
return Default.Consistently(args...) return Default.Consistently(actualOrCtx, args...)
} }
// ConsistentlyWithOffset operates like Consistently but takes an additional // ConsistentlyWithOffset operates like Consistently but takes an additional
@ -413,9 +413,9 @@ func Consistently(args ...interface{}) AsyncAssertion {
// //
// `ConsistentlyWithOffset` is the same as `Consistently(...).WithOffset` and // `ConsistentlyWithOffset` is the same as `Consistently(...).WithOffset` and
// optional `WithTimeout` and `WithPolling`. // optional `WithTimeout` and `WithPolling`.
func ConsistentlyWithOffset(offset int, args ...interface{}) AsyncAssertion { func ConsistentlyWithOffset(offset int, actualOrCtx interface{}, args ...interface{}) AsyncAssertion {
ensureDefaultGomegaIsConfigured() ensureDefaultGomegaIsConfigured()
return Default.ConsistentlyWithOffset(offset, args...) return Default.ConsistentlyWithOffset(offset, actualOrCtx, args...)
} }
/* /*

View File

@ -2,7 +2,6 @@ package internal
import ( import (
"context" "context"
"fmt"
"time" "time"
"github.com/onsi/gomega/types" "github.com/onsi/gomega/types"
@ -53,42 +52,38 @@ func (g *Gomega) ExpectWithOffset(offset int, actual interface{}, extra ...inter
return NewAssertion(actual, g, offset, extra...) return NewAssertion(actual, g, offset, extra...)
} }
func (g *Gomega) Eventually(args ...interface{}) types.AsyncAssertion { func (g *Gomega) Eventually(actualOrCtx interface{}, args ...interface{}) types.AsyncAssertion {
return g.makeAsyncAssertion(AsyncAssertionTypeEventually, 0, args...) return g.makeAsyncAssertion(AsyncAssertionTypeEventually, 0, actualOrCtx, args...)
} }
func (g *Gomega) EventuallyWithOffset(offset int, args ...interface{}) types.AsyncAssertion { func (g *Gomega) EventuallyWithOffset(offset int, actualOrCtx interface{}, args ...interface{}) types.AsyncAssertion {
return g.makeAsyncAssertion(AsyncAssertionTypeEventually, offset, args...) return g.makeAsyncAssertion(AsyncAssertionTypeEventually, offset, actualOrCtx, args...)
} }
func (g *Gomega) Consistently(args ...interface{}) types.AsyncAssertion { func (g *Gomega) Consistently(actualOrCtx interface{}, args ...interface{}) types.AsyncAssertion {
return g.makeAsyncAssertion(AsyncAssertionTypeConsistently, 0, args...) return g.makeAsyncAssertion(AsyncAssertionTypeConsistently, 0, actualOrCtx, args...)
} }
func (g *Gomega) ConsistentlyWithOffset(offset int, args ...interface{}) types.AsyncAssertion { func (g *Gomega) ConsistentlyWithOffset(offset int, actualOrCtx interface{}, args ...interface{}) types.AsyncAssertion {
return g.makeAsyncAssertion(AsyncAssertionTypeConsistently, offset, args...) return g.makeAsyncAssertion(AsyncAssertionTypeConsistently, offset, actualOrCtx, args...)
} }
func (g *Gomega) makeAsyncAssertion(asyncAssertionType AsyncAssertionType, offset int, args ...interface{}) types.AsyncAssertion { func (g *Gomega) makeAsyncAssertion(asyncAssertionType AsyncAssertionType, offset int, actualOrCtx interface{}, args ...interface{}) types.AsyncAssertion {
baseOffset := 3 baseOffset := 3
timeoutInterval := -time.Duration(1) timeoutInterval := -time.Duration(1)
pollingInterval := -time.Duration(1) pollingInterval := -time.Duration(1)
intervals := []interface{}{} intervals := []interface{}{}
var ctx context.Context var ctx context.Context
if len(args) == 0 {
g.Fail(fmt.Sprintf("Call to %s is missing a value or function to poll", asyncAssertionType), offset+baseOffset)
return nil
}
actual := args[0] actual := actualOrCtx
startingIndex := 1 startingIndex := 0
if _, isCtx := args[0].(context.Context); isCtx && len(args) > 1 { if _, isCtx := actualOrCtx.(context.Context); isCtx && len(args) > 0 {
// the first argument is a context, we should accept it as the context _only if_ it is **not** the only argumnent **and** the second argument is not a parseable duration // the first argument is a context, we should accept it as the context _only if_ it is **not** the only argumnent **and** the second argument is not a parseable duration
// this is due to an unfortunate ambiguity in early version of Gomega in which multi-type durations are allowed after the actual // this is due to an unfortunate ambiguity in early version of Gomega in which multi-type durations are allowed after the actual
if _, err := toDuration(args[1]); err != nil { if _, err := toDuration(args[0]); err != nil {
ctx = args[0].(context.Context) ctx = actualOrCtx.(context.Context)
actual = args[1] actual = args[0]
startingIndex = 2 startingIndex = 1
} }
} }

View File

@ -19,11 +19,11 @@ type Gomega interface {
Expect(actual interface{}, extra ...interface{}) Assertion Expect(actual interface{}, extra ...interface{}) Assertion
ExpectWithOffset(offset int, actual interface{}, extra ...interface{}) Assertion ExpectWithOffset(offset int, actual interface{}, extra ...interface{}) Assertion
Eventually(args ...interface{}) AsyncAssertion Eventually(actualOrCtx interface{}, args ...interface{}) AsyncAssertion
EventuallyWithOffset(offset int, args ...interface{}) AsyncAssertion EventuallyWithOffset(offset int, actualOrCtx interface{}, args ...interface{}) AsyncAssertion
Consistently(args ...interface{}) AsyncAssertion Consistently(actualOrCtx interface{}, args ...interface{}) AsyncAssertion
ConsistentlyWithOffset(offset int, args ...interface{}) AsyncAssertion ConsistentlyWithOffset(offset int, actualOrCtx interface{}, args ...interface{}) AsyncAssertion
SetDefaultEventuallyTimeout(time.Duration) SetDefaultEventuallyTimeout(time.Duration)
SetDefaultEventuallyPollingInterval(time.Duration) SetDefaultEventuallyPollingInterval(time.Duration)

View File

@ -605,7 +605,10 @@ func (z *Tokenizer) readComment() {
z.data.end = z.data.start z.data.end = z.data.start
} }
}() }()
for dashCount := 2; ; {
var dashCount int
beginning := true
for {
c := z.readByte() c := z.readByte()
if z.err != nil { if z.err != nil {
// Ignore up to two dashes at EOF. // Ignore up to two dashes at EOF.
@ -620,7 +623,7 @@ func (z *Tokenizer) readComment() {
dashCount++ dashCount++
continue continue
case '>': case '>':
if dashCount >= 2 { if dashCount >= 2 || beginning {
z.data.end = z.raw.end - len("-->") z.data.end = z.raw.end - len("-->")
return return
} }
@ -638,6 +641,7 @@ func (z *Tokenizer) readComment() {
} }
} }
dashCount = 0 dashCount = 0
beginning = false
} }
} }

View File

@ -27,7 +27,14 @@ func buildCommonHeaderMaps() {
"accept-language", "accept-language",
"accept-ranges", "accept-ranges",
"age", "age",
"access-control-allow-credentials",
"access-control-allow-headers",
"access-control-allow-methods",
"access-control-allow-origin", "access-control-allow-origin",
"access-control-expose-headers",
"access-control-max-age",
"access-control-request-headers",
"access-control-request-method",
"allow", "allow",
"authorization", "authorization",
"cache-control", "cache-control",
@ -53,6 +60,7 @@ func buildCommonHeaderMaps() {
"link", "link",
"location", "location",
"max-forwards", "max-forwards",
"origin",
"proxy-authenticate", "proxy-authenticate",
"proxy-authorization", "proxy-authorization",
"range", "range",
@ -68,6 +76,8 @@ func buildCommonHeaderMaps() {
"vary", "vary",
"via", "via",
"www-authenticate", "www-authenticate",
"x-forwarded-for",
"x-forwarded-proto",
} }
commonLowerHeader = make(map[string]string, len(common)) commonLowerHeader = make(map[string]string, len(common))
commonCanonHeader = make(map[string]string, len(common)) commonCanonHeader = make(map[string]string, len(common))
@ -85,3 +95,11 @@ func lowerHeader(v string) (lower string, ascii bool) {
} }
return asciiToLower(v) return asciiToLower(v)
} }
func canonicalHeader(v string) string {
buildCommonHeaderMapsOnce()
if s, ok := commonCanonHeader[v]; ok {
return s
}
return http.CanonicalHeaderKey(v)
}

188
vendor/golang.org/x/net/http2/hpack/static_table.go generated vendored Normal file
View File

@ -0,0 +1,188 @@
// go generate gen.go
// Code generated by the command above; DO NOT EDIT.
package hpack
var staticTable = &headerFieldTable{
evictCount: 0,
byName: map[string]uint64{
":authority": 1,
":method": 3,
":path": 5,
":scheme": 7,
":status": 14,
"accept-charset": 15,
"accept-encoding": 16,
"accept-language": 17,
"accept-ranges": 18,
"accept": 19,
"access-control-allow-origin": 20,
"age": 21,
"allow": 22,
"authorization": 23,
"cache-control": 24,
"content-disposition": 25,
"content-encoding": 26,
"content-language": 27,
"content-length": 28,
"content-location": 29,
"content-range": 30,
"content-type": 31,
"cookie": 32,
"date": 33,
"etag": 34,
"expect": 35,
"expires": 36,
"from": 37,
"host": 38,
"if-match": 39,
"if-modified-since": 40,
"if-none-match": 41,
"if-range": 42,
"if-unmodified-since": 43,
"last-modified": 44,
"link": 45,
"location": 46,
"max-forwards": 47,
"proxy-authenticate": 48,
"proxy-authorization": 49,
"range": 50,
"referer": 51,
"refresh": 52,
"retry-after": 53,
"server": 54,
"set-cookie": 55,
"strict-transport-security": 56,
"transfer-encoding": 57,
"user-agent": 58,
"vary": 59,
"via": 60,
"www-authenticate": 61,
},
byNameValue: map[pairNameValue]uint64{
{name: ":authority", value: ""}: 1,
{name: ":method", value: "GET"}: 2,
{name: ":method", value: "POST"}: 3,
{name: ":path", value: "/"}: 4,
{name: ":path", value: "/index.html"}: 5,
{name: ":scheme", value: "http"}: 6,
{name: ":scheme", value: "https"}: 7,
{name: ":status", value: "200"}: 8,
{name: ":status", value: "204"}: 9,
{name: ":status", value: "206"}: 10,
{name: ":status", value: "304"}: 11,
{name: ":status", value: "400"}: 12,
{name: ":status", value: "404"}: 13,
{name: ":status", value: "500"}: 14,
{name: "accept-charset", value: ""}: 15,
{name: "accept-encoding", value: "gzip, deflate"}: 16,
{name: "accept-language", value: ""}: 17,
{name: "accept-ranges", value: ""}: 18,
{name: "accept", value: ""}: 19,
{name: "access-control-allow-origin", value: ""}: 20,
{name: "age", value: ""}: 21,
{name: "allow", value: ""}: 22,
{name: "authorization", value: ""}: 23,
{name: "cache-control", value: ""}: 24,
{name: "content-disposition", value: ""}: 25,
{name: "content-encoding", value: ""}: 26,
{name: "content-language", value: ""}: 27,
{name: "content-length", value: ""}: 28,
{name: "content-location", value: ""}: 29,
{name: "content-range", value: ""}: 30,
{name: "content-type", value: ""}: 31,
{name: "cookie", value: ""}: 32,
{name: "date", value: ""}: 33,
{name: "etag", value: ""}: 34,
{name: "expect", value: ""}: 35,
{name: "expires", value: ""}: 36,
{name: "from", value: ""}: 37,
{name: "host", value: ""}: 38,
{name: "if-match", value: ""}: 39,
{name: "if-modified-since", value: ""}: 40,
{name: "if-none-match", value: ""}: 41,
{name: "if-range", value: ""}: 42,
{name: "if-unmodified-since", value: ""}: 43,
{name: "last-modified", value: ""}: 44,
{name: "link", value: ""}: 45,
{name: "location", value: ""}: 46,
{name: "max-forwards", value: ""}: 47,
{name: "proxy-authenticate", value: ""}: 48,
{name: "proxy-authorization", value: ""}: 49,
{name: "range", value: ""}: 50,
{name: "referer", value: ""}: 51,
{name: "refresh", value: ""}: 52,
{name: "retry-after", value: ""}: 53,
{name: "server", value: ""}: 54,
{name: "set-cookie", value: ""}: 55,
{name: "strict-transport-security", value: ""}: 56,
{name: "transfer-encoding", value: ""}: 57,
{name: "user-agent", value: ""}: 58,
{name: "vary", value: ""}: 59,
{name: "via", value: ""}: 60,
{name: "www-authenticate", value: ""}: 61,
},
ents: []HeaderField{
{Name: ":authority", Value: "", Sensitive: false},
{Name: ":method", Value: "GET", Sensitive: false},
{Name: ":method", Value: "POST", Sensitive: false},
{Name: ":path", Value: "/", Sensitive: false},
{Name: ":path", Value: "/index.html", Sensitive: false},
{Name: ":scheme", Value: "http", Sensitive: false},
{Name: ":scheme", Value: "https", Sensitive: false},
{Name: ":status", Value: "200", Sensitive: false},
{Name: ":status", Value: "204", Sensitive: false},
{Name: ":status", Value: "206", Sensitive: false},
{Name: ":status", Value: "304", Sensitive: false},
{Name: ":status", Value: "400", Sensitive: false},
{Name: ":status", Value: "404", Sensitive: false},
{Name: ":status", Value: "500", Sensitive: false},
{Name: "accept-charset", Value: "", Sensitive: false},
{Name: "accept-encoding", Value: "gzip, deflate", Sensitive: false},
{Name: "accept-language", Value: "", Sensitive: false},
{Name: "accept-ranges", Value: "", Sensitive: false},
{Name: "accept", Value: "", Sensitive: false},
{Name: "access-control-allow-origin", Value: "", Sensitive: false},
{Name: "age", Value: "", Sensitive: false},
{Name: "allow", Value: "", Sensitive: false},
{Name: "authorization", Value: "", Sensitive: false},
{Name: "cache-control", Value: "", Sensitive: false},
{Name: "content-disposition", Value: "", Sensitive: false},
{Name: "content-encoding", Value: "", Sensitive: false},
{Name: "content-language", Value: "", Sensitive: false},
{Name: "content-length", Value: "", Sensitive: false},
{Name: "content-location", Value: "", Sensitive: false},
{Name: "content-range", Value: "", Sensitive: false},
{Name: "content-type", Value: "", Sensitive: false},
{Name: "cookie", Value: "", Sensitive: false},
{Name: "date", Value: "", Sensitive: false},
{Name: "etag", Value: "", Sensitive: false},
{Name: "expect", Value: "", Sensitive: false},
{Name: "expires", Value: "", Sensitive: false},
{Name: "from", Value: "", Sensitive: false},
{Name: "host", Value: "", Sensitive: false},
{Name: "if-match", Value: "", Sensitive: false},
{Name: "if-modified-since", Value: "", Sensitive: false},
{Name: "if-none-match", Value: "", Sensitive: false},
{Name: "if-range", Value: "", Sensitive: false},
{Name: "if-unmodified-since", Value: "", Sensitive: false},
{Name: "last-modified", Value: "", Sensitive: false},
{Name: "link", Value: "", Sensitive: false},
{Name: "location", Value: "", Sensitive: false},
{Name: "max-forwards", Value: "", Sensitive: false},
{Name: "proxy-authenticate", Value: "", Sensitive: false},
{Name: "proxy-authorization", Value: "", Sensitive: false},
{Name: "range", Value: "", Sensitive: false},
{Name: "referer", Value: "", Sensitive: false},
{Name: "refresh", Value: "", Sensitive: false},
{Name: "retry-after", Value: "", Sensitive: false},
{Name: "server", Value: "", Sensitive: false},
{Name: "set-cookie", Value: "", Sensitive: false},
{Name: "strict-transport-security", Value: "", Sensitive: false},
{Name: "transfer-encoding", Value: "", Sensitive: false},
{Name: "user-agent", Value: "", Sensitive: false},
{Name: "vary", Value: "", Sensitive: false},
{Name: "via", Value: "", Sensitive: false},
{Name: "www-authenticate", Value: "", Sensitive: false},
},
}

View File

@ -96,8 +96,7 @@ func (t *headerFieldTable) evictOldest(n int) {
// meaning t.ents is reversed for dynamic tables. Hence, when t is a dynamic // meaning t.ents is reversed for dynamic tables. Hence, when t is a dynamic
// table, the return value i actually refers to the entry t.ents[t.len()-i]. // table, the return value i actually refers to the entry t.ents[t.len()-i].
// //
// All tables are assumed to be a dynamic tables except for the global // All tables are assumed to be a dynamic tables except for the global staticTable.
// staticTable pointer.
// //
// See Section 2.3.3. // See Section 2.3.3.
func (t *headerFieldTable) search(f HeaderField) (i uint64, nameValueMatch bool) { func (t *headerFieldTable) search(f HeaderField) (i uint64, nameValueMatch bool) {
@ -125,81 +124,6 @@ func (t *headerFieldTable) idToIndex(id uint64) uint64 {
return k + 1 return k + 1
} }
// http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#appendix-B
var staticTable = newStaticTable()
var staticTableEntries = [...]HeaderField{
{Name: ":authority"},
{Name: ":method", Value: "GET"},
{Name: ":method", Value: "POST"},
{Name: ":path", Value: "/"},
{Name: ":path", Value: "/index.html"},
{Name: ":scheme", Value: "http"},
{Name: ":scheme", Value: "https"},
{Name: ":status", Value: "200"},
{Name: ":status", Value: "204"},
{Name: ":status", Value: "206"},
{Name: ":status", Value: "304"},
{Name: ":status", Value: "400"},
{Name: ":status", Value: "404"},
{Name: ":status", Value: "500"},
{Name: "accept-charset"},
{Name: "accept-encoding", Value: "gzip, deflate"},
{Name: "accept-language"},
{Name: "accept-ranges"},
{Name: "accept"},
{Name: "access-control-allow-origin"},
{Name: "age"},
{Name: "allow"},
{Name: "authorization"},
{Name: "cache-control"},
{Name: "content-disposition"},
{Name: "content-encoding"},
{Name: "content-language"},
{Name: "content-length"},
{Name: "content-location"},
{Name: "content-range"},
{Name: "content-type"},
{Name: "cookie"},
{Name: "date"},
{Name: "etag"},
{Name: "expect"},
{Name: "expires"},
{Name: "from"},
{Name: "host"},
{Name: "if-match"},
{Name: "if-modified-since"},
{Name: "if-none-match"},
{Name: "if-range"},
{Name: "if-unmodified-since"},
{Name: "last-modified"},
{Name: "link"},
{Name: "location"},
{Name: "max-forwards"},
{Name: "proxy-authenticate"},
{Name: "proxy-authorization"},
{Name: "range"},
{Name: "referer"},
{Name: "refresh"},
{Name: "retry-after"},
{Name: "server"},
{Name: "set-cookie"},
{Name: "strict-transport-security"},
{Name: "transfer-encoding"},
{Name: "user-agent"},
{Name: "vary"},
{Name: "via"},
{Name: "www-authenticate"},
}
func newStaticTable() *headerFieldTable {
t := &headerFieldTable{}
t.init()
for _, e := range staticTableEntries[:] {
t.addEntry(e)
}
return t
}
var huffmanCodes = [256]uint32{ var huffmanCodes = [256]uint32{
0x1ff8, 0x1ff8,
0x7fffd8, 0x7fffd8,

View File

@ -622,7 +622,9 @@ type stream struct {
resetQueued bool // RST_STREAM queued for write; set by sc.resetStream resetQueued bool // RST_STREAM queued for write; set by sc.resetStream
gotTrailerHeader bool // HEADER frame for trailers was seen gotTrailerHeader bool // HEADER frame for trailers was seen
wroteHeaders bool // whether we wrote headers (not status 100) wroteHeaders bool // whether we wrote headers (not status 100)
readDeadline *time.Timer // nil if unused
writeDeadline *time.Timer // nil if unused writeDeadline *time.Timer // nil if unused
closeErr error // set before cw is closed
trailer http.Header // accumulated trailers trailer http.Header // accumulated trailers
reqTrailer http.Header // handler's Request.Trailer reqTrailer http.Header // handler's Request.Trailer
@ -869,7 +871,9 @@ func (sc *serverConn) serve() {
// Each connection starts with initialWindowSize inflow tokens. // Each connection starts with initialWindowSize inflow tokens.
// If a higher value is configured, we add more tokens. // If a higher value is configured, we add more tokens.
sc.sendWindowUpdate(nil) if diff := sc.srv.initialConnRecvWindowSize() - initialWindowSize; diff > 0 {
sc.sendWindowUpdate(nil, int(diff))
}
if err := sc.readPreface(); err != nil { if err := sc.readPreface(); err != nil {
sc.condlogf(err, "http2: server: error reading preface from client %v: %v", sc.conn.RemoteAddr(), err) sc.condlogf(err, "http2: server: error reading preface from client %v: %v", sc.conn.RemoteAddr(), err)
@ -946,6 +950,8 @@ func (sc *serverConn) serve() {
} }
case *startPushRequest: case *startPushRequest:
sc.startPush(v) sc.startPush(v)
case func(*serverConn):
v(sc)
default: default:
panic(fmt.Sprintf("unexpected type %T", v)) panic(fmt.Sprintf("unexpected type %T", v))
} }
@ -1459,6 +1465,21 @@ func (sc *serverConn) processFrame(f Frame) error {
sc.sawFirstSettings = true sc.sawFirstSettings = true
} }
// Discard frames for streams initiated after the identified last
// stream sent in a GOAWAY, or all frames after sending an error.
// We still need to return connection-level flow control for DATA frames.
// RFC 9113 Section 6.8.
if sc.inGoAway && (sc.goAwayCode != ErrCodeNo || f.Header().StreamID > sc.maxClientStreamID) {
if f, ok := f.(*DataFrame); ok {
if sc.inflow.available() < int32(f.Length) {
return sc.countError("data_flow", streamError(f.Header().StreamID, ErrCodeFlowControl))
}
sc.sendWindowUpdate(nil, int(f.Length)) // conn-level
}
return nil
}
switch f := f.(type) { switch f := f.(type) {
case *SettingsFrame: case *SettingsFrame:
return sc.processSettings(f) return sc.processSettings(f)
@ -1501,9 +1522,6 @@ func (sc *serverConn) processPing(f *PingFrame) error {
// PROTOCOL_ERROR." // PROTOCOL_ERROR."
return sc.countError("ping_on_stream", ConnectionError(ErrCodeProtocol)) return sc.countError("ping_on_stream", ConnectionError(ErrCodeProtocol))
} }
if sc.inGoAway && sc.goAwayCode != ErrCodeNo {
return nil
}
sc.writeFrame(FrameWriteRequest{write: writePingAck{f}}) sc.writeFrame(FrameWriteRequest{write: writePingAck{f}})
return nil return nil
} }
@ -1565,6 +1583,9 @@ func (sc *serverConn) closeStream(st *stream, err error) {
panic(fmt.Sprintf("invariant; can't close stream in state %v", st.state)) panic(fmt.Sprintf("invariant; can't close stream in state %v", st.state))
} }
st.state = stateClosed st.state = stateClosed
if st.readDeadline != nil {
st.readDeadline.Stop()
}
if st.writeDeadline != nil { if st.writeDeadline != nil {
st.writeDeadline.Stop() st.writeDeadline.Stop()
} }
@ -1586,10 +1607,18 @@ func (sc *serverConn) closeStream(st *stream, err error) {
if p := st.body; p != nil { if p := st.body; p != nil {
// Return any buffered unread bytes worth of conn-level flow control. // Return any buffered unread bytes worth of conn-level flow control.
// See golang.org/issue/16481 // See golang.org/issue/16481
sc.sendWindowUpdate(nil) sc.sendWindowUpdate(nil, p.Len())
p.CloseWithError(err) p.CloseWithError(err)
} }
if e, ok := err.(StreamError); ok {
if e.Cause != nil {
err = e.Cause
} else {
err = errStreamClosed
}
}
st.closeErr = err
st.cw.Close() // signals Handler's CloseNotifier, unblocks writes, etc st.cw.Close() // signals Handler's CloseNotifier, unblocks writes, etc
sc.writeSched.CloseStream(st.id) sc.writeSched.CloseStream(st.id)
} }
@ -1686,16 +1715,6 @@ func (sc *serverConn) processSettingInitialWindowSize(val uint32) error {
func (sc *serverConn) processData(f *DataFrame) error { func (sc *serverConn) processData(f *DataFrame) error {
sc.serveG.check() sc.serveG.check()
id := f.Header().StreamID id := f.Header().StreamID
if sc.inGoAway && (sc.goAwayCode != ErrCodeNo || id > sc.maxClientStreamID) {
// Discard all DATA frames if the GOAWAY is due to an
// error, or:
//
// Section 6.8: After sending a GOAWAY frame, the sender
// can discard frames for streams initiated by the
// receiver with identifiers higher than the identified
// last stream.
return nil
}
data := f.Data() data := f.Data()
state, st := sc.state(id) state, st := sc.state(id)
@ -1734,7 +1753,7 @@ func (sc *serverConn) processData(f *DataFrame) error {
// sendWindowUpdate, which also schedules sending the // sendWindowUpdate, which also schedules sending the
// frames. // frames.
sc.inflow.take(int32(f.Length)) sc.inflow.take(int32(f.Length))
sc.sendWindowUpdate(nil) // conn-level sc.sendWindowUpdate(nil, int(f.Length)) // conn-level
if st != nil && st.resetQueued { if st != nil && st.resetQueued {
// Already have a stream error in flight. Don't send another. // Already have a stream error in flight. Don't send another.
@ -1752,7 +1771,7 @@ func (sc *serverConn) processData(f *DataFrame) error {
return sc.countError("data_flow", streamError(id, ErrCodeFlowControl)) return sc.countError("data_flow", streamError(id, ErrCodeFlowControl))
} }
sc.inflow.take(int32(f.Length)) sc.inflow.take(int32(f.Length))
sc.sendWindowUpdate(nil) // conn-level sc.sendWindowUpdate(nil, int(f.Length)) // conn-level
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))
// RFC 7540, sec 8.1.2.6: A request or response is also malformed if the // RFC 7540, sec 8.1.2.6: A request or response is also malformed if the
@ -1770,7 +1789,7 @@ func (sc *serverConn) processData(f *DataFrame) error {
if len(data) > 0 { if len(data) > 0 {
wrote, err := st.body.Write(data) wrote, err := st.body.Write(data)
if err != nil { if err != nil {
sc.sendWindowUpdate32(nil, int32(f.Length)-int32(wrote)) sc.sendWindowUpdate(nil, int(f.Length)-wrote)
return sc.countError("body_write_err", streamError(id, ErrCodeStreamClosed)) return sc.countError("body_write_err", streamError(id, ErrCodeStreamClosed))
} }
if wrote != len(data) { if wrote != len(data) {
@ -1838,19 +1857,27 @@ func (st *stream) copyTrailersToHandlerRequest() {
} }
} }
// onReadTimeout is run on its own goroutine (from time.AfterFunc)
// when the stream's ReadTimeout has fired.
func (st *stream) onReadTimeout() {
// Wrap the ErrDeadlineExceeded to avoid callers depending on us
// returning the bare error.
st.body.CloseWithError(fmt.Errorf("%w", os.ErrDeadlineExceeded))
}
// onWriteTimeout is run on its own goroutine (from time.AfterFunc) // onWriteTimeout is run on its own goroutine (from time.AfterFunc)
// when the stream's WriteTimeout has fired. // when the stream's WriteTimeout has fired.
func (st *stream) onWriteTimeout() { func (st *stream) onWriteTimeout() {
st.sc.writeFrameFromHandler(FrameWriteRequest{write: streamError(st.id, ErrCodeInternal)}) st.sc.writeFrameFromHandler(FrameWriteRequest{write: StreamError{
StreamID: st.id,
Code: ErrCodeInternal,
Cause: os.ErrDeadlineExceeded,
}})
} }
func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error { func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
sc.serveG.check() sc.serveG.check()
id := f.StreamID id := f.StreamID
if sc.inGoAway {
// Ignore.
return nil
}
// http://tools.ietf.org/html/rfc7540#section-5.1.1 // http://tools.ietf.org/html/rfc7540#section-5.1.1
// Streams initiated by a client MUST use odd-numbered stream // Streams initiated by a client MUST use odd-numbered stream
// identifiers. [...] An endpoint that receives an unexpected // identifiers. [...] An endpoint that receives an unexpected
@ -1953,6 +1980,9 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
// (in Go 1.8), though. That's a more sane option anyway. // (in Go 1.8), though. That's a more sane option anyway.
if sc.hs.ReadTimeout != 0 { if sc.hs.ReadTimeout != 0 {
sc.conn.SetReadDeadline(time.Time{}) sc.conn.SetReadDeadline(time.Time{})
if st.body != nil {
st.readDeadline = time.AfterFunc(sc.hs.ReadTimeout, st.onReadTimeout)
}
} }
go sc.runHandler(rw, req, handler) go sc.runHandler(rw, req, handler)
@ -2021,9 +2051,6 @@ func (sc *serverConn) checkPriority(streamID uint32, p PriorityParam) error {
} }
func (sc *serverConn) processPriority(f *PriorityFrame) error { func (sc *serverConn) processPriority(f *PriorityFrame) error {
if sc.inGoAway {
return nil
}
if err := sc.checkPriority(f.StreamID, f.PriorityParam); err != nil { if err := sc.checkPriority(f.StreamID, f.PriorityParam); err != nil {
return err return err
} }
@ -2322,39 +2349,24 @@ func (sc *serverConn) noteBodyReadFromHandler(st *stream, n int, err error) {
func (sc *serverConn) noteBodyRead(st *stream, n int) { func (sc *serverConn) noteBodyRead(st *stream, n int) {
sc.serveG.check() sc.serveG.check()
sc.sendWindowUpdate(nil) // conn-level sc.sendWindowUpdate(nil, n) // conn-level
if st.state != stateHalfClosedRemote && st.state != stateClosed { if st.state != stateHalfClosedRemote && st.state != stateClosed {
// Don't send this WINDOW_UPDATE if the stream is closed // Don't send this WINDOW_UPDATE if the stream is closed
// remotely. // remotely.
sc.sendWindowUpdate(st) sc.sendWindowUpdate(st, n)
} }
} }
// st may be nil for conn-level // st may be nil for conn-level
func (sc *serverConn) sendWindowUpdate(st *stream) { func (sc *serverConn) sendWindowUpdate(st *stream, n int) {
sc.serveG.check() sc.serveG.check()
var n int32
if st == nil {
if avail, windowSize := sc.inflow.available(), sc.srv.initialConnRecvWindowSize(); avail > windowSize/2 {
return
} else {
n = windowSize - avail
}
} else {
if avail, windowSize := st.inflow.available(), sc.srv.initialStreamRecvWindowSize(); avail > windowSize/2 {
return
} else {
n = windowSize - avail
}
}
// "The legal range for the increment to the flow control // "The legal range for the increment to the flow control
// window is 1 to 2^31-1 (2,147,483,647) octets." // window is 1 to 2^31-1 (2,147,483,647) octets."
// A Go Read call on 64-bit machines could in theory read // A Go Read call on 64-bit machines could in theory read
// a larger Read than this. Very unlikely, but we handle it here // a larger Read than this. Very unlikely, but we handle it here
// rather than elsewhere for now. // rather than elsewhere for now.
const maxUint31 = 1<<31 - 1 const maxUint31 = 1<<31 - 1
for n >= maxUint31 { for n > maxUint31 {
sc.sendWindowUpdate32(st, maxUint31) sc.sendWindowUpdate32(st, maxUint31)
n -= maxUint31 n -= maxUint31
} }
@ -2474,7 +2486,15 @@ type responseWriterState struct {
type chunkWriter struct{ rws *responseWriterState } type chunkWriter struct{ rws *responseWriterState }
func (cw chunkWriter) Write(p []byte) (n int, err error) { return cw.rws.writeChunk(p) } func (cw chunkWriter) Write(p []byte) (n int, err error) {
n, err = cw.rws.writeChunk(p)
if err == errStreamClosed {
// If writing failed because the stream has been closed,
// return the reason it was closed.
err = cw.rws.stream.closeErr
}
return n, err
}
func (rws *responseWriterState) hasTrailers() bool { return len(rws.trailers) > 0 } func (rws *responseWriterState) hasTrailers() bool { return len(rws.trailers) > 0 }
@ -2668,23 +2688,85 @@ func (rws *responseWriterState) promoteUndeclaredTrailers() {
} }
} }
func (w *responseWriter) SetReadDeadline(deadline time.Time) error {
st := w.rws.stream
if !deadline.IsZero() && deadline.Before(time.Now()) {
// If we're setting a deadline in the past, reset the stream immediately
// so writes after SetWriteDeadline returns will fail.
st.onReadTimeout()
return nil
}
w.rws.conn.sendServeMsg(func(sc *serverConn) {
if st.readDeadline != nil {
if !st.readDeadline.Stop() {
// Deadline already exceeded, or stream has been closed.
return
}
}
if deadline.IsZero() {
st.readDeadline = nil
} else if st.readDeadline == nil {
st.readDeadline = time.AfterFunc(deadline.Sub(time.Now()), st.onReadTimeout)
} else {
st.readDeadline.Reset(deadline.Sub(time.Now()))
}
})
return nil
}
func (w *responseWriter) SetWriteDeadline(deadline time.Time) error {
st := w.rws.stream
if !deadline.IsZero() && deadline.Before(time.Now()) {
// If we're setting a deadline in the past, reset the stream immediately
// so writes after SetWriteDeadline returns will fail.
st.onWriteTimeout()
return nil
}
w.rws.conn.sendServeMsg(func(sc *serverConn) {
if st.writeDeadline != nil {
if !st.writeDeadline.Stop() {
// Deadline already exceeded, or stream has been closed.
return
}
}
if deadline.IsZero() {
st.writeDeadline = nil
} else if st.writeDeadline == nil {
st.writeDeadline = time.AfterFunc(deadline.Sub(time.Now()), st.onWriteTimeout)
} else {
st.writeDeadline.Reset(deadline.Sub(time.Now()))
}
})
return nil
}
func (w *responseWriter) Flush() { func (w *responseWriter) Flush() {
w.FlushError()
}
func (w *responseWriter) FlushError() error {
rws := w.rws rws := w.rws
if rws == nil { if rws == nil {
panic("Header called after Handler finished") panic("Header called after Handler finished")
} }
var err error
if rws.bw.Buffered() > 0 { if rws.bw.Buffered() > 0 {
if err := rws.bw.Flush(); err != nil { err = rws.bw.Flush()
// Ignore the error. The frame writer already knows.
return
}
} else { } else {
// The bufio.Writer won't call chunkWriter.Write // The bufio.Writer won't call chunkWriter.Write
// (writeChunk with zero bytes, so we have to do it // (writeChunk with zero bytes, so we have to do it
// ourselves to force the HTTP response header and/or // ourselves to force the HTTP response header and/or
// final DATA frame (with END_STREAM) to be sent. // final DATA frame (with END_STREAM) to be sent.
rws.writeChunk(nil) _, err = chunkWriter{rws}.Write(nil)
if err == nil {
select {
case <-rws.stream.cw:
err = rws.stream.closeErr
default:
}
}
} }
return err
} }
func (w *responseWriter) CloseNotify() <-chan bool { func (w *responseWriter) CloseNotify() <-chan bool {

View File

@ -16,6 +16,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"io/fs"
"log" "log"
"math" "math"
mathrand "math/rand" mathrand "math/rand"
@ -501,6 +502,15 @@ func authorityAddr(scheme string, authority string) (addr string) {
return net.JoinHostPort(host, port) return net.JoinHostPort(host, port)
} }
var retryBackoffHook func(time.Duration) *time.Timer
func backoffNewTimer(d time.Duration) *time.Timer {
if retryBackoffHook != nil {
return retryBackoffHook(d)
}
return time.NewTimer(d)
}
// RoundTripOpt is like RoundTrip, but takes options. // RoundTripOpt is like RoundTrip, but takes options.
func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Response, error) { func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Response, error) {
if !(req.URL.Scheme == "https" || (req.URL.Scheme == "http" && t.AllowHTTP)) { if !(req.URL.Scheme == "https" || (req.URL.Scheme == "http" && t.AllowHTTP)) {
@ -526,11 +536,14 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Res
} }
backoff := float64(uint(1) << (uint(retry) - 1)) backoff := float64(uint(1) << (uint(retry) - 1))
backoff += backoff * (0.1 * mathrand.Float64()) backoff += backoff * (0.1 * mathrand.Float64())
d := time.Second * time.Duration(backoff)
timer := backoffNewTimer(d)
select { select {
case <-time.After(time.Second * time.Duration(backoff)): case <-timer.C:
t.vlogf("RoundTrip retrying after failure: %v", err) t.vlogf("RoundTrip retrying after failure: %v", err)
continue continue
case <-req.Context().Done(): case <-req.Context().Done():
timer.Stop()
err = req.Context().Err() err = req.Context().Err()
} }
} }
@ -1075,7 +1088,7 @@ var errRequestCanceled = errors.New("net/http: request canceled")
func commaSeparatedTrailers(req *http.Request) (string, error) { func commaSeparatedTrailers(req *http.Request) (string, error) {
keys := make([]string, 0, len(req.Trailer)) keys := make([]string, 0, len(req.Trailer))
for k := range req.Trailer { for k := range req.Trailer {
k = http.CanonicalHeaderKey(k) k = canonicalHeader(k)
switch k { switch k {
case "Transfer-Encoding", "Trailer", "Content-Length": case "Transfer-Encoding", "Trailer", "Content-Length":
return "", fmt.Errorf("invalid Trailer key %q", k) return "", fmt.Errorf("invalid Trailer key %q", k)
@ -1612,7 +1625,7 @@ func (cs *clientStream) writeRequestBody(req *http.Request) (err error) {
var sawEOF bool var sawEOF bool
for !sawEOF { for !sawEOF {
n, err := body.Read(buf[:len(buf)]) n, err := body.Read(buf)
if hasContentLen { if hasContentLen {
remainLen -= int64(n) remainLen -= int64(n)
if remainLen == 0 && err == nil { if remainLen == 0 && err == nil {
@ -1915,7 +1928,7 @@ func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trail
// 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) {
name, ascii := asciiToLower(name) name, ascii := lowerHeader(name)
if !ascii { if !ascii {
// Skip writing invalid headers. Per RFC 7540, Section 8.1.2, header // Skip writing invalid headers. Per RFC 7540, Section 8.1.2, header
// field names have to be ASCII characters (just as in HTTP/1.x). // field names have to be ASCII characters (just as in HTTP/1.x).
@ -1968,7 +1981,7 @@ func (cc *ClientConn) encodeTrailers(trailer http.Header) ([]byte, error) {
} }
for k, vv := range trailer { for k, vv := range trailer {
lowKey, ascii := asciiToLower(k) lowKey, ascii := lowerHeader(k)
if !ascii { if !ascii {
// Skip writing invalid headers. Per RFC 7540, Section 8.1.2, header // Skip writing invalid headers. Per RFC 7540, Section 8.1.2, header
// field names have to be ASCII characters (just as in HTTP/1.x). // field names have to be ASCII characters (just as in HTTP/1.x).
@ -2301,7 +2314,7 @@ func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFra
Status: status + " " + http.StatusText(statusCode), Status: status + " " + http.StatusText(statusCode),
} }
for _, hf := range regularFields { for _, hf := range regularFields {
key := http.CanonicalHeaderKey(hf.Name) key := canonicalHeader(hf.Name)
if key == "Trailer" { if key == "Trailer" {
t := res.Trailer t := res.Trailer
if t == nil { if t == nil {
@ -2309,7 +2322,7 @@ func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFra
res.Trailer = t res.Trailer = t
} }
foreachHeaderElement(hf.Value, func(v string) { foreachHeaderElement(hf.Value, func(v string) {
t[http.CanonicalHeaderKey(v)] = nil t[canonicalHeader(v)] = nil
}) })
} else { } else {
vv := header[key] vv := header[key]
@ -2414,7 +2427,7 @@ func (rl *clientConnReadLoop) processTrailers(cs *clientStream, f *MetaHeadersFr
trailer := make(http.Header) trailer := make(http.Header)
for _, hf := range f.RegularFields() { for _, hf := range f.RegularFields() {
key := http.CanonicalHeaderKey(hf.Name) key := canonicalHeader(hf.Name)
trailer[key] = append(trailer[key], hf.Value) trailer[key] = append(trailer[key], hf.Value)
} }
cs.trailer = trailer cs.trailer = trailer
@ -2985,7 +2998,11 @@ func (gz *gzipReader) Read(p []byte) (n int, err error) {
} }
func (gz *gzipReader) Close() error { func (gz *gzipReader) Close() error {
return gz.body.Close() if err := gz.body.Close(); err != nil {
return err
}
gz.zerr = fs.ErrClosed
return nil
} }
type errorReader struct{ err error } type errorReader struct{ err error }

4
vendor/modules.txt vendored
View File

@ -587,7 +587,7 @@ github.com/onsi/ginkgo/reporters/stenographer
github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable github.com/onsi/ginkgo/reporters/stenographer/support/go-colorable
github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty github.com/onsi/ginkgo/reporters/stenographer/support/go-isatty
github.com/onsi/ginkgo/types github.com/onsi/ginkgo/types
# github.com/onsi/gomega v1.24.0 # github.com/onsi/gomega v1.24.1
## explicit; go 1.18 ## explicit; go 1.18
github.com/onsi/gomega github.com/onsi/gomega
github.com/onsi/gomega/format github.com/onsi/gomega/format
@ -804,7 +804,7 @@ golang.org/x/crypto/ssh/knownhosts
# golang.org/x/mod v0.6.0 # golang.org/x/mod v0.6.0
## explicit; go 1.17 ## explicit; go 1.17
golang.org/x/mod/semver golang.org/x/mod/semver
# golang.org/x/net v0.1.0 # golang.org/x/net v0.2.0
## explicit; go 1.17 ## explicit; go 1.17
golang.org/x/net/context golang.org/x/net/context
golang.org/x/net/html golang.org/x/net/html