[chore]: Bump github.com/microcosm-cc/bluemonday from 1.0.20 to 1.0.21 (#1004)
Bumps [github.com/microcosm-cc/bluemonday](https://github.com/microcosm-cc/bluemonday) from 1.0.20 to 1.0.21. - [Release notes](https://github.com/microcosm-cc/bluemonday/releases) - [Commits](https://github.com/microcosm-cc/bluemonday/compare/v1.0.20...v1.0.21) --- updated-dependencies: - dependency-name: github.com/microcosm-cc/bluemonday dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
parent
18e7e00732
commit
a9a43beca2
4
go.mod
4
go.mod
|
@ -29,7 +29,7 @@ require (
|
||||||
github.com/h2non/filetype v1.1.3
|
github.com/h2non/filetype v1.1.3
|
||||||
github.com/jackc/pgconn v1.13.0
|
github.com/jackc/pgconn v1.13.0
|
||||||
github.com/jackc/pgx/v4 v4.17.2
|
github.com/jackc/pgx/v4 v4.17.2
|
||||||
github.com/microcosm-cc/bluemonday v1.0.20
|
github.com/microcosm-cc/bluemonday v1.0.21
|
||||||
github.com/miekg/dns v1.1.50
|
github.com/miekg/dns v1.1.50
|
||||||
github.com/minio/minio-go/v7 v7.0.43
|
github.com/minio/minio-go/v7 v7.0.43
|
||||||
github.com/mitchellh/mapstructure v1.5.0
|
github.com/mitchellh/mapstructure v1.5.0
|
||||||
|
@ -50,7 +50,7 @@ require (
|
||||||
github.com/wagslane/go-password-validator v0.3.0
|
github.com/wagslane/go-password-validator v0.3.0
|
||||||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90
|
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90
|
||||||
golang.org/x/exp v0.0.0-20220613132600-b0d781184e0d
|
golang.org/x/exp v0.0.0-20220613132600-b0d781184e0d
|
||||||
golang.org/x/net v0.0.0-20220909164309-bea034e7d591
|
golang.org/x/net v0.0.0-20221002022538-bcab6841153b
|
||||||
golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094
|
golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094
|
||||||
golang.org/x/text v0.4.0
|
golang.org/x/text v0.4.0
|
||||||
gopkg.in/mcuadros/go-syslog.v2 v2.3.0
|
gopkg.in/mcuadros/go-syslog.v2 v2.3.0
|
||||||
|
|
8
go.sum
8
go.sum
|
@ -451,8 +451,8 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k
|
||||||
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
|
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
|
||||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
|
github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
|
||||||
github.com/microcosm-cc/bluemonday v1.0.20 h1:flpzsq4KU3QIYAYGV/szUat7H+GPOXR0B2JU5A1Wp8Y=
|
github.com/microcosm-cc/bluemonday v1.0.21 h1:dNH3e4PSyE4vNX+KlRGHT5KrSvjeUkoNPwEORjffHJg=
|
||||||
github.com/microcosm-cc/bluemonday v1.0.20/go.mod h1:yfBmMi8mxvaZut3Yytv+jTXRY8mxyjJ0/kQBTElld50=
|
github.com/microcosm-cc/bluemonday v1.0.21/go.mod h1:ytNkv4RrDrLJ2pqlsSI46O6IVXmZOBBD4SaJyDwwTkM=
|
||||||
github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
|
github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
|
||||||
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
|
github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
|
||||||
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
|
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
|
||||||
|
@ -758,8 +758,8 @@ golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su
|
||||||
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||||
golang.org/x/net v0.0.0-20220909164309-bea034e7d591 h1:D0B/7al0LLrVC8aWF4+oxpv/m8bc7ViFfVS8/gXGdqI=
|
golang.org/x/net v0.0.0-20221002022538-bcab6841153b h1:6e93nYa3hNqAvLr0pD4PN1fFS+gKzp2zAXqrnTCstqU=
|
||||||
golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||||
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=
|
||||||
|
|
|
@ -35,31 +35,31 @@ the allowlist will be stripped.
|
||||||
|
|
||||||
The default bluemonday.UGCPolicy().Sanitize() turns this:
|
The default bluemonday.UGCPolicy().Sanitize() turns this:
|
||||||
|
|
||||||
Hello <STYLE>.XSS{background-image:url("javascript:alert('XSS')");}</STYLE><A CLASS=XSS></A>World
|
Hello <STYLE>.XSS{background-image:url("javascript:alert('XSS')");}</STYLE><A CLASS=XSS></A>World
|
||||||
|
|
||||||
Into the more harmless:
|
Into the more harmless:
|
||||||
|
|
||||||
Hello World
|
Hello World
|
||||||
|
|
||||||
And it turns this:
|
And it turns this:
|
||||||
|
|
||||||
<a href="javascript:alert('XSS1')" onmouseover="alert('XSS2')">XSS<a>
|
<a href="javascript:alert('XSS1')" onmouseover="alert('XSS2')">XSS<a>
|
||||||
|
|
||||||
Into this:
|
Into this:
|
||||||
|
|
||||||
XSS
|
XSS
|
||||||
|
|
||||||
Whilst still allowing this:
|
Whilst still allowing this:
|
||||||
|
|
||||||
<a href="http://www.google.com/">
|
<a href="http://www.google.com/">
|
||||||
<img src="https://ssl.gstatic.com/accounts/ui/logo_2x.png"/>
|
<img src="https://ssl.gstatic.com/accounts/ui/logo_2x.png"/>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
To pass through mostly unaltered (it gained a rel="nofollow"):
|
To pass through mostly unaltered (it gained a rel="nofollow"):
|
||||||
|
|
||||||
<a href="http://www.google.com/" rel="nofollow">
|
<a href="http://www.google.com/" rel="nofollow">
|
||||||
<img src="https://ssl.gstatic.com/accounts/ui/logo_2x.png"/>
|
<img src="https://ssl.gstatic.com/accounts/ui/logo_2x.png"/>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
The primary purpose of bluemonday is to take potentially unsafe user generated
|
The primary purpose of bluemonday is to take potentially unsafe user generated
|
||||||
content (from things like Markdown, HTML WYSIWYG tools, etc) and make it safe
|
content (from things like Markdown, HTML WYSIWYG tools, etc) and make it safe
|
||||||
|
@ -95,10 +95,10 @@ attributes are considered safe for your scenario. OWASP provide an XSS
|
||||||
prevention cheat sheet ( https://www.google.com/search?q=xss+prevention+cheat+sheet )
|
prevention cheat sheet ( https://www.google.com/search?q=xss+prevention+cheat+sheet )
|
||||||
to help explain the risks, but essentially:
|
to help explain the risks, but essentially:
|
||||||
|
|
||||||
1. Avoid allowing anything other than plain HTML elements
|
1. Avoid allowing anything other than plain HTML elements
|
||||||
2. Avoid allowing `script`, `style`, `iframe`, `object`, `embed`, `base`
|
2. Avoid allowing `script`, `style`, `iframe`, `object`, `embed`, `base`
|
||||||
elements
|
elements
|
||||||
3. Avoid allowing anything other than plain HTML elements with simple
|
3. Avoid allowing anything other than plain HTML elements with simple
|
||||||
values that you can match to a regexp
|
values that you can match to a regexp
|
||||||
*/
|
*/
|
||||||
package bluemonday
|
package bluemonday
|
||||||
|
|
|
@ -193,10 +193,11 @@ func (p *Policy) AllowImages() {
|
||||||
// http://en.wikipedia.org/wiki/Data_URI_scheme
|
// http://en.wikipedia.org/wiki/Data_URI_scheme
|
||||||
//
|
//
|
||||||
// Images must have a mimetype matching:
|
// Images must have a mimetype matching:
|
||||||
// image/gif
|
//
|
||||||
// image/jpeg
|
// image/gif
|
||||||
// image/png
|
// image/jpeg
|
||||||
// image/webp
|
// image/png
|
||||||
|
// image/webp
|
||||||
//
|
//
|
||||||
// NOTE: There is a potential security risk to allowing data URIs and you should
|
// NOTE: There is a potential security risk to allowing data URIs and you should
|
||||||
// only permit them on content you already trust.
|
// only permit them on content you already trust.
|
||||||
|
|
|
@ -440,8 +440,8 @@ func (p *Policy) sanitize(r io.Reader, w io.Writer) error {
|
||||||
if _, err := buff.WriteString(" "); err != nil {
|
if _, err := buff.WriteString(" "); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
if !skipElementContent {
|
if !skipElementContent {
|
||||||
if _, err := buff.WriteString(token.String()); err != nil {
|
if _, err := buff.WriteString(token.String()); err != nil {
|
||||||
|
|
|
@ -70,6 +70,15 @@ func NewHandler(h http.Handler, s *http2.Server) http.Handler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// extractServer extracts existing http.Server instance from http.Request or create an empty http.Server
|
||||||
|
func extractServer(r *http.Request) *http.Server {
|
||||||
|
server, ok := r.Context().Value(http.ServerContextKey).(*http.Server)
|
||||||
|
if ok {
|
||||||
|
return server
|
||||||
|
}
|
||||||
|
return new(http.Server)
|
||||||
|
}
|
||||||
|
|
||||||
// ServeHTTP implement the h2c support that is enabled by h2c.GetH2CHandler.
|
// ServeHTTP implement the h2c support that is enabled by h2c.GetH2CHandler.
|
||||||
func (s h2cHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (s h2cHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
// Handle h2c with prior knowledge (RFC 7540 Section 3.4)
|
// Handle h2c with prior knowledge (RFC 7540 Section 3.4)
|
||||||
|
@ -87,6 +96,7 @@ func (s h2cHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
s.s.ServeConn(conn, &http2.ServeConnOpts{
|
s.s.ServeConn(conn, &http2.ServeConnOpts{
|
||||||
Context: r.Context(),
|
Context: r.Context(),
|
||||||
|
BaseConfig: extractServer(r),
|
||||||
Handler: s.Handler,
|
Handler: s.Handler,
|
||||||
SawClientPreface: true,
|
SawClientPreface: true,
|
||||||
})
|
})
|
||||||
|
@ -104,6 +114,7 @@ func (s h2cHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
s.s.ServeConn(conn, &http2.ServeConnOpts{
|
s.s.ServeConn(conn, &http2.ServeConnOpts{
|
||||||
Context: r.Context(),
|
Context: r.Context(),
|
||||||
|
BaseConfig: extractServer(r),
|
||||||
Handler: s.Handler,
|
Handler: s.Handler,
|
||||||
UpgradeRequest: r,
|
UpgradeRequest: r,
|
||||||
Settings: settings,
|
Settings: settings,
|
||||||
|
|
|
@ -143,7 +143,7 @@ type Server struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) initialConnRecvWindowSize() int32 {
|
func (s *Server) initialConnRecvWindowSize() int32 {
|
||||||
if s.MaxUploadBufferPerConnection > initialWindowSize {
|
if s.MaxUploadBufferPerConnection >= initialWindowSize {
|
||||||
return s.MaxUploadBufferPerConnection
|
return s.MaxUploadBufferPerConnection
|
||||||
}
|
}
|
||||||
return 1 << 20
|
return 1 << 20
|
||||||
|
@ -869,9 +869,7 @@ 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.
|
||||||
if diff := sc.srv.initialConnRecvWindowSize() - initialWindowSize; diff > 0 {
|
sc.sendWindowUpdate(nil)
|
||||||
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)
|
||||||
|
@ -1588,7 +1586,7 @@ 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, p.Len())
|
sc.sendWindowUpdate(nil)
|
||||||
|
|
||||||
p.CloseWithError(err)
|
p.CloseWithError(err)
|
||||||
}
|
}
|
||||||
|
@ -1736,7 +1734,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, int(f.Length)) // conn-level
|
sc.sendWindowUpdate(nil) // 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.
|
||||||
|
@ -1754,7 +1752,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, int(f.Length)) // conn-level
|
sc.sendWindowUpdate(nil) // 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
|
||||||
|
@ -1772,7 +1770,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.sendWindowUpdate(nil, int(f.Length)-wrote)
|
sc.sendWindowUpdate32(nil, int32(f.Length)-int32(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) {
|
||||||
|
@ -2099,12 +2097,6 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res
|
||||||
return nil, nil, sc.countError("bad_path_method", streamError(f.StreamID, ErrCodeProtocol))
|
return nil, nil, sc.countError("bad_path_method", streamError(f.StreamID, ErrCodeProtocol))
|
||||||
}
|
}
|
||||||
|
|
||||||
bodyOpen := !f.StreamEnded()
|
|
||||||
if rp.method == "HEAD" && bodyOpen {
|
|
||||||
// HEAD requests can't have bodies
|
|
||||||
return nil, nil, sc.countError("head_body", streamError(f.StreamID, ErrCodeProtocol))
|
|
||||||
}
|
|
||||||
|
|
||||||
rp.header = make(http.Header)
|
rp.header = make(http.Header)
|
||||||
for _, hf := range f.RegularFields() {
|
for _, hf := range f.RegularFields() {
|
||||||
rp.header.Add(sc.canonicalHeader(hf.Name), hf.Value)
|
rp.header.Add(sc.canonicalHeader(hf.Name), hf.Value)
|
||||||
|
@ -2117,6 +2109,7 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
bodyOpen := !f.StreamEnded()
|
||||||
if bodyOpen {
|
if bodyOpen {
|
||||||
if vv, ok := rp.header["Content-Length"]; ok {
|
if vv, ok := rp.header["Content-Length"]; ok {
|
||||||
if cl, err := strconv.ParseUint(vv[0], 10, 63); err == nil {
|
if cl, err := strconv.ParseUint(vv[0], 10, 63); err == nil {
|
||||||
|
@ -2329,17 +2322,32 @@ 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, n) // conn-level
|
sc.sendWindowUpdate(nil) // 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, n)
|
sc.sendWindowUpdate(st)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// st may be nil for conn-level
|
// st may be nil for conn-level
|
||||||
func (sc *serverConn) sendWindowUpdate(st *stream, n int) {
|
func (sc *serverConn) sendWindowUpdate(st *stream) {
|
||||||
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
|
||||||
|
@ -2505,6 +2513,10 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
|
||||||
rws.writeHeader(200)
|
rws.writeHeader(200)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if rws.handlerDone {
|
||||||
|
rws.promoteUndeclaredTrailers()
|
||||||
|
}
|
||||||
|
|
||||||
isHeadResp := rws.req.Method == "HEAD"
|
isHeadResp := rws.req.Method == "HEAD"
|
||||||
if !rws.sentHeader {
|
if !rws.sentHeader {
|
||||||
rws.sentHeader = true
|
rws.sentHeader = true
|
||||||
|
@ -2576,10 +2588,6 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if rws.handlerDone {
|
|
||||||
rws.promoteUndeclaredTrailers()
|
|
||||||
}
|
|
||||||
|
|
||||||
// only send trailers if they have actually been defined by the
|
// only send trailers if they have actually been defined by the
|
||||||
// server handler.
|
// server handler.
|
||||||
hasNonemptyTrailers := rws.hasNonemptyTrailers()
|
hasNonemptyTrailers := rws.hasNonemptyTrailers()
|
||||||
|
|
|
@ -258,7 +258,8 @@ func (t *Transport) initConnPool() {
|
||||||
// HTTP/2 server.
|
// HTTP/2 server.
|
||||||
type ClientConn struct {
|
type ClientConn struct {
|
||||||
t *Transport
|
t *Transport
|
||||||
tconn net.Conn // usually *tls.Conn, except specialized impls
|
tconn net.Conn // usually *tls.Conn, except specialized impls
|
||||||
|
tconnClosed bool
|
||||||
tlsState *tls.ConnectionState // nil only for specialized impls
|
tlsState *tls.ConnectionState // nil only for specialized impls
|
||||||
reused uint32 // whether conn is being reused; atomic
|
reused uint32 // whether conn is being reused; atomic
|
||||||
singleUse bool // whether being used for a single http.Request
|
singleUse bool // whether being used for a single http.Request
|
||||||
|
@ -344,8 +345,8 @@ type clientStream struct {
|
||||||
readErr error // sticky read error; owned by transportResponseBody.Read
|
readErr error // sticky read error; owned by transportResponseBody.Read
|
||||||
|
|
||||||
reqBody io.ReadCloser
|
reqBody io.ReadCloser
|
||||||
reqBodyContentLength int64 // -1 means unknown
|
reqBodyContentLength int64 // -1 means unknown
|
||||||
reqBodyClosed bool // body has been closed; guarded by cc.mu
|
reqBodyClosed chan struct{} // guarded by cc.mu; non-nil on Close, closed when done
|
||||||
|
|
||||||
// owned by writeRequest:
|
// owned by writeRequest:
|
||||||
sentEndStream bool // sent an END_STREAM flag to the peer
|
sentEndStream bool // sent an END_STREAM flag to the peer
|
||||||
|
@ -385,9 +386,8 @@ func (cs *clientStream) abortStreamLocked(err error) {
|
||||||
cs.abortErr = err
|
cs.abortErr = err
|
||||||
close(cs.abort)
|
close(cs.abort)
|
||||||
})
|
})
|
||||||
if cs.reqBody != nil && !cs.reqBodyClosed {
|
if cs.reqBody != nil {
|
||||||
cs.reqBody.Close()
|
cs.closeReqBodyLocked()
|
||||||
cs.reqBodyClosed = true
|
|
||||||
}
|
}
|
||||||
// TODO(dneil): Clean up tests where cs.cc.cond is nil.
|
// TODO(dneil): Clean up tests where cs.cc.cond is nil.
|
||||||
if cs.cc.cond != nil {
|
if cs.cc.cond != nil {
|
||||||
|
@ -400,13 +400,24 @@ func (cs *clientStream) abortRequestBodyWrite() {
|
||||||
cc := cs.cc
|
cc := cs.cc
|
||||||
cc.mu.Lock()
|
cc.mu.Lock()
|
||||||
defer cc.mu.Unlock()
|
defer cc.mu.Unlock()
|
||||||
if cs.reqBody != nil && !cs.reqBodyClosed {
|
if cs.reqBody != nil && cs.reqBodyClosed == nil {
|
||||||
cs.reqBody.Close()
|
cs.closeReqBodyLocked()
|
||||||
cs.reqBodyClosed = true
|
|
||||||
cc.cond.Broadcast()
|
cc.cond.Broadcast()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cs *clientStream) closeReqBodyLocked() {
|
||||||
|
if cs.reqBodyClosed != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cs.reqBodyClosed = make(chan struct{})
|
||||||
|
reqBodyClosed := cs.reqBodyClosed
|
||||||
|
go func() {
|
||||||
|
cs.reqBody.Close()
|
||||||
|
close(reqBodyClosed)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
type stickyErrWriter struct {
|
type stickyErrWriter struct {
|
||||||
conn net.Conn
|
conn net.Conn
|
||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
|
@ -921,10 +932,10 @@ func (cc *ClientConn) onIdleTimeout() {
|
||||||
cc.closeIfIdle()
|
cc.closeIfIdle()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cc *ClientConn) closeConn() error {
|
func (cc *ClientConn) closeConn() {
|
||||||
t := time.AfterFunc(250*time.Millisecond, cc.forceCloseConn)
|
t := time.AfterFunc(250*time.Millisecond, cc.forceCloseConn)
|
||||||
defer t.Stop()
|
defer t.Stop()
|
||||||
return cc.tconn.Close()
|
cc.tconn.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// A tls.Conn.Close can hang for a long time if the peer is unresponsive.
|
// A tls.Conn.Close can hang for a long time if the peer is unresponsive.
|
||||||
|
@ -990,7 +1001,8 @@ func (cc *ClientConn) Shutdown(ctx context.Context) error {
|
||||||
shutdownEnterWaitStateHook()
|
shutdownEnterWaitStateHook()
|
||||||
select {
|
select {
|
||||||
case <-done:
|
case <-done:
|
||||||
return cc.closeConn()
|
cc.closeConn()
|
||||||
|
return nil
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
cc.mu.Lock()
|
cc.mu.Lock()
|
||||||
// Free the goroutine above
|
// Free the goroutine above
|
||||||
|
@ -1027,7 +1039,7 @@ func (cc *ClientConn) sendGoAway() error {
|
||||||
|
|
||||||
// closes the client connection immediately. In-flight requests are interrupted.
|
// closes the client connection immediately. In-flight requests are interrupted.
|
||||||
// err is sent to streams.
|
// err is sent to streams.
|
||||||
func (cc *ClientConn) closeForError(err error) error {
|
func (cc *ClientConn) closeForError(err error) {
|
||||||
cc.mu.Lock()
|
cc.mu.Lock()
|
||||||
cc.closed = true
|
cc.closed = true
|
||||||
for _, cs := range cc.streams {
|
for _, cs := range cc.streams {
|
||||||
|
@ -1035,7 +1047,7 @@ func (cc *ClientConn) closeForError(err error) error {
|
||||||
}
|
}
|
||||||
cc.cond.Broadcast()
|
cc.cond.Broadcast()
|
||||||
cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
return cc.closeConn()
|
cc.closeConn()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close closes the client connection immediately.
|
// Close closes the client connection immediately.
|
||||||
|
@ -1043,16 +1055,17 @@ func (cc *ClientConn) closeForError(err error) error {
|
||||||
// In-flight requests are interrupted. For a graceful shutdown, use Shutdown instead.
|
// In-flight requests are interrupted. For a graceful shutdown, use Shutdown instead.
|
||||||
func (cc *ClientConn) Close() error {
|
func (cc *ClientConn) Close() error {
|
||||||
err := errors.New("http2: client connection force closed via ClientConn.Close")
|
err := errors.New("http2: client connection force closed via ClientConn.Close")
|
||||||
return cc.closeForError(err)
|
cc.closeForError(err)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// closes the client connection immediately. In-flight requests are interrupted.
|
// closes the client connection immediately. In-flight requests are interrupted.
|
||||||
func (cc *ClientConn) closeForLostPing() error {
|
func (cc *ClientConn) closeForLostPing() {
|
||||||
err := errors.New("http2: client connection lost")
|
err := errors.New("http2: client connection lost")
|
||||||
if f := cc.t.CountError; f != nil {
|
if f := cc.t.CountError; f != nil {
|
||||||
f("conn_close_lost_ping")
|
f("conn_close_lost_ping")
|
||||||
}
|
}
|
||||||
return cc.closeForError(err)
|
cc.closeForError(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// errRequestCanceled is a copy of net/http's errRequestCanceled because it's not
|
// errRequestCanceled is a copy of net/http's errRequestCanceled because it's not
|
||||||
|
@ -1430,11 +1443,19 @@ func (cs *clientStream) cleanupWriteRequest(err error) {
|
||||||
// and in multiple cases: server replies <=299 and >299
|
// and in multiple cases: server replies <=299 and >299
|
||||||
// while still writing request body
|
// while still writing request body
|
||||||
cc.mu.Lock()
|
cc.mu.Lock()
|
||||||
|
mustCloseBody := false
|
||||||
|
if cs.reqBody != nil && cs.reqBodyClosed == nil {
|
||||||
|
mustCloseBody = true
|
||||||
|
cs.reqBodyClosed = make(chan struct{})
|
||||||
|
}
|
||||||
bodyClosed := cs.reqBodyClosed
|
bodyClosed := cs.reqBodyClosed
|
||||||
cs.reqBodyClosed = true
|
|
||||||
cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
if !bodyClosed && cs.reqBody != nil {
|
if mustCloseBody {
|
||||||
cs.reqBody.Close()
|
cs.reqBody.Close()
|
||||||
|
close(bodyClosed)
|
||||||
|
}
|
||||||
|
if bodyClosed != nil {
|
||||||
|
<-bodyClosed
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil && cs.sentEndStream {
|
if err != nil && cs.sentEndStream {
|
||||||
|
@ -1614,7 +1635,7 @@ func (cs *clientStream) writeRequestBody(req *http.Request) (err error) {
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cc.mu.Lock()
|
cc.mu.Lock()
|
||||||
bodyClosed := cs.reqBodyClosed
|
bodyClosed := cs.reqBodyClosed != nil
|
||||||
cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
switch {
|
switch {
|
||||||
case bodyClosed:
|
case bodyClosed:
|
||||||
|
@ -1709,7 +1730,7 @@ func (cs *clientStream) awaitFlowControl(maxBytes int) (taken int32, err error)
|
||||||
if cc.closed {
|
if cc.closed {
|
||||||
return 0, errClientConnClosed
|
return 0, errClientConnClosed
|
||||||
}
|
}
|
||||||
if cs.reqBodyClosed {
|
if cs.reqBodyClosed != nil {
|
||||||
return 0, errStopReqBodyWrite
|
return 0, errStopReqBodyWrite
|
||||||
}
|
}
|
||||||
select {
|
select {
|
||||||
|
@ -2005,7 +2026,7 @@ func (cc *ClientConn) forgetStreamID(id uint32) {
|
||||||
// wake up RoundTrip if there is a pending request.
|
// wake up RoundTrip if there is a pending request.
|
||||||
cc.cond.Broadcast()
|
cc.cond.Broadcast()
|
||||||
|
|
||||||
closeOnIdle := cc.singleUse || cc.doNotReuse || cc.t.disableKeepAlives()
|
closeOnIdle := cc.singleUse || cc.doNotReuse || cc.t.disableKeepAlives() || cc.goAway != nil
|
||||||
if closeOnIdle && cc.streamsReserved == 0 && len(cc.streams) == 0 {
|
if closeOnIdle && cc.streamsReserved == 0 && len(cc.streams) == 0 {
|
||||||
if VerboseLogs {
|
if VerboseLogs {
|
||||||
cc.vlogf("http2: Transport closing idle conn %p (forSingleUse=%v, maxStream=%v)", cc, cc.singleUse, cc.nextStreamID-2)
|
cc.vlogf("http2: Transport closing idle conn %p (forSingleUse=%v, maxStream=%v)", cc, cc.singleUse, cc.nextStreamID-2)
|
||||||
|
@ -2081,6 +2102,7 @@ func (rl *clientConnReadLoop) cleanup() {
|
||||||
err = io.ErrUnexpectedEOF
|
err = io.ErrUnexpectedEOF
|
||||||
}
|
}
|
||||||
cc.closed = true
|
cc.closed = true
|
||||||
|
|
||||||
for _, cs := range cc.streams {
|
for _, cs := range cc.streams {
|
||||||
select {
|
select {
|
||||||
case <-cs.peerClosed:
|
case <-cs.peerClosed:
|
||||||
|
@ -2674,7 +2696,6 @@ func (rl *clientConnReadLoop) processGoAway(f *GoAwayFrame) error {
|
||||||
if fn := cc.t.CountError; fn != nil {
|
if fn := cc.t.CountError; fn != nil {
|
||||||
fn("recv_goaway_" + f.ErrCode.stringToken())
|
fn("recv_goaway_" + f.ErrCode.stringToken())
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
cc.setGoAway(f)
|
cc.setGoAway(f)
|
||||||
return nil
|
return nil
|
||||||
|
@ -3028,7 +3049,7 @@ func traceGotConn(req *http.Request, cc *ClientConn, reused bool) {
|
||||||
cc.mu.Lock()
|
cc.mu.Lock()
|
||||||
ci.WasIdle = len(cc.streams) == 0 && reused
|
ci.WasIdle = len(cc.streams) == 0 && reused
|
||||||
if ci.WasIdle && !cc.lastActive.IsZero() {
|
if ci.WasIdle && !cc.lastActive.IsZero() {
|
||||||
ci.IdleTime = time.Now().Sub(cc.lastActive)
|
ci.IdleTime = time.Since(cc.lastActive)
|
||||||
}
|
}
|
||||||
cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
|
|
||||||
|
|
|
@ -172,7 +172,23 @@ type mmsgTmpsPool struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *mmsgTmpsPool) Get() *mmsgTmps {
|
func (p *mmsgTmpsPool) Get() *mmsgTmps {
|
||||||
return p.p.Get().(*mmsgTmps)
|
m := p.p.Get().(*mmsgTmps)
|
||||||
|
// Clear fields up to the len (not the cap) of the slice,
|
||||||
|
// assuming that the previous caller only used that many elements.
|
||||||
|
for i := range m.packer.sockaddrs {
|
||||||
|
m.packer.sockaddrs[i] = 0
|
||||||
|
}
|
||||||
|
m.packer.sockaddrs = m.packer.sockaddrs[:0]
|
||||||
|
for i := range m.packer.vs {
|
||||||
|
m.packer.vs[i] = iovec{}
|
||||||
|
}
|
||||||
|
m.packer.vs = m.packer.vs[:0]
|
||||||
|
for i := range m.packer.hs {
|
||||||
|
m.packer.hs[i].Len = 0
|
||||||
|
m.packer.hs[i].Hdr = msghdr{}
|
||||||
|
}
|
||||||
|
m.packer.hs = m.packer.hs[:0]
|
||||||
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *mmsgTmpsPool) Put(tmps *mmsgTmps) {
|
func (p *mmsgTmpsPool) Put(tmps *mmsgTmps) {
|
||||||
|
|
|
@ -17,9 +17,6 @@ func (h *msghdr) pack(vs []iovec, bs [][]byte, oob []byte, sa []byte) {
|
||||||
if sa != nil {
|
if sa != nil {
|
||||||
h.Name = (*byte)(unsafe.Pointer(&sa[0]))
|
h.Name = (*byte)(unsafe.Pointer(&sa[0]))
|
||||||
h.Namelen = uint32(len(sa))
|
h.Namelen = uint32(len(sa))
|
||||||
} else {
|
|
||||||
h.Name = nil
|
|
||||||
h.Namelen = 0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -263,7 +263,7 @@ github.com/magiconair/properties
|
||||||
# github.com/mattn/go-isatty v0.0.16
|
# github.com/mattn/go-isatty v0.0.16
|
||||||
## explicit; go 1.15
|
## explicit; go 1.15
|
||||||
github.com/mattn/go-isatty
|
github.com/mattn/go-isatty
|
||||||
# github.com/microcosm-cc/bluemonday v1.0.20
|
# github.com/microcosm-cc/bluemonday v1.0.21
|
||||||
## explicit; go 1.19
|
## explicit; go 1.19
|
||||||
github.com/microcosm-cc/bluemonday
|
github.com/microcosm-cc/bluemonday
|
||||||
github.com/microcosm-cc/bluemonday/css
|
github.com/microcosm-cc/bluemonday/css
|
||||||
|
@ -655,7 +655,7 @@ golang.org/x/image/tiff/lzw
|
||||||
# golang.org/x/mod v0.6.0-dev.0.20220907135952-02c991387e35
|
# golang.org/x/mod v0.6.0-dev.0.20220907135952-02c991387e35
|
||||||
## explicit; go 1.17
|
## explicit; go 1.17
|
||||||
golang.org/x/mod/semver
|
golang.org/x/mod/semver
|
||||||
# golang.org/x/net v0.0.0-20220909164309-bea034e7d591
|
# golang.org/x/net v0.0.0-20221002022538-bcab6841153b
|
||||||
## explicit; go 1.17
|
## explicit; go 1.17
|
||||||
golang.org/x/net/bpf
|
golang.org/x/net/bpf
|
||||||
golang.org/x/net/context
|
golang.org/x/net/context
|
||||||
|
|
Loading…
Reference in New Issue