private void parseBodyByContentLength(Buf in, BufRanges body, int clength) { body.add(); // there will be only 1 body part in.scanN(clength, body.ranges[0]); }
private boolean detectKeepAlive(Buf buf, RapidoidHelper helper, Bytes bytes, BufRange protocol, BufRanges headers) { IntWrap result = helper.integers[0]; boolean keepAliveByDefault = protocol.isEmpty() || bytes.get(protocol.last()) != '0'; // e.g. HTTP/1.1 // try to detect the opposite of the default if (keepAliveByDefault) { buf.scanLnLn(headers.reset(), result, (byte) 's', (byte) 'e'); // clo[se] } else { buf.scanLnLn(headers.reset(), result, (byte) 'v', (byte) 'e'); // keep-ali[ve] } int possibleConnHeaderPos = result.value; if (possibleConnHeaderPos < 0) return keepAliveByDefault; // no evidence of the opposite BufRange possibleConnHdr = headers.get(possibleConnHeaderPos); if (BytesUtil.startsWith(bytes, possibleConnHdr, CONNECTION, true)) { return !keepAliveByDefault; // detected the opposite of the default } return isKeepAlive(bytes, headers, helper, keepAliveByDefault); }
private boolean isKeepAlive(Bytes bytes, BufRanges headers, RapidoidHelper helper, boolean keepAliveByDefault) { BufRange connHdr = headers.getByPrefix(bytes, CONNECTION, false); return connHdr != null ? getKeepAliveValue(bytes, connHdr, helper) : keepAliveByDefault; }
public BufRange first() { return get(0); }
@SuppressWarnings("unchecked") public boolean parsePosted(Buf input, KeyValueRanges headersKV, BufRange rBody, KeyValueRanges posted, Map<String, List<Upload>> files, RapidoidHelper helper, Map<String, Object> dest) { BufRanges dataContentTypes = helper.ranges3.reset(); boolean completed = parseBody(input, headersKV, rBody, posted, dataContentTypes, files, helper); posted.toUrlDecodedParams(input, dest, dataContentTypes); return completed; }
@Override protected int state1(Channel ctx) { ctx.log("receiving response"); final BufRanges head = ctx.helper().ranges1.reset(); final BufRanges body = ctx.helper().ranges2.reset(); Buf in = ctx.input(); in.scanLnLn(head); Map<String, String> headers = head.toMap(in.bytes(), 1, head.count - 1, "\\s*\\:\\s*"); Map<String, String> headersLow = Msc.lowercase(headers); if ("chunked".equals(headersLow.get("transfer-encoding"))) { ctx.log("got chunked encoding"); parseChunkedBody(in, body); callback.onResult(in, head, body); } else if (headersLow.containsKey("content-length")) { ctx.log("got content length"); int clength = Integer.parseInt(headersLow.get("content-length")); parseBodyByContentLength(in, body, clength); callback.onResult(in, head, body); } else { // no content length is provided, read until connection is closed ctx.log("read until closed"); readBodyUntilClosed(ctx, body); callback.onResult(in, head, body); } ctx.log("done"); ctx.close(); // improve: keep-alive return STOP; }
public int add() { if (count >= max()) { throw U.rte("too many key-values!"); } return count++; }
public static int findBodyStart(byte[] response) { Bytes bytes = BytesUtil.from(response); BufRanges lines = new BufRanges(100); int pos = BytesUtil.parseLines(bytes, lines, 0, bytes.limit()); U.must(pos > 0, "Invalid HTTP response!"); return pos; }
public String str(Buf buf) { return str(buf.bytes()); }
public BufRange last() { return get(count - 1); }
public int parseHeaders(Buf buf, int from, int to, KeyValueRanges headersKV, RapidoidHelper helper) { int pos = buf.position(); int limit = buf.limit(); buf.position(from); buf.limit(to); BufRanges headers = helper.ranges2.reset(); buf.scanLnLn(headers); parseHeadersIntoKV(buf, headers, headersKV, null, helper); int bodyPos = buf.position(); buf.position(pos); buf.limit(limit); return bodyPos; }
public void add(int start, int length) { if (count >= max()) { throw U.rte("too many key-values!"); } ranges[count++].set(start, length); }
public static int findBodyStart(byte[] response) { Bytes bytes = BytesUtil.from(response); BufRanges lines = new BufRanges(100); int pos = BytesUtil.parseLines(bytes, lines, 0, bytes.limit()); U.must(pos > 0, "Invalid HTTP response!"); return pos; }
public String str(Buf buf) { return str(buf.bytes()); }
public static int parseLines(Bytes bytes, BufRanges lines, int start, int limit) { byte b0 = 0, b1 = 0; int ret = -1; int i; int from = start; for (i = start; i < limit; i++) { b0 = b1; b1 = bytes.get(i); if (b1 == LF) { int len; if (b0 == CR) { len = i - from - 1; } else { len = i - from; } if (len == 0) { ret = i + 1; break; } lines.add(from, len); from = i + 1; } } return ret; }
private boolean detectKeepAlive(Buf buf, RapidoidHelper helper, Bytes bytes, BufRange protocol, BufRanges headers) { IntWrap result = helper.integers[0]; boolean keepAliveByDefault = protocol.isEmpty() || bytes.get(protocol.last()) != '0'; // e.g. HTTP/1.1 // try to detect the opposite of the default if (keepAliveByDefault) { buf.scanLnLn(headers.reset(), result, (byte) 's', (byte) 'e'); // clo[se] } else { buf.scanLnLn(headers.reset(), result, (byte) 'v', (byte) 'e'); // keep-ali[ve] } int possibleConnHeaderPos = result.value; if (possibleConnHeaderPos < 0) return keepAliveByDefault; // no evidence of the opposite BufRange possibleConnHdr = headers.get(possibleConnHeaderPos); if (BytesUtil.startsWith(bytes, possibleConnHdr, CONNECTION, true)) { return !keepAliveByDefault; // detected the opposite of the default } return isKeepAlive(bytes, headers, helper, keepAliveByDefault); }
private boolean isJSON(Buf src, BufRanges contentTypes, int index) { if (contentTypes.count > 0) { U.must(contentTypes.count > index); BufRange ct = contentTypes.get(index); return !ct.isEmpty() && ct.str(src.bytes()).startsWith("application/json"); } else { return false; } }
@SuppressWarnings("unchecked") public boolean parsePosted(Buf input, KeyValueRanges headersKV, BufRange rBody, KeyValueRanges posted, Map<String, List<Upload>> files, RapidoidHelper helper, Map<String, Object> dest) { BufRanges dataContentTypes = helper.ranges3.reset(); boolean completed = parseBody(input, headersKV, rBody, posted, dataContentTypes, files, helper); posted.toUrlDecodedParams(input, dest, dataContentTypes); return completed; }
public int add() { if (count >= max()) { throw U.rte("too many key-values!"); } return count++; }
private void parseBody(Buf buf, RapidoidHelper helper) { BufRanges headers = helper.headers; BufRange body = helper.body; BufRange clen = headers.getByPrefix(buf.bytes(), CONTENT_LENGTH, false); if (clen != null) { BufRange clenValue = helper.ranges5.ranges[helper.ranges5.ranges.length - 1]; clenValue.setInterval(clen.start + CONTENT_LENGTH.length, clen.limit()); BytesUtil.trim(buf.bytes(), clenValue); long len = buf.getN(clenValue); U.must(len >= 0 && len <= Integer.MAX_VALUE, "Invalid body size!"); buf.scanN((int) len, body); Log.debug("Request body complete", "range", body); } else { body.reset(); } }