ILastHttpContent ReadTrailingHeaders(IByteBuffer buffer) { AppendableCharSequence line = this.headerParser.Parse(buffer); if (line == null) { return(null); } AsciiString lastHeader = null; if (line.Count > 0) { ILastHttpContent trailingHeaders = this.trailer; if (trailingHeaders == null) { trailingHeaders = new DefaultLastHttpContent(Unpooled.Empty, this.ValidateHeaders); this.trailer = trailingHeaders; } do { byte firstChar = line.Bytes[0]; if (lastHeader != null && (firstChar == ' ' || firstChar == '\t')) { IList <ICharSequence> current = trailingHeaders.TrailingHeaders.GetAll(lastHeader); if (current.Count > 0) { int lastPos = current.Count - 1; ICharSequence lineTrimmed = CharUtil.Trim(line); current[lastPos] = new AsciiString($"{current[lastPos]} {lineTrimmed}"); } } else { this.SplitHeader(line); AsciiString headerName = this.name; if (!HttpHeaderNames.ContentLength.ContentEqualsIgnoreCase(headerName) && !HttpHeaderNames.TransferEncoding.ContentEqualsIgnoreCase(headerName) && !HttpHeaderNames.Trailer.ContentEqualsIgnoreCase(headerName)) { trailingHeaders.TrailingHeaders.Add(headerName, this.value); } lastHeader = this.name; // reset name and value fields this.name = null; this.value = null; } line = this.headerParser.Parse(buffer); if (line == null) { return(null); } } while (line.Count > 0); this.trailer = null; return(trailingHeaders); } return(EmptyLastHttpContent.Default); }
private ILastHttpContent ReadTrailingHeaders(IByteBuffer buffer) { AppendableCharSequence line = _headerParser.Parse(buffer); if (line is null) { return(null); } ILastHttpContent trailingHeaders = _trailer; if (0u >= (uint)line.Count && trailingHeaders is null) { // We have received the empty line which signals the trailer is complete and did not parse any trailers // before. Just return an empty last content to reduce allocations. return(EmptyLastHttpContent.Default); } AsciiString lastHeader = null; if (trailingHeaders is null) { trailingHeaders = new DefaultLastHttpContent(Unpooled.Empty, ValidateHeaders); _trailer = trailingHeaders; } while ((uint)line.Count > 0u) { byte firstChar = line.Bytes[0]; if (lastHeader is object && (firstChar == c_space || firstChar == c_tab)) { IList <ICharSequence> current = trailingHeaders.TrailingHeaders.GetAll(lastHeader); if ((uint)current.Count > 0u) { int lastPos = current.Count - 1; //please do not make one line from below code //as it breaks +XX:OptimizeStringConcat optimization ICharSequence lineTrimmed = CharUtil.Trim(line); current[lastPos] = new AsciiString($"{current[lastPos]}{lineTrimmed}"); } } else { SplitHeader(line); AsciiString headerName = _name; if (!HttpHeaderNames.ContentLength.ContentEqualsIgnoreCase(headerName) && !HttpHeaderNames.TransferEncoding.ContentEqualsIgnoreCase(headerName) && !HttpHeaderNames.Trailer.ContentEqualsIgnoreCase(headerName)) { _ = trailingHeaders.TrailingHeaders.Add(headerName, _value); } lastHeader = _name; // reset name and value fields _name = null; _value = null; } line = _headerParser.Parse(buffer); if (line is null) { return(null); } } _trailer = null; return(trailingHeaders); }
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); } }
State?ReadHeaders(IByteBuffer buffer) { IHttpMessage httpMessage = this.message; HttpHeaders headers = httpMessage.Headers; AppendableCharSequence line = this.headerParser.Parse(buffer); if (line == null) { return(null); } // ReSharper disable once ConvertIfDoToWhile if (line.Count > 0) { do { byte firstChar = line.Bytes[0]; if (this.name != null && (firstChar == ' ' || firstChar == '\t')) { ICharSequence trimmedLine = CharUtil.Trim(line); this.value = new AsciiString($"{this.value} {trimmedLine}"); } else { if (this.name != null) { headers.Add(this.name, this.value); } this.SplitHeader(line); } line = this.headerParser.Parse(buffer); if (line == null) { return(null); } } while (line.Count > 0); } // Add the last header. if (this.name != null) { headers.Add(this.name, this.value); } // reset name and value fields this.name = null; this.value = null; State nextState; if (this.IsContentAlwaysEmpty(httpMessage)) { HttpUtil.SetTransferEncodingChunked(httpMessage, false); nextState = State.SkipControlChars; } else if (HttpUtil.IsTransferEncodingChunked(httpMessage)) { nextState = State.ReadChunkSize; } else if (this.ContentLength() >= 0) { nextState = State.ReadFixedLengthContent; } else { nextState = State.ReadVariableLengthContent; } return(nextState); }
// // Check from the request ContentType if this request is a Multipart request. // return an array of String if multipartDataBoundary exists with the multipartDataBoundary // as first element, charset if any as second (missing if not set), else null // protected internal static ICharSequence[] GetMultipartDataBoundary(ICharSequence contentType) { // Check if Post using "multipart/form-data; boundary=--89421926422648 [; charset=xxx]" ICharSequence[] headerContentType = SplitHeaderContentType(contentType); AsciiString multiPartHeader = HttpHeaderValues.MultipartFormData; if (headerContentType[0].RegionMatchesIgnoreCase(0, multiPartHeader, 0, multiPartHeader.Count)) { int mrank; int crank; AsciiString boundaryHeader = HttpHeaderValues.Boundary; if (headerContentType[1].RegionMatchesIgnoreCase(0, boundaryHeader, 0, boundaryHeader.Count)) { mrank = 1; crank = 2; } else if (headerContentType[2].RegionMatchesIgnoreCase(0, boundaryHeader, 0, boundaryHeader.Count)) { mrank = 2; crank = 1; } else { return(null); } ICharSequence boundary = headerContentType[mrank].SubstringAfter(HttpConstants.EqualsSignChar); if (boundary is null) { ThrowHelper.ThrowErrorDataDecoderException_NeedBoundaryValue(); } if (boundary[0] == HttpConstants.DoubleQuoteChar) { ICharSequence bound = CharUtil.Trim(boundary); int index = bound.Count - 1; if (bound[index] == HttpConstants.DoubleQuoteChar) { boundary = bound.SubSequence(1, index); } } AsciiString charsetHeader = HttpHeaderValues.Charset; if (headerContentType[crank].RegionMatchesIgnoreCase(0, charsetHeader, 0, charsetHeader.Count)) { ICharSequence charset = headerContentType[crank].SubstringAfter(HttpConstants.EqualsSignChar); if (charset is object) { return(new[] { new StringCharSequence("--" + boundary.ToString()), charset }); } } return(new ICharSequence[] { new StringCharSequence("--" + boundary.ToString()) }); } return(null); }