func()

in mux.go [229:279]


func (m *mux) getContentType(framer *http2.Framer, framesBuf *bytes.Buffer) (contentType string, _ error) {
	// Code based on https://github.com/soheilhy/cmux
	//
	// Copyright 2016 The CMux Authors. All rights reserved.
	dec := decoderPool.Get().(*decoder)

	// Read frames until we have the content-type header, or we know there isn't one.
	var haveFirstSettings bool
	var haveFirstSettingsACK bool
	var haveEndHeaders bool
	for (dec.contentType == "" && !haveEndHeaders) || !haveFirstSettings || !haveFirstSettingsACK {
		f, err := framer.ReadFrame()
		if err != nil {
			return "", err
		}

		switch f := f.(type) {
		case *http2.SettingsFrame:
			switch {
			case !haveFirstSettingsACK && f.IsAck():
				haveFirstSettingsACK = true
				// We accept the ACK, and omit it from the frames
				// written to the real server.
				framesBuf.Truncate(framesBuf.Len() - int(f.Length) - http2FrameHeaderLength)
			case !haveFirstSettings && !f.IsAck():
				haveFirstSettings = true
				// We ACK the client's first SETTINGS to unblock it,
				// and ignore the first ACK from the real server.
				if err := framer.WriteSettingsAck(); err != nil {
					return "", err
				}
			}
		case *http2.ContinuationFrame:
			if _, err := dec.d.Write(f.HeaderBlockFragment()); err != nil {
				return "", err
			}
			haveEndHeaders = f.FrameHeader.Flags&http2.FlagHeadersEndHeaders != 0
		case *http2.HeadersFrame:
			if _, err := dec.d.Write(f.HeaderBlockFragment()); err != nil {
				return "", err
			}
			haveEndHeaders = f.FrameHeader.Flags&http2.FlagHeadersEndHeaders != 0
		}
	}
	contentType = dec.contentType
	if dec.d.Close() == nil {
		dec.contentType = ""
		decoderPool.Put(dec)
	}
	return contentType, nil
}