示例#1
0
        State?ReadHeaders(IByteBuffer buffer)
        {
            IHttpMessage httpMessage = _message;
            HttpHeaders  headers     = httpMessage.Headers;

            AppendableCharSequence line = _headerParser.Parse(buffer);

            if (line is null)
            {
                return(null);
            }
            // ReSharper disable once ConvertIfDoToWhile
            if ((uint)line.Count > 0u)
            {
                do
                {
                    byte firstChar = line.Bytes[0];
                    if (_name is object && (firstChar == c_space || firstChar == c_tab))
                    {
                        //please do not make one line from below code
                        //as it breaks +XX:OptimizeStringConcat optimization
                        ICharSequence trimmedLine = CharUtil.Trim(line);
                        _value = new AsciiString($"{_value} {trimmedLine}");
                    }
                    else
                    {
                        if (_name is object)
                        {
                            _ = headers.Add(_name, _value);
                        }
                        SplitHeader(line);
                    }

                    line = _headerParser.Parse(buffer);
                    if (line is null)
                    {
                        return(null);
                    }
                } while ((uint)line.Count > 0u);
            }

            // Add the last header.
            if (_name is object)
            {
                _ = headers.Add(_name, _value);
            }

            // reset name and value fields
            _name  = null;
            _value = null;

            var  values = headers.GetAll(HttpHeaderNames.ContentLength);
            uint contentLengthValuesCount = (uint)values.Count;

            if (contentLengthValuesCount > 0u)
            {
                // Guard against multiple Content-Length headers as stated in
                // https://tools.ietf.org/html/rfc7230#section-3.3.2:
                //
                // If a message is received that has multiple Content-Length header
                //   fields with field-values consisting of the same decimal value, or a
                //   single Content-Length header field with a field value containing a
                //   list of identical decimal values (e.g., "Content-Length: 42, 42"),
                //   indicating that duplicate Content-Length header fields have been
                //   generated or combined by an upstream message processor, then the
                //   recipient MUST either reject the message as invalid or replace the
                //   duplicated field-values with a single valid Content-Length field
                //   containing that decimal value prior to determining the message body
                //   length or forwarding the message.
                if (contentLengthValuesCount > 1u && httpMessage.ProtocolVersion == HttpVersion.Http11)
                {
                    ThrowHelper.ThrowArgumentException_Multiple_Content_Length_Headers_Found();
                }
                if (!long.TryParse(values[0].ToString(), out _contentLength))
                {
                    ThrowHelper.ThrowArgumentException_Invalid_Content_Length();
                }
            }

            if (IsContentAlwaysEmpty(httpMessage))
            {
                HttpUtil.SetTransferEncodingChunked(httpMessage, false);
                return(State.SkipControlChars);
            }
            else if (HttpUtil.IsTransferEncodingChunked(httpMessage))
            {
                if (contentLengthValuesCount > 0u && httpMessage.ProtocolVersion == HttpVersion.Http11)
                {
                    HandleTransferEncodingChunkedWithContentLength(httpMessage);
                }

                return(State.ReadChunkSize);
            }
            else if (ContentLength() >= 0L)
            {
                return(State.ReadFixedLengthContent);
            }
            else
            {
                return(State.ReadVariableLengthContent);
            }
        }