@Override public Integer parse(ByteBuf in) { AppendableCharSequence seq = sequenceRef.get(); seq.reset(); boolean foundStart = false; for (;;) { char c = ((char) in.readUnsignedByte()); if (c == '{') { foundStart = true; } else if (c == '}') { return Integer.parseInt(seq.toString()); } else if (foundStart) { seq.append(c); } } }
private static String[] splitInitialLine(AppendableCharSequence sb) { int aStart; int aEnd; int bStart; int bEnd; int cStart; int cEnd; aStart = findNonWhitespace(sb, 0); aEnd = findWhitespace(sb, aStart); bStart = findNonWhitespace(sb, aEnd); bEnd = findWhitespace(sb, bStart); cStart = findNonWhitespace(sb, bEnd); cEnd = findEndOfString(sb); return new String[] { sb.substring(aStart, aEnd), sb.substring(bStart, bEnd), cStart < cEnd? sb.substring(cStart, cEnd) : "" }; }
private static String[] splitInitialLine(AppendableCharSequence sb) { int aStart; int aEnd; int bStart; int bEnd; int cStart; int cEnd; aStart = findNonWhitespace(sb, 0); aEnd = findWhitespace(sb, aStart); bStart = findNonWhitespace(sb, aEnd); bEnd = findWhitespace(sb, bStart); cStart = findNonWhitespace(sb, bEnd); cEnd = findEndOfString(sb); return new String[]{ sb.substring(aStart, aEnd), sb.substring(bStart, bEnd), cStart < cEnd ? sb.substring(cStart, cEnd) : ""}; }
public AppendableCharSequence get() { AppendableCharSequence sequence = reference.get(); if (sequence == null) { sequence = newCharSeq(); } reference = new SoftReference<>(sequence); return sequence; }
@Override public String parse(ByteBuf in) { AppendableCharSequence seq = sequenceRef.get(); seq.reset(); size = 0; expectedSize = -1; for (;;) { char c = ((char) in.readUnsignedByte()); if (c == '{' && expectedSize < 0) { in.readerIndex(in.readerIndex() - 1); expectedSize = sizeParser.parse(in); in.readerIndex(in.readerIndex() + 2); // Skip CRLF } else if (expectedSize >= 0) { seq.reset(); seq.append(c); size++; while (size < expectedSize) { c = ((char) in.readUnsignedByte()); seq.append(c); size++; } return seq.toString(); } else if (Character.isWhitespace(c)) { continue; } else { in.readerIndex(in.readerIndex() - 1); return stringParser.parse(in); } } }
@Override public String parse(ByteBuf buffer) { AppendableCharSequence sequence = sequenceReference.get(); int readerIndex = buffer.readerIndex(); try { super.parse(buffer); } catch (Signal e) { e.expect(REPLAYING_SIGNAL); buffer.readerIndex(readerIndex + size); return sequence.toString(); } return sequence.toString(); }
private void append(AppendableCharSequence seq, char c) { if (size >= maxStringLength) { throw new TooLongFrameException("String is larger than " + maxStringLength + " bytes."); } size++; seq.append(c); }
@Override public String parse(ByteBuf in) { AppendableCharSequence seq = sequenceRef.get(); seq.reset(); size = 0; for (;;) { char nextByte = (char) in.readUnsignedByte(); if (Character.isWhitespace(nextByte)) { if (size > 0) { break; } } else if (!Character.isLetterOrDigit(nextByte) && nextByte != '.' && nextByte != '-') { in.readerIndex(in.readerIndex() - 1); break; } else { if (size >= maxWordLength) { throw new TooLongFrameException( "Word is larger than " + maxWordLength + " bytes."); } size++; seq.append(nextByte); } } return seq.toString(); }
/** * Creates a new instance with the specified parameters. */ protected HttpObjectDecoder( int maxInitialLineLength, int maxHeaderSize, int maxChunkSize, boolean chunkedSupported, boolean validateHeaders) { if (maxInitialLineLength <= 0) { throw new IllegalArgumentException( "maxInitialLineLength must be a positive integer: " + maxInitialLineLength); } if (maxHeaderSize <= 0) { throw new IllegalArgumentException( "maxHeaderSize must be a positive integer: " + maxHeaderSize); } if (maxChunkSize <= 0) { throw new IllegalArgumentException( "maxChunkSize must be a positive integer: " + maxChunkSize); } this.maxChunkSize = maxChunkSize; this.chunkedSupported = chunkedSupported; this.validateHeaders = validateHeaders; AppendableCharSequence seq = new AppendableCharSequence(128); lineParser = new LineParser(seq, maxInitialLineLength); headerParser = new HeaderParser(seq, maxHeaderSize); }
private void splitHeader(AppendableCharSequence sb) { final int length = sb.length(); int nameStart; int nameEnd; int colonEnd; int valueStart; int valueEnd; nameStart = findNonWhitespace(sb, 0); for (nameEnd = nameStart; nameEnd < length; nameEnd ++) { char ch = sb.charAt(nameEnd); if (ch == ':' || Character.isWhitespace(ch)) { break; } } for (colonEnd = nameEnd; colonEnd < length; colonEnd ++) { if (sb.charAt(colonEnd) == ':') { colonEnd ++; break; } } name = sb.substring(nameStart, nameEnd); valueStart = findNonWhitespace(sb, colonEnd); if (valueStart == length) { value = EMPTY_VALUE; } else { valueEnd = findEndOfString(sb); value = sb.substring(valueStart, valueEnd); } }
public AppendableCharSequence parse(ByteBuf buffer) { final int oldSize = size; seq.reset(); int i = buffer.forEachByte(this); if (i == -1) { size = oldSize; return null; } buffer.readerIndex(i + 1); return seq; }
private LastHttpContent readTrailingHeaders(ByteBuf buffer) { headerSize = 0; AppendableCharSequence line = readHeader(buffer); String lastHeader = null; if (line.length() > 0) { LastHttpContent trailer = new DefaultLastHttpContent(Unpooled.EMPTY_BUFFER, validateHeaders); do { char firstChar = line.charAt(0); if (lastHeader != null && (firstChar == ' ' || firstChar == '\t')) { List<String> current = trailer.trailingHeaders().getAll(lastHeader); if (!current.isEmpty()) { int lastPos = current.size() - 1; String newString = current.get(lastPos) + line.toString().trim(); current.set(lastPos, newString); } else { // Content-Length, Transfer-Encoding, or Trailer } } else { String[] header = splitHeader(line); String name = header[0]; if (!HttpHeaders.equalsIgnoreCase(name, HttpHeaders.Names.CONTENT_LENGTH) && !HttpHeaders.equalsIgnoreCase(name, HttpHeaders.Names.TRANSFER_ENCODING) && !HttpHeaders.equalsIgnoreCase(name, HttpHeaders.Names.TRAILER)) { trailer.trailingHeaders().add(name, header[1]); } lastHeader = name; } line = readHeader(buffer); } while (line.length() > 0); return trailer; } return LastHttpContent.EMPTY_LAST_CONTENT; }
private AppendableCharSequence readHeader(ByteBuf buffer) { AppendableCharSequence sb = this.sb; sb.reset(); int headerSize = this.headerSize; loop: for (; ; ) { char nextByte = (char) buffer.readByte(); headerSize++; switch (nextByte) { case HttpConstants.CR: nextByte = (char) buffer.readByte(); headerSize++; if (nextByte == HttpConstants.LF) { break loop; } break; case HttpConstants.LF: break loop; } // Abort decoding if the header part is too large. if (headerSize >= maxHeaderSize) { // TODO: Respond with Bad Request and discard the traffic // or close the connection. // No need to notify the upstream handlers - just log. // If decoding a response, just throw an exception. throw new TooLongFrameException( "HTTP header is larger than " + maxHeaderSize + " bytes."); } sb.append(nextByte); } this.headerSize = headerSize; return sb; }
private AppendableCharSequence readLine(ByteBuf buffer, int maxLineLength) { AppendableCharSequence sb = this.sb; sb.reset(); int lineLength = 0; while (true) { byte nextByte = buffer.readByte(); if (nextByte == HttpConstants.CR) { nextByte = buffer.readByte(); if (nextByte == HttpConstants.LF) { return sb; } } else if (nextByte == HttpConstants.LF) { return sb; } else { if (lineLength >= maxLineLength) { // TODO: Respond with Bad Request and discard the traffic // or close the connection. // No need to notify the upstream handlers - just log. // If decoding a response, just throw an exception. throw new TooLongFrameException( "An HTTP line is larger than " + maxLineLength + " bytes."); } lineLength++; sb.append((char) nextByte); } } }
private static String[] splitHeader(AppendableCharSequence sb) { final int length = sb.length(); int nameStart; int nameEnd; int colonEnd; int valueStart; int valueEnd; nameStart = findNonWhitespace(sb, 0); for (nameEnd = nameStart; nameEnd < length; nameEnd++) { char ch = sb.charAt(nameEnd); if (ch == ':' || Character.isWhitespace(ch)) { break; } } for (colonEnd = nameEnd; colonEnd < length; colonEnd++) { if (sb.charAt(colonEnd) == ':') { colonEnd++; break; } } valueStart = findNonWhitespace(sb, colonEnd); if (valueStart == length) { return new String[]{ sb.substring(nameStart, nameEnd), "" }; } valueEnd = findEndOfString(sb); return new String[]{ sb.substring(nameStart, nameEnd), sb.substring(valueStart, valueEnd) }; }
private AppendableCharSequence readHeader(ByteBuf buffer) { AppendableCharSequence sb = this.sb; sb.reset(); int headerSize = this.headerSize; loop: for (;;) { char nextByte = (char) buffer.readByte(); headerSize ++; switch (nextByte) { case HttpConstants.CR: nextByte = (char) buffer.readByte(); headerSize ++; if (nextByte == HttpConstants.LF) { break loop; } break; case HttpConstants.LF: break loop; } // Abort decoding if the header part is too large. if (headerSize >= maxHeaderSize) { // TODO: Respond with Bad Request and discard the traffic // or close the connection. // No need to notify the upstream handlers - just log. // If decoding a response, just throw an exception. throw new TooLongFrameException( "HTTP header is larger than " + maxHeaderSize + " bytes."); } sb.append(nextByte); } this.headerSize = headerSize; return sb; }
private AppendableCharSequence readLine(ByteBuf buffer, int maxLineLength) { AppendableCharSequence sb = this.sb; sb.reset(); int lineLength = 0; while (true) { byte nextByte = buffer.readByte(); if (nextByte == HttpConstants.CR) { nextByte = buffer.readByte(); if (nextByte == HttpConstants.LF) { return sb; } } else if (nextByte == HttpConstants.LF) { return sb; } else { if (lineLength >= maxLineLength) { // TODO: Respond with Bad Request and discard the traffic // or close the connection. // No need to notify the upstream handlers - just log. // If decoding a response, just throw an exception. throw new TooLongFrameException( "An HTTP line is larger than " + maxLineLength + " bytes."); } lineLength ++; sb.append((char) nextByte); } } }
private static String[] splitHeader(AppendableCharSequence sb) { final int length = sb.length(); int nameStart; int nameEnd; int colonEnd; int valueStart; int valueEnd; nameStart = findNonWhitespace(sb, 0); for (nameEnd = nameStart; nameEnd < length; nameEnd ++) { char ch = sb.charAt(nameEnd); if (ch == ':' || Character.isWhitespace(ch)) { break; } } for (colonEnd = nameEnd; colonEnd < length; colonEnd ++) { if (sb.charAt(colonEnd) == ':') { colonEnd ++; break; } } valueStart = findNonWhitespace(sb, colonEnd); if (valueStart == length) { return new String[] { sb.substring(nameStart, nameEnd), "" }; } valueEnd = findEndOfString(sb); return new String[] { sb.substring(nameStart, nameEnd), sb.substring(valueStart, valueEnd) }; }
private AppendableCharSequence newCharSeq() { return new AppendableCharSequence(defaultResponseBufferSize); }
public String parse(ByteBuf buffer) { AppendableCharSequence seq = sequenceRef.get(); seq.reset(); size = 0; boolean isQuoted = false; char previousChar = ' '; for (;;) { char c; try { c = ((char) buffer.readUnsignedByte()); } catch (IndexOutOfBoundsException e) { return seq.toString(); } if (Character.isWhitespace(c)) { if (isQuoted) { append(seq, c); } else if (size > 0) { break; } } else if (c == QUOTE && previousChar != BACKSLASH) { if (size == 0 && !isQuoted) { // Start Quote isQuoted = true; } else { // End Quote break; } } else if (!isQuoted && (c == ')' || c == '(')) { buffer.readerIndex(buffer.readerIndex() - 1); break; } else { append(seq, c); } // Always ignore any characters after a backslash if (previousChar != BACKSLASH) { previousChar = c; } else { previousChar = ' '; } } return seq.toString(); }
private State readHeaders(ByteBuf buffer) { final HttpMessage message = this.message; final HttpHeaders headers = message.headers(); AppendableCharSequence line = headerParser.parse(buffer); if (line == null) { return null; } if (line.length() > 0) { do { char firstChar = line.charAt(0); if (name != null && (firstChar == ' ' || firstChar == '\t')) { StringBuilder buf = new StringBuilder(value.length() + line.length() + 1); buf.append(value) .append(' ') .append(line.toString().trim()); value = buf.toString(); } else { if (name != null) { headers.add(name, value); } splitHeader(line); } line = headerParser.parse(buffer); if (line == null) { return null; } } while (line.length() > 0); } // Add the last header. if (name != null) { headers.add(name, value); } // reset name and value fields name = null; value = null; State nextState; if (isContentAlwaysEmpty(message)) { HttpHeaders.removeTransferEncodingChunked(message); nextState = State.SKIP_CONTROL_CHARS; } else if (HttpHeaders.isTransferEncodingChunked(message)) { nextState = State.READ_CHUNK_SIZE; } else if (contentLength() >= 0) { nextState = State.READ_FIXED_LENGTH_CONTENT; } else { nextState = State.READ_VARIABLE_LENGTH_CONTENT; } return nextState; }
private LastHttpContent readTrailingHeaders(ByteBuf buffer) { AppendableCharSequence line = headerParser.parse(buffer); if (line == null) { return null; } CharSequence lastHeader = null; if (line.length() > 0) { LastHttpContent trailer = this.trailer; if (trailer == null) { trailer = this.trailer = new DefaultLastHttpContent(Unpooled.EMPTY_BUFFER, validateHeaders); } do { char firstChar = line.charAt(0); if (lastHeader != null && (firstChar == ' ' || firstChar == '\t')) { List<String> current = trailer.trailingHeaders().getAll(lastHeader); if (!current.isEmpty()) { int lastPos = current.size() - 1; String lineTrimmed = line.toString().trim(); CharSequence currentLastPos = current.get(lastPos); StringBuilder b = new StringBuilder(currentLastPos.length() + lineTrimmed.length()); b.append(currentLastPos) .append(lineTrimmed); current.set(lastPos, b.toString()); } else { // Content-Length, Transfer-Encoding, or Trailer } } else { splitHeader(line); CharSequence headerName = name; if (!HttpHeaders.equalsIgnoreCase(HttpHeaders.Names.CONTENT_LENGTH, headerName) && !HttpHeaders.equalsIgnoreCase(HttpHeaders.Names.TRANSFER_ENCODING, headerName) && !HttpHeaders.equalsIgnoreCase(HttpHeaders.Names.TRAILER, headerName)) { trailer.trailingHeaders().add(headerName, value); } lastHeader = name; // reset name and value fields name = null; value = null; } line = headerParser.parse(buffer); if (line == null) { return null; } } while (line.length() > 0); this.trailer = null; return trailer; } return LastHttpContent.EMPTY_LAST_CONTENT; }
HeaderParser(AppendableCharSequence seq, int maxLength) { this.seq = seq; this.maxLength = maxLength; }
LineParser(AppendableCharSequence seq, int maxLength) { super(seq, maxLength); }
@Override public AppendableCharSequence parse(ByteBuf buffer) { reset(); return super.parse(buffer); }
private State readHeaders(ByteBuf buffer) { headerSize = 0; final HttpMessage message = this.message; final HttpHeaders headers = message.headers(); AppendableCharSequence line = readHeader(buffer); String name = null; String value = null; if (line.length() > 0) { headers.clear(); do { char firstChar = line.charAt(0); if (name != null && (firstChar == ' ' || firstChar == '\t')) { value = value + ' ' + line.toString().trim(); } else { if (name != null) { headers.add(name, value); } String[] header = splitHeader(line); name = header[0]; value = header[1]; } line = readHeader(buffer); } while (line.length() > 0); // Add the last header. if (name != null) { headers.add(name, value); } } State nextState; if (isContentAlwaysEmpty(message)) { HttpHeaders.removeTransferEncodingChunked(message); nextState = State.SKIP_CONTROL_CHARS; } else if (HttpHeaders.isTransferEncodingChunked(message)) { nextState = State.READ_CHUNK_SIZE; } else if (contentLength() >= 0) { nextState = State.READ_FIXED_LENGTH_CONTENT; } else { nextState = State.READ_VARIABLE_LENGTH_CONTENT; } return nextState; }