mirror of
https://github.com/miniflux/v2.git
synced 2025-09-15 18:57:04 +00:00
Add FeedIcon API call and update dependencies
This commit is contained in:
parent
231ebf2daa
commit
27196589fb
262 changed files with 83830 additions and 30061 deletions
1
vendor/golang.org/x/net/http2/go19_test.go
generated
vendored
1
vendor/golang.org/x/net/http2/go19_test.go
generated
vendored
|
@ -46,7 +46,6 @@ func TestServerGracefulShutdown(t *testing.T) {
|
|||
wanth := [][2]string{
|
||||
{":status", "200"},
|
||||
{"x-foo", "bar"},
|
||||
{"content-type", "text/plain; charset=utf-8"},
|
||||
{"content-length", "0"},
|
||||
}
|
||||
if !reflect.DeepEqual(goth, wanth) {
|
||||
|
|
21
vendor/golang.org/x/net/http2/server.go
generated
vendored
21
vendor/golang.org/x/net/http2/server.go
generated
vendored
|
@ -2322,7 +2322,7 @@ func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
|
|||
clen = strconv.Itoa(len(p))
|
||||
}
|
||||
_, hasContentType := rws.snapHeader["Content-Type"]
|
||||
if !hasContentType && bodyAllowedForStatus(rws.status) {
|
||||
if !hasContentType && bodyAllowedForStatus(rws.status) && len(p) > 0 {
|
||||
ctype = http.DetectContentType(p)
|
||||
}
|
||||
var date string
|
||||
|
@ -2490,7 +2490,26 @@ func (w *responseWriter) Header() http.Header {
|
|||
return rws.handlerHeader
|
||||
}
|
||||
|
||||
// checkWriteHeaderCode is a copy of net/http's checkWriteHeaderCode.
|
||||
func checkWriteHeaderCode(code int) {
|
||||
// Issue 22880: require valid WriteHeader status codes.
|
||||
// For now we only enforce that it's three digits.
|
||||
// In the future we might block things over 599 (600 and above aren't defined
|
||||
// at http://httpwg.org/specs/rfc7231.html#status.codes)
|
||||
// and we might block under 200 (once we have more mature 1xx support).
|
||||
// But for now any three digits.
|
||||
//
|
||||
// We used to send "HTTP/1.1 000 0" on the wire in responses but there's
|
||||
// no equivalent bogus thing we can realistically send in HTTP/2,
|
||||
// so we'll consistently panic instead and help people find their bugs
|
||||
// early. (We can't return an error from WriteHeader even if we wanted to.)
|
||||
if code < 100 || code > 999 {
|
||||
panic(fmt.Sprintf("invalid WriteHeader code %v", code))
|
||||
}
|
||||
}
|
||||
|
||||
func (w *responseWriter) WriteHeader(code int) {
|
||||
checkWriteHeaderCode(code)
|
||||
rws := w.rws
|
||||
if rws == nil {
|
||||
panic("WriteHeader called after Handler finished")
|
||||
|
|
3
vendor/golang.org/x/net/http2/server_test.go
generated
vendored
3
vendor/golang.org/x/net/http2/server_test.go
generated
vendored
|
@ -1718,7 +1718,6 @@ func TestServer_Response_NoData_Header_FooBar(t *testing.T) {
|
|||
wanth := [][2]string{
|
||||
{":status", "200"},
|
||||
{"foo-bar", "some-value"},
|
||||
{"content-type", "text/plain; charset=utf-8"},
|
||||
{"content-length", "0"},
|
||||
}
|
||||
if !reflect.DeepEqual(goth, wanth) {
|
||||
|
@ -2953,7 +2952,6 @@ func TestServerDoesntWriteInvalidHeaders(t *testing.T) {
|
|||
wanth := [][2]string{
|
||||
{":status", "200"},
|
||||
{"ok1", "x"},
|
||||
{"content-type", "text/plain; charset=utf-8"},
|
||||
{"content-length", "0"},
|
||||
}
|
||||
if !reflect.DeepEqual(goth, wanth) {
|
||||
|
@ -3266,7 +3264,6 @@ func TestServerNoAutoContentLengthOnHead(t *testing.T) {
|
|||
headers := st.decodeHeader(h.HeaderBlockFragment())
|
||||
want := [][2]string{
|
||||
{":status", "200"},
|
||||
{"content-type", "text/plain; charset=utf-8"},
|
||||
}
|
||||
if !reflect.DeepEqual(headers, want) {
|
||||
t.Errorf("Headers mismatch.\n got: %q\nwant: %q\n", headers, want)
|
||||
|
|
62
vendor/golang.org/x/net/http2/transport.go
generated
vendored
62
vendor/golang.org/x/net/http2/transport.go
generated
vendored
|
@ -811,7 +811,7 @@ func (cc *ClientConn) roundTrip(req *http.Request) (res *http.Response, gotErrAf
|
|||
|
||||
cc.wmu.Lock()
|
||||
endStream := !hasBody && !hasTrailers
|
||||
werr := cc.writeHeaders(cs.ID, endStream, hdrs)
|
||||
werr := cc.writeHeaders(cs.ID, endStream, int(cc.maxFrameSize), hdrs)
|
||||
cc.wmu.Unlock()
|
||||
traceWroteHeaders(cs.trace)
|
||||
cc.mu.Unlock()
|
||||
|
@ -964,13 +964,12 @@ func (cc *ClientConn) awaitOpenSlotForRequest(req *http.Request) error {
|
|||
}
|
||||
|
||||
// requires cc.wmu be held
|
||||
func (cc *ClientConn) writeHeaders(streamID uint32, endStream bool, hdrs []byte) error {
|
||||
func (cc *ClientConn) writeHeaders(streamID uint32, endStream bool, maxFrameSize int, hdrs []byte) error {
|
||||
first := true // first frame written (HEADERS is first, then CONTINUATION)
|
||||
frameSize := int(cc.maxFrameSize)
|
||||
for len(hdrs) > 0 && cc.werr == nil {
|
||||
chunk := hdrs
|
||||
if len(chunk) > frameSize {
|
||||
chunk = chunk[:frameSize]
|
||||
if len(chunk) > maxFrameSize {
|
||||
chunk = chunk[:maxFrameSize]
|
||||
}
|
||||
hdrs = hdrs[len(chunk):]
|
||||
endHeaders := len(hdrs) == 0
|
||||
|
@ -1087,13 +1086,17 @@ func (cs *clientStream) writeRequestBody(body io.Reader, bodyCloser io.Closer) (
|
|||
}
|
||||
}
|
||||
|
||||
cc.mu.Lock()
|
||||
maxFrameSize := int(cc.maxFrameSize)
|
||||
cc.mu.Unlock()
|
||||
|
||||
cc.wmu.Lock()
|
||||
defer cc.wmu.Unlock()
|
||||
|
||||
// Two ways to send END_STREAM: either with trailers, or
|
||||
// with an empty DATA frame.
|
||||
if len(trls) > 0 {
|
||||
err = cc.writeHeaders(cs.ID, true, trls)
|
||||
err = cc.writeHeaders(cs.ID, true, maxFrameSize, trls)
|
||||
} else {
|
||||
err = cc.fr.WriteData(cs.ID, true, nil)
|
||||
}
|
||||
|
@ -1373,17 +1376,12 @@ func (cc *ClientConn) streamByID(id uint32, andRemove bool) *clientStream {
|
|||
// clientConnReadLoop is the state owned by the clientConn's frame-reading readLoop.
|
||||
type clientConnReadLoop struct {
|
||||
cc *ClientConn
|
||||
activeRes map[uint32]*clientStream // keyed by streamID
|
||||
closeWhenIdle bool
|
||||
}
|
||||
|
||||
// readLoop runs in its own goroutine and reads and dispatches frames.
|
||||
func (cc *ClientConn) readLoop() {
|
||||
rl := &clientConnReadLoop{
|
||||
cc: cc,
|
||||
activeRes: make(map[uint32]*clientStream),
|
||||
}
|
||||
|
||||
rl := &clientConnReadLoop{cc: cc}
|
||||
defer rl.cleanup()
|
||||
cc.readerErr = rl.run()
|
||||
if ce, ok := cc.readerErr.(ConnectionError); ok {
|
||||
|
@ -1438,10 +1436,8 @@ func (rl *clientConnReadLoop) cleanup() {
|
|||
} else if err == io.EOF {
|
||||
err = io.ErrUnexpectedEOF
|
||||
}
|
||||
for _, cs := range rl.activeRes {
|
||||
cs.bufPipe.CloseWithError(err)
|
||||
}
|
||||
for _, cs := range cc.streams {
|
||||
cs.bufPipe.CloseWithError(err) // no-op if already closed
|
||||
select {
|
||||
case cs.resc <- resAndError{err: err}:
|
||||
default:
|
||||
|
@ -1519,7 +1515,7 @@ func (rl *clientConnReadLoop) run() error {
|
|||
}
|
||||
return err
|
||||
}
|
||||
if rl.closeWhenIdle && gotReply && maybeIdle && len(rl.activeRes) == 0 {
|
||||
if rl.closeWhenIdle && gotReply && maybeIdle {
|
||||
cc.closeIfIdle()
|
||||
}
|
||||
}
|
||||
|
@ -1527,6 +1523,13 @@ func (rl *clientConnReadLoop) run() error {
|
|||
|
||||
func (rl *clientConnReadLoop) processHeaders(f *MetaHeadersFrame) error {
|
||||
cc := rl.cc
|
||||
cs := cc.streamByID(f.StreamID, false)
|
||||
if cs == nil {
|
||||
// We'd get here if we canceled a request while the
|
||||
// server had its response still in flight. So if this
|
||||
// was just something we canceled, ignore it.
|
||||
return nil
|
||||
}
|
||||
if f.StreamEnded() {
|
||||
// Issue 20521: If the stream has ended, streamByID() causes
|
||||
// clientStream.done to be closed, which causes the request's bodyWriter
|
||||
|
@ -1535,14 +1538,15 @@ func (rl *clientConnReadLoop) processHeaders(f *MetaHeadersFrame) error {
|
|||
// Deferring stream closure allows the header processing to occur first.
|
||||
// clientConn.RoundTrip may still receive the bodyWriter error first, but
|
||||
// the fix for issue 16102 prioritises any response.
|
||||
defer cc.streamByID(f.StreamID, true)
|
||||
}
|
||||
cs := cc.streamByID(f.StreamID, false)
|
||||
if cs == nil {
|
||||
// We'd get here if we canceled a request while the
|
||||
// server had its response still in flight. So if this
|
||||
// was just something we canceled, ignore it.
|
||||
return nil
|
||||
//
|
||||
// Issue 22413: If there is no request body, we should close the
|
||||
// stream before writing to cs.resc so that the stream is closed
|
||||
// immediately once RoundTrip returns.
|
||||
if cs.req.Body != nil {
|
||||
defer cc.forgetStreamID(f.StreamID)
|
||||
} else {
|
||||
cc.forgetStreamID(f.StreamID)
|
||||
}
|
||||
}
|
||||
if !cs.firstByte {
|
||||
if cs.trace != nil {
|
||||
|
@ -1567,6 +1571,7 @@ func (rl *clientConnReadLoop) processHeaders(f *MetaHeadersFrame) error {
|
|||
}
|
||||
// Any other error type is a stream error.
|
||||
cs.cc.writeStreamReset(f.StreamID, ErrCodeProtocol, err)
|
||||
cc.forgetStreamID(cs.ID)
|
||||
cs.resc <- resAndError{err: err}
|
||||
return nil // return nil from process* funcs to keep conn alive
|
||||
}
|
||||
|
@ -1574,9 +1579,6 @@ func (rl *clientConnReadLoop) processHeaders(f *MetaHeadersFrame) error {
|
|||
// (nil, nil) special case. See handleResponse docs.
|
||||
return nil
|
||||
}
|
||||
if res.Body != noBody {
|
||||
rl.activeRes[cs.ID] = cs
|
||||
}
|
||||
cs.resTrailer = &res.Trailer
|
||||
cs.resc <- resAndError{res: res}
|
||||
return nil
|
||||
|
@ -1596,11 +1598,11 @@ func (rl *clientConnReadLoop) handleResponse(cs *clientStream, f *MetaHeadersFra
|
|||
|
||||
status := f.PseudoValue("status")
|
||||
if status == "" {
|
||||
return nil, errors.New("missing status pseudo header")
|
||||
return nil, errors.New("malformed response from server: missing status pseudo header")
|
||||
}
|
||||
statusCode, err := strconv.Atoi(status)
|
||||
if err != nil {
|
||||
return nil, errors.New("malformed non-numeric status pseudo header")
|
||||
return nil, errors.New("malformed response from server: malformed non-numeric status pseudo header")
|
||||
}
|
||||
|
||||
if statusCode == 100 {
|
||||
|
@ -1915,7 +1917,6 @@ func (rl *clientConnReadLoop) endStreamError(cs *clientStream, err error) {
|
|||
rl.closeWhenIdle = true
|
||||
}
|
||||
cs.bufPipe.closeWithErrorAndCode(err, code)
|
||||
delete(rl.activeRes, cs.ID)
|
||||
|
||||
select {
|
||||
case cs.resc <- resAndError{err: err}:
|
||||
|
@ -2042,7 +2043,6 @@ func (rl *clientConnReadLoop) processResetStream(f *RSTStreamFrame) error {
|
|||
cs.bufPipe.CloseWithError(err)
|
||||
cs.cc.cond.Broadcast() // wake up checkResetOrDone via clientStream.awaitFlowControl
|
||||
}
|
||||
delete(rl.activeRes, cs.ID)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
51
vendor/golang.org/x/net/http2/transport_test.go
generated
vendored
51
vendor/golang.org/x/net/http2/transport_test.go
generated
vendored
|
@ -13,6 +13,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
|
@ -2291,6 +2292,11 @@ func TestTransportReadHeadResponse(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestTransportReadHeadResponseWithBody(t *testing.T) {
|
||||
// This test use not valid response format.
|
||||
// Discarding logger output to not spam tests output.
|
||||
log.SetOutput(ioutil.Discard)
|
||||
defer log.SetOutput(os.Stderr)
|
||||
|
||||
response := "redirecting to /elsewhere"
|
||||
ct := newClientTester(t)
|
||||
clientDone := make(chan struct{})
|
||||
|
@ -3383,6 +3389,11 @@ func TestTransportRetryHasLimit(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestTransportResponseDataBeforeHeaders(t *testing.T) {
|
||||
// This test use not valid response format.
|
||||
// Discarding logger output to not spam tests output.
|
||||
log.SetOutput(ioutil.Discard)
|
||||
defer log.SetOutput(os.Stderr)
|
||||
|
||||
ct := newClientTester(t)
|
||||
ct.client = func() error {
|
||||
defer ct.cc.(*net.TCPConn).CloseWrite()
|
||||
|
@ -3788,6 +3799,46 @@ func TestTransportResponseAndResetWithoutConsumingBodyRace(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// Verify transport doesn't crash when receiving bogus response lacking a :status header.
|
||||
// Issue 22880.
|
||||
func TestTransportHandlesInvalidStatuslessResponse(t *testing.T) {
|
||||
ct := newClientTester(t)
|
||||
ct.client = func() error {
|
||||
req, _ := http.NewRequest("GET", "https://dummy.tld/", nil)
|
||||
_, err := ct.tr.RoundTrip(req)
|
||||
const substr = "malformed response from server: missing status pseudo header"
|
||||
if !strings.Contains(fmt.Sprint(err), substr) {
|
||||
return fmt.Errorf("RoundTrip error = %v; want substring %q", err, substr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
ct.server = func() error {
|
||||
ct.greet()
|
||||
var buf bytes.Buffer
|
||||
enc := hpack.NewEncoder(&buf)
|
||||
|
||||
for {
|
||||
f, err := ct.fr.ReadFrame()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch f := f.(type) {
|
||||
case *HeadersFrame:
|
||||
enc.WriteField(hpack.HeaderField{Name: "content-type", Value: "text/html"}) // no :status header
|
||||
ct.fr.WriteHeaders(HeadersFrameParam{
|
||||
StreamID: f.StreamID,
|
||||
EndHeaders: true,
|
||||
EndStream: false, // we'll send some DATA to try to crash the transport
|
||||
BlockFragment: buf.Bytes(),
|
||||
})
|
||||
ct.fr.WriteData(f.StreamID, true, []byte("payload"))
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
ct.run()
|
||||
}
|
||||
|
||||
func BenchmarkClientRequestHeaders(b *testing.B) {
|
||||
b.Run(" 0 Headers", func(b *testing.B) { benchSimpleRoundTrip(b, 0) })
|
||||
b.Run(" 10 Headers", func(b *testing.B) { benchSimpleRoundTrip(b, 10) })
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue