bump golang.org/x/net to v0.55.0
Signed-off-by: Sopho Merkviladze <smerkviladze@mirantis.com>
This commit is contained in:
+21
-17
@@ -5,9 +5,11 @@
|
||||
package html
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
a "golang.org/x/net/html/atom"
|
||||
@@ -328,6 +330,14 @@ func (p *parser) addText(text string) {
|
||||
})
|
||||
}
|
||||
|
||||
func attrCompare(a, b Attribute) int {
|
||||
return cmp.Or(
|
||||
cmp.Compare(a.Namespace, b.Namespace),
|
||||
cmp.Compare(a.Key, b.Key),
|
||||
cmp.Compare(a.Val, b.Val),
|
||||
)
|
||||
}
|
||||
|
||||
// addElement adds a child element based on the current token.
|
||||
func (p *parser) addElement() {
|
||||
p.addChild(&Node{
|
||||
@@ -343,6 +353,10 @@ func (p *parser) addFormattingElement() {
|
||||
tagAtom, attr := p.tok.DataAtom, p.tok.Attr
|
||||
p.addElement()
|
||||
|
||||
// In order to optimize the search, we need the attributes to be sorted, so we
|
||||
// can just use slices.Equal.
|
||||
slices.SortFunc(attr, attrCompare)
|
||||
|
||||
// Implement the Noah's Ark clause, but with three per family instead of two.
|
||||
identicalElements := 0
|
||||
findIdenticalElements:
|
||||
@@ -360,19 +374,7 @@ findIdenticalElements:
|
||||
if n.DataAtom != tagAtom {
|
||||
continue
|
||||
}
|
||||
if len(n.Attr) != len(attr) {
|
||||
continue
|
||||
}
|
||||
compareAttributes:
|
||||
for _, t0 := range n.Attr {
|
||||
for _, t1 := range attr {
|
||||
if t0.Key == t1.Key && t0.Namespace == t1.Namespace && t0.Val == t1.Val {
|
||||
// Found a match for this attribute, continue with the next attribute.
|
||||
continue compareAttributes
|
||||
}
|
||||
}
|
||||
// If we get here, there is no attribute that matches a.
|
||||
// Therefore the element is not identical to the new one.
|
||||
if !slices.Equal(n.Attr, attr) {
|
||||
continue findIdenticalElements
|
||||
}
|
||||
|
||||
@@ -382,7 +384,11 @@ findIdenticalElements:
|
||||
}
|
||||
}
|
||||
|
||||
p.afe = append(p.afe, p.top())
|
||||
// Sort the attributes to optimize future identical-element searches.
|
||||
top := p.top()
|
||||
slices.SortFunc(top.Attr, attrCompare)
|
||||
|
||||
p.afe = append(p.afe, top)
|
||||
}
|
||||
|
||||
// Section 12.2.4.3.
|
||||
@@ -1372,8 +1378,6 @@ func (p *parser) inBodyEndTagFormatting(tagAtom a.Atom, tagName string) {
|
||||
}
|
||||
|
||||
// inBodyEndTagOther performs the "any other end tag" algorithm for inBodyIM.
|
||||
// "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
|
||||
func (p *parser) inBodyEndTagOther(tagAtom a.Atom, tagName string) {
|
||||
for i := len(p.oe) - 1; i >= 0; i-- {
|
||||
// Two element nodes have the same tag if they have the same Data (a
|
||||
@@ -1383,7 +1387,7 @@ func (p *parser) inBodyEndTagOther(tagAtom a.Atom, tagName string) {
|
||||
// Uncommon (custom) tags get a zero DataAtom.
|
||||
//
|
||||
// The if condition here is equivalent to (p.oe[i].Data == tagName).
|
||||
if (p.oe[i].DataAtom == tagAtom) &&
|
||||
if p.oe[i].Namespace == "" && (p.oe[i].DataAtom == tagAtom) &&
|
||||
((tagAtom != 0) || (p.oe[i].Data == tagName)) {
|
||||
p.oe = p.oe[:i]
|
||||
break
|
||||
|
||||
+29
-6
@@ -113,14 +113,14 @@ func render1(w writer, n *Node) error {
|
||||
if _, err := w.WriteString(" PUBLIC "); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := writeQuoted(w, p); err != nil {
|
||||
if err := writeDoctypeQuoted(w, p); err != nil {
|
||||
return err
|
||||
}
|
||||
if s != "" {
|
||||
if err := w.WriteByte(' '); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := writeQuoted(w, s); err != nil {
|
||||
if err := writeDoctypeQuoted(w, s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -128,7 +128,7 @@ func render1(w writer, n *Node) error {
|
||||
if _, err := w.WriteString(" SYSTEM "); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := writeQuoted(w, s); err != nil {
|
||||
if err := writeDoctypeQuoted(w, s); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -243,27 +243,50 @@ func childTextNodesAreLiteral(n *Node) bool {
|
||||
if n.Namespace != "" {
|
||||
return false
|
||||
}
|
||||
|
||||
switch n.Data {
|
||||
case "iframe", "noembed", "noframes", "noscript", "plaintext", "script", "style", "xmp":
|
||||
// We need to check if n is a node that was fostered from a HTML namespace
|
||||
// into a non-HTML namespace (in which case, different rules apply to it).
|
||||
// We do this by walking up the tree until we find a node with a non-empty
|
||||
// namespace. If we find such a node, we also have to check if it's
|
||||
// an HTML integration point. If it isn't, then the node we're currently
|
||||
// looking at is foster-parented and we should return false.
|
||||
for p := n.Parent; p != nil; p = p.Parent {
|
||||
if p.Namespace != "" {
|
||||
if !htmlIntegrationPoint(p) {
|
||||
return false
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// writeQuoted writes s to w surrounded by quotes. Normally it will use double
|
||||
// writeDoctypeQuoted writes s to w surrounded by quotes. Normally it will use double
|
||||
// quotes, but if s contains a double quote, it will use single quotes.
|
||||
// If s contains any '>' characters, they are replaced with > in order
|
||||
// to prevent triggering an abrupt-doctype-system-identifier parse error.
|
||||
// It is used for writing the identifiers in a doctype declaration.
|
||||
// In valid HTML, they can't contain both types of quotes.
|
||||
func writeQuoted(w writer, s string) error {
|
||||
func writeDoctypeQuoted(w writer, s string) error {
|
||||
var q byte = '"'
|
||||
if strings.Contains(s, `"`) {
|
||||
// parseDoctype will never produce a Node with both quote types, but a user
|
||||
// can construct their own Node that violates this assumption.
|
||||
if strings.Contains(s, `'`) {
|
||||
return errors.New("doctype contains both quote types, cannot be safely rendered")
|
||||
}
|
||||
q = '\''
|
||||
}
|
||||
if err := w.WriteByte(q); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := w.WriteString(s); err != nil {
|
||||
if _, err := w.WriteString(strings.ReplaceAll(s, ">", ">")); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := w.WriteByte(q); err != nil {
|
||||
|
||||
+9
-4
@@ -156,6 +156,7 @@ type Tokenizer struct {
|
||||
// incremented on each call to TagAttr.
|
||||
pendingAttr [2]span
|
||||
attr [][2]span
|
||||
attrNames map[string]bool
|
||||
nAttrReturned int
|
||||
// rawTag is the "script" in "</script>" that closes the next token. If
|
||||
// non-empty, the subsequent call to Next will return a raw or RCDATA text
|
||||
@@ -867,6 +868,7 @@ func (z *Tokenizer) readStartTag() TokenType {
|
||||
func (z *Tokenizer) readTag(saveAttr bool) {
|
||||
z.attr = z.attr[:0]
|
||||
z.nAttrReturned = 0
|
||||
clear(z.attrNames)
|
||||
// Read the tag name and attribute key/value pairs.
|
||||
z.readTagName()
|
||||
if z.skipWhiteSpace(); z.err != nil {
|
||||
@@ -880,9 +882,11 @@ func (z *Tokenizer) readTag(saveAttr bool) {
|
||||
z.raw.end--
|
||||
z.readTagAttrKey()
|
||||
z.readTagAttrVal()
|
||||
// Save pendingAttr if saveAttr and that attribute has a non-empty key.
|
||||
if saveAttr && z.pendingAttr[0].start != z.pendingAttr[0].end {
|
||||
// Save pendingAttr if saveAttr and that attribute has a non-empty key, and the key hasn't been seen before.
|
||||
key := strings.ToLower(string(z.buf[z.pendingAttr[0].start:z.pendingAttr[0].end]))
|
||||
if saveAttr && z.pendingAttr[0].start != z.pendingAttr[0].end && !z.attrNames[key] {
|
||||
z.attr = append(z.attr, z.pendingAttr)
|
||||
z.attrNames[key] = true
|
||||
}
|
||||
if z.skipWhiteSpace(); z.err != nil {
|
||||
break
|
||||
@@ -1273,8 +1277,9 @@ func NewTokenizer(r io.Reader) *Tokenizer {
|
||||
// The input is assumed to be UTF-8 encoded.
|
||||
func NewTokenizerFragment(r io.Reader, contextTag string) *Tokenizer {
|
||||
z := &Tokenizer{
|
||||
r: r,
|
||||
buf: make([]byte, 0, 4096),
|
||||
r: r,
|
||||
buf: make([]byte, 0, 4096),
|
||||
attrNames: make(map[string]bool),
|
||||
}
|
||||
if contextTag != "" {
|
||||
switch s := strings.ToLower(contextTag); s {
|
||||
|
||||
-21
@@ -2657,21 +2657,6 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
// TrailerPrefix is a magic prefix for ResponseWriter.Header map keys
|
||||
// that, if present, signals that the map entry is actually for
|
||||
// the response trailers, and not the response headers. The prefix
|
||||
// is stripped after the ServeHTTP call finishes and the values are
|
||||
// sent in the trailers.
|
||||
//
|
||||
// This mechanism is intended only for trailers that are not known
|
||||
// prior to the headers being written. If the set of trailers is fixed
|
||||
// or known before the header is written, the normal Go trailers mechanism
|
||||
// is preferred:
|
||||
//
|
||||
// https://golang.org/pkg/net/http/#ResponseWriter
|
||||
// https://golang.org/pkg/net/http/#example_ResponseWriter_trailers
|
||||
const TrailerPrefix = "Trailer:"
|
||||
|
||||
// promoteUndeclaredTrailers permits http.Handlers to set trailers
|
||||
// after the header has already been flushed. Because the Go
|
||||
// ResponseWriter interface has no way to set Trailers (only the
|
||||
@@ -2948,12 +2933,6 @@ func (w *responseWriter) handlerDone() {
|
||||
responseWriterStatePool.Put(rws)
|
||||
}
|
||||
|
||||
// Push errors.
|
||||
var (
|
||||
ErrRecursivePush = errors.New("http2: recursive push not allowed")
|
||||
ErrPushLimitReached = errors.New("http2: push would exceed peer's SETTINGS_MAX_CONCURRENT_STREAMS")
|
||||
)
|
||||
|
||||
var _ http.Pusher = (*responseWriter)(nil)
|
||||
|
||||
func (w *responseWriter) Push(target string, opts *http.PushOptions) error {
|
||||
|
||||
+22
@@ -6,11 +6,33 @@ package http2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
// TrailerPrefix is a magic prefix for ResponseWriter.Header map keys
|
||||
// that, if present, signals that the map entry is actually for
|
||||
// the response trailers, and not the response headers. The prefix
|
||||
// is stripped after the ServeHTTP call finishes and the values are
|
||||
// sent in the trailers.
|
||||
//
|
||||
// This mechanism is intended only for trailers that are not known
|
||||
// prior to the headers being written. If the set of trailers is fixed
|
||||
// or known before the header is written, the normal Go trailers mechanism
|
||||
// is preferred:
|
||||
//
|
||||
// https://golang.org/pkg/net/http/#ResponseWriter
|
||||
// https://golang.org/pkg/net/http/#example_ResponseWriter_trailers
|
||||
const TrailerPrefix = "Trailer:"
|
||||
|
||||
// Push errors.
|
||||
var (
|
||||
ErrRecursivePush = errors.New("http2: recursive push not allowed")
|
||||
ErrPushLimitReached = errors.New("http2: push would exceed peer's SETTINGS_MAX_CONCURRENT_STREAMS")
|
||||
)
|
||||
|
||||
// ConfigureServer adds HTTP/2 support to a net/http Server.
|
||||
//
|
||||
// The configuration conf may be nil.
|
||||
|
||||
+40
@@ -159,3 +159,43 @@ type FrameWriteRequest struct {
|
||||
// to avoid duplicating an exported symbol across two files,
|
||||
// but the changes required to make this work are fairly large.
|
||||
}
|
||||
|
||||
func (wr FrameWriteRequest) StreamID() uint32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (wr FrameWriteRequest) DataSize() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (wr FrameWriteRequest) Consume(n int32) (FrameWriteRequest, FrameWriteRequest, int) {
|
||||
return FrameWriteRequest{}, FrameWriteRequest{}, 0
|
||||
}
|
||||
|
||||
func (wr FrameWriteRequest) String() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// NewPriorityWriteScheduler is deprecated.
|
||||
//
|
||||
// Deprecated: User-provided write schedulers are deprecated.
|
||||
func NewPriorityWriteScheduler(cfg *PriorityWriteSchedulerConfig) WriteScheduler {
|
||||
return unsupportedWriteScheduler{}
|
||||
}
|
||||
|
||||
// NewRandomWriteScheduler is deprecated.
|
||||
//
|
||||
// Deprecated: User-provided write schedulers are deprecated.
|
||||
func NewRandomWriteScheduler() WriteScheduler {
|
||||
return unsupportedWriteScheduler{}
|
||||
}
|
||||
|
||||
type unsupportedWriteScheduler struct{}
|
||||
|
||||
func (unsupportedWriteScheduler) OpenStream(streamID uint32, options OpenStreamOptions) {}
|
||||
func (unsupportedWriteScheduler) CloseStream(streamID uint32) {}
|
||||
func (unsupportedWriteScheduler) AdjustStream(streamID uint32, priority PriorityParam) {}
|
||||
func (unsupportedWriteScheduler) Push(wr FrameWriteRequest) {}
|
||||
func (unsupportedWriteScheduler) Pop() (wr FrameWriteRequest, ok bool) {
|
||||
return FrameWriteRequest{}, false
|
||||
}
|
||||
|
||||
-34
@@ -399,27 +399,6 @@ func (sew stickyErrWriter) Write(p []byte) (n int, err error) {
|
||||
return n, err
|
||||
}
|
||||
|
||||
// noCachedConnError is the concrete type of ErrNoCachedConn, which
|
||||
// needs to be detected by net/http regardless of whether it's its
|
||||
// bundled version (in h2_bundle.go with a rewritten type name) or
|
||||
// from a user's x/net/http2. As such, as it has a unique method name
|
||||
// (IsHTTP2NoCachedConnError) that net/http sniffs for via func
|
||||
// isNoCachedConnError.
|
||||
type noCachedConnError struct{}
|
||||
|
||||
func (noCachedConnError) IsHTTP2NoCachedConnError() {}
|
||||
func (noCachedConnError) Error() string { return "http2: no cached connection was available" }
|
||||
|
||||
// isNoCachedConnError reports whether err is of type noCachedConnError
|
||||
// or its equivalent renamed type in net/http2's h2_bundle.go. Both types
|
||||
// may coexist in the same running program.
|
||||
func isNoCachedConnError(err error) bool {
|
||||
_, ok := err.(interface{ IsHTTP2NoCachedConnError() })
|
||||
return ok
|
||||
}
|
||||
|
||||
var ErrNoCachedConn error = noCachedConnError{}
|
||||
|
||||
func (t *Transport) roundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Response, error) {
|
||||
switch req.URL.Scheme {
|
||||
case "https":
|
||||
@@ -1786,19 +1765,6 @@ func (cc *ClientConn) readLoop() {
|
||||
}
|
||||
}
|
||||
|
||||
// GoAwayError is returned by the Transport when the server closes the
|
||||
// TCP connection after sending a GOAWAY frame.
|
||||
type GoAwayError struct {
|
||||
LastStreamID uint32
|
||||
ErrCode ErrCode
|
||||
DebugData string
|
||||
}
|
||||
|
||||
func (e GoAwayError) Error() string {
|
||||
return fmt.Sprintf("http2: server sent GOAWAY and closed the connection; LastStreamID=%v, ErrCode=%v, debug=%q",
|
||||
e.LastStreamID, e.ErrCode, e.DebugData)
|
||||
}
|
||||
|
||||
func isEOFOrNetReadError(err error) bool {
|
||||
if err == io.EOF {
|
||||
return true
|
||||
|
||||
+34
@@ -411,3 +411,37 @@ func (t *Transport) dialTLSWithContext(ctx context.Context, network, addr string
|
||||
tlsCn := cn.(*tls.Conn) // DialContext comment promises this will always succeed
|
||||
return tlsCn, nil
|
||||
}
|
||||
|
||||
// GoAwayError is returned by the Transport when the server closes the
|
||||
// TCP connection after sending a GOAWAY frame.
|
||||
type GoAwayError struct {
|
||||
LastStreamID uint32
|
||||
ErrCode ErrCode
|
||||
DebugData string
|
||||
}
|
||||
|
||||
func (e GoAwayError) Error() string {
|
||||
return fmt.Sprintf("http2: server sent GOAWAY and closed the connection; LastStreamID=%v, ErrCode=%v, debug=%q",
|
||||
e.LastStreamID, e.ErrCode, e.DebugData)
|
||||
}
|
||||
|
||||
// noCachedConnError is the concrete type of ErrNoCachedConn, which
|
||||
// needs to be detected by net/http regardless of whether it's its
|
||||
// bundled version (in h2_bundle.go with a rewritten type name) or
|
||||
// from a user's x/net/http2. As such, as it has a unique method name
|
||||
// (IsHTTP2NoCachedConnError) that net/http sniffs for via func
|
||||
// isNoCachedConnError.
|
||||
type noCachedConnError struct{}
|
||||
|
||||
func (noCachedConnError) IsHTTP2NoCachedConnError() {}
|
||||
func (noCachedConnError) Error() string { return "http2: no cached connection was available" }
|
||||
|
||||
// isNoCachedConnError reports whether err is of type noCachedConnError
|
||||
// or its equivalent renamed type in net/http2's h2_bundle.go. Both types
|
||||
// may coexist in the same running program.
|
||||
func isNoCachedConnError(err error) bool {
|
||||
_, ok := err.(interface{ IsHTTP2NoCachedConnError() })
|
||||
return ok
|
||||
}
|
||||
|
||||
var ErrNoCachedConn error = noCachedConnError{}
|
||||
|
||||
+41
@@ -47,3 +47,44 @@ type OpenStreamOptions struct {
|
||||
// priority is used to set the priority of the newly opened stream.
|
||||
priority PriorityParam
|
||||
}
|
||||
|
||||
// PriorityWriteSchedulerConfig configures a priorityWriteScheduler.
|
||||
//
|
||||
// Deprecated: User-provided write schedulers are deprecated.
|
||||
type PriorityWriteSchedulerConfig struct {
|
||||
// MaxClosedNodesInTree controls the maximum number of closed streams to
|
||||
// retain in the priority tree. Setting this to zero saves a small amount
|
||||
// of memory at the cost of performance.
|
||||
//
|
||||
// See RFC 7540, Section 5.3.4:
|
||||
// "It is possible for a stream to become closed while prioritization
|
||||
// information ... is in transit. ... This potentially creates suboptimal
|
||||
// prioritization, since the stream could be given a priority that is
|
||||
// different from what is intended. To avoid these problems, an endpoint
|
||||
// SHOULD retain stream prioritization state for a period after streams
|
||||
// become closed. The longer state is retained, the lower the chance that
|
||||
// streams are assigned incorrect or default priority values."
|
||||
MaxClosedNodesInTree int
|
||||
|
||||
// MaxIdleNodesInTree controls the maximum number of idle streams to
|
||||
// retain in the priority tree. Setting this to zero saves a small amount
|
||||
// of memory at the cost of performance.
|
||||
//
|
||||
// See RFC 7540, Section 5.3.4:
|
||||
// Similarly, streams that are in the "idle" state can be assigned
|
||||
// priority or become a parent of other streams. This allows for the
|
||||
// creation of a grouping node in the dependency tree, which enables
|
||||
// more flexible expressions of priority. Idle streams begin with a
|
||||
// default priority (Section 5.3.5).
|
||||
MaxIdleNodesInTree int
|
||||
|
||||
// ThrottleOutOfOrderWrites enables write throttling to help ensure that
|
||||
// data is delivered in priority order. This works around a race where
|
||||
// stream B depends on stream A and both streams are about to call Write
|
||||
// to queue DATA frames. If B wins the race, a naive scheduler would eagerly
|
||||
// write as much data from B as possible, but this is suboptimal because A
|
||||
// is a higher-priority stream. With throttling enabled, we write a small
|
||||
// amount of data from B to minimize the amount of bandwidth that B can
|
||||
// steal from A.
|
||||
ThrottleOutOfOrderWrites bool
|
||||
}
|
||||
|
||||
-41
@@ -15,47 +15,6 @@ import (
|
||||
// RFC 7540, Section 5.3.5: the default weight is 16.
|
||||
const priorityDefaultWeightRFC7540 = 15 // 16 = 15 + 1
|
||||
|
||||
// PriorityWriteSchedulerConfig configures a priorityWriteScheduler.
|
||||
//
|
||||
// Deprecated: User-provided write schedulers are deprecated.
|
||||
type PriorityWriteSchedulerConfig struct {
|
||||
// MaxClosedNodesInTree controls the maximum number of closed streams to
|
||||
// retain in the priority tree. Setting this to zero saves a small amount
|
||||
// of memory at the cost of performance.
|
||||
//
|
||||
// See RFC 7540, Section 5.3.4:
|
||||
// "It is possible for a stream to become closed while prioritization
|
||||
// information ... is in transit. ... This potentially creates suboptimal
|
||||
// prioritization, since the stream could be given a priority that is
|
||||
// different from what is intended. To avoid these problems, an endpoint
|
||||
// SHOULD retain stream prioritization state for a period after streams
|
||||
// become closed. The longer state is retained, the lower the chance that
|
||||
// streams are assigned incorrect or default priority values."
|
||||
MaxClosedNodesInTree int
|
||||
|
||||
// MaxIdleNodesInTree controls the maximum number of idle streams to
|
||||
// retain in the priority tree. Setting this to zero saves a small amount
|
||||
// of memory at the cost of performance.
|
||||
//
|
||||
// See RFC 7540, Section 5.3.4:
|
||||
// Similarly, streams that are in the "idle" state can be assigned
|
||||
// priority or become a parent of other streams. This allows for the
|
||||
// creation of a grouping node in the dependency tree, which enables
|
||||
// more flexible expressions of priority. Idle streams begin with a
|
||||
// default priority (Section 5.3.5).
|
||||
MaxIdleNodesInTree int
|
||||
|
||||
// ThrottleOutOfOrderWrites enables write throttling to help ensure that
|
||||
// data is delivered in priority order. This works around a race where
|
||||
// stream B depends on stream A and both streams are about to call Write
|
||||
// to queue DATA frames. If B wins the race, a naive scheduler would eagerly
|
||||
// write as much data from B as possible, but this is suboptimal because A
|
||||
// is a higher-priority stream. With throttling enabled, we write a small
|
||||
// amount of data from B to minimize the amount of bandwidth that B can
|
||||
// steal from A.
|
||||
ThrottleOutOfOrderWrites bool
|
||||
}
|
||||
|
||||
// NewPriorityWriteScheduler constructs a WriteScheduler that schedules
|
||||
// frames by following HTTP/2 priorities as described in RFC 7540 Section 5.3.
|
||||
// If cfg is nil, default options are used.
|
||||
|
||||
Vendored
+1
-1
@@ -1318,7 +1318,7 @@ golang.org/x/mod/internal/lazyregexp
|
||||
golang.org/x/mod/module
|
||||
golang.org/x/mod/semver
|
||||
golang.org/x/mod/sumdb/note
|
||||
# golang.org/x/net v0.54.0
|
||||
# golang.org/x/net v0.55.0
|
||||
## explicit; go 1.25.0
|
||||
golang.org/x/net/html
|
||||
golang.org/x/net/html/atom
|
||||
|
||||
Reference in New Issue
Block a user