private void writeHeader( ByteString prefix, long upstreamSize, long metadataSize) throws IOException { Buffer header = new Buffer(); header.write(prefix); header.writeLong(upstreamSize); header.writeLong(metadataSize); if (header.size() != FILE_HEADER_SIZE) throw new IllegalArgumentException(); FileOperator fileOperator = new FileOperator(file.getChannel()); fileOperator.write(0, header, FILE_HEADER_SIZE); }
/** Returns a new response body that transmits {@code content}. */ public static ResponseBody create(final @Nullable MediaType contentType, byte[] content) { Buffer buffer = new Buffer().write(content); return create(contentType, content.length, buffer); }
/** * Sets the response body to {@code body}, chunked every {@code maxChunkSize} bytes. */ public MockResponse setChunkedBody(Buffer body, int maxChunkSize) { removeHeader("Content-Length"); headers.add(CHUNKED_BODY_HEADER); Buffer bytesOut = new Buffer(); while (!body.exhausted()) { long chunkSize = Math.min(body.size(), maxChunkSize); bytesOut.writeHexadecimalUnsignedLong(chunkSize); bytesOut.writeUtf8("\r\n"); bytesOut.write(body, chunkSize); bytesOut.writeUtf8("\r\n"); } bytesOut.writeUtf8("0\r\n"); // Last chunk. Trailers follow! this.body = bytesOut; return this; }
@Test public void writePrefixDoesntSplit() { Buffer sink = new Buffer(); sink.writeUtf8(repeat('b', 10)); Buffer source = new Buffer(); source.writeUtf8(repeat('a', SEGMENT_SIZE * 2)); sink.write(source, 20); assertEquals(asList(30), segmentSizes(sink)); assertEquals(asList(SEGMENT_SIZE - 20, SEGMENT_SIZE), segmentSizes(source)); assertEquals(30, sink.size()); assertEquals(SEGMENT_SIZE * 2 - 20, source.size()); }
/** * Send a close frame with optional code and reason. * * @param code Status code as defined by <a * href="http://tools.ietf.org/html/rfc6455#section-7.4">Section 7.4 of RFC 6455</a> or {@code 0}. * @param reason Reason for shutting down or {@code null}. */ void writeClose(int code, ByteString reason) throws IOException { ByteString payload = ByteString.EMPTY; if (code != 0 || reason != null) { if (code != 0) { validateCloseCode(code); } Buffer buffer = new Buffer(); buffer.writeShort(code); if (reason != null) { buffer.write(reason); } payload = buffer.readByteString(); } try { writeControlFrame(OPCODE_CONTROL_CLOSE, payload); } finally { writerClosed = true; } }
/** Returns a new response body that transmits {@code content}. */ public static ResponseBody create(@Nullable MediaType contentType, ByteString content) { Buffer buffer = new Buffer().write(content); return create(contentType, content.size(), buffer); }
@Test public void writePrefixDoesntSplitButRequiresCompact() throws Exception { Buffer sink = new Buffer(); sink.writeUtf8(repeat('b', SEGMENT_SIZE - 10)); // limit = size - 10 sink.readUtf8(SEGMENT_SIZE - 20); // pos = size = 20 Buffer source = new Buffer(); source.writeUtf8(repeat('a', SEGMENT_SIZE * 2)); sink.write(source, 20); assertEquals(asList(30), segmentSizes(sink)); assertEquals(asList(SEGMENT_SIZE - 20, SEGMENT_SIZE), segmentSizes(source)); assertEquals(30, sink.size()); assertEquals(SEGMENT_SIZE * 2 - 20, source.size()); }
@Test public void gunzip_withExtra() throws Exception { Buffer gzipped = new Buffer(); gzipped.write(gzipHeaderWithFlags((byte) 0x04)); gzipped.writeShort(TestUtil.reverseBytes((short) 7)); // little endian extra length gzipped.write("blubber".getBytes(UTF_8), 0, 7); gzipped.write(deflated); gzipped.write(gzipTrailer); assertGzipped(gzipped); }
@Override public void write(Buffer source, long byteCount) throws IOException { assert (!Thread.holdsLock(Http2Stream.this)); sendBuffer.write(source, byteCount); while (sendBuffer.size() >= EMIT_BUFFER_SIZE) { emitFrame(false); } }
private void writeMetadata(long upstreamSize) throws IOException { Buffer metadataBuffer = new Buffer(); metadataBuffer.write(metadata); FileOperator fileOperator = new FileOperator(file.getChannel()); fileOperator.write(FILE_HEADER_SIZE + upstreamSize, metadataBuffer, metadata.size()); }
private List<Certificate> readCertificateList(BufferedSource source) throws IOException { int length = readInt(source); if (length == -1) return Collections.emptyList(); // OkHttp v1.2 used -1 to indicate null. try { CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509"); List<Certificate> result = new ArrayList<>(length); for (int i = 0; i < length; i++) { String line = source.readUtf8LineStrict(); Buffer bytes = new Buffer(); bytes.write(ByteString.decodeBase64(line)); result.add(certificateFactory.generateCertificate(bytes.inputStream())); } return result; } catch (CertificateException e) { throw new IOException(e.getMessage()); } }
@Override public void write(Buffer source, long byteCount) throws IOException { if (closed) throw new IOException("closed"); buffer.write(source, byteCount); // Determine if this is a buffered write which we can defer until close() flushes. boolean deferWrite = isFirstFrame && contentLength != -1 && buffer.size() > contentLength - 8192 /* segment size */; long emitCount = buffer.completeSegmentByteCount(); if (emitCount > 0 && !deferWrite) { writeMessageFrame(formatOpcode, emitCount, isFirstFrame, false /* final */); isFirstFrame = false; } }
/** * Reads a double-quoted string, unescaping quoted pairs like {@code \"} to the 2nd character in * each sequence. Returns the unescaped string, or null if the buffer isn't prefixed with a * double-quoted string. */ private static String readQuotedString(Buffer buffer) { if (buffer.readByte() != '\"') throw new IllegalArgumentException(); Buffer result = new Buffer(); while (true) { long i = buffer.indexOfElement(QUOTED_STRING_DELIMITERS); if (i == -1L) return null; // Unterminated quoted string. if (buffer.getByte(i) == '"') { result.write(buffer, i); buffer.readByte(); // Consume '"'. return result.readUtf8(); } if (buffer.size() == i + 1L) return null; // Dangling escape. result.write(buffer, i); buffer.readByte(); // Consume '\'. result.write(buffer, 1L); // The escaped character. } }
/** * Peeks up to {@code byteCount} bytes from the response body and returns them as a new response * body. If fewer than {@code byteCount} bytes are in the response body, the full response body is * returned. If more than {@code byteCount} bytes are in the response body, the returned value * will be truncated to {@code byteCount} bytes. * * <p>It is an error to call this method after the body has been consumed. * * <p><strong>Warning:</strong> this method loads the requested bytes into memory. Most * applications should set a modest limit on {@code byteCount}, such as 1 MiB. */ public ResponseBody peekBody(long byteCount) throws IOException { BufferedSource peeked = body.source().peek(); Buffer buffer = new Buffer(); peeked.request(byteCount); buffer.write(peeked, Math.min(byteCount, peeked.getBuffer().size())); return ResponseBody.create(body.contentType(), buffer.size(), buffer); }
void writeByteString(ByteString data) throws IOException { if (useCompression && Huffman.get().encodedLength(data) < data.size()) { Buffer huffmanBuffer = new Buffer(); Huffman.get().encode(data, huffmanBuffer); ByteString huffmanBytes = huffmanBuffer.readByteString(); writeInt(huffmanBytes.size(), PREFIX_7_BITS, 0x80); out.write(huffmanBytes); } else { writeInt(data.size(), PREFIX_7_BITS, 0); out.write(data); } }
private MockResponse getRequest(RecordedRequest request, byte[] body, String contentType) { if (request.getMethod().equals("OPTIONS")) { return new MockResponse().setResponseCode(200).setHeader("Allow", "GET, OPTIONS, HEAD, TRACE"); } Buffer buf = new Buffer(); buf.write(body); MockResponse response = new MockResponse() .setHeader("Content-Length", body.length) .setBody(buf) .setResponseCode(200); if (contentType != null) { response = response.setHeader("Content-Type", contentType); } return response; }
@Test public void readCodePointBeyondUnicodeMaximum() throws Exception { // A 4-byte encoding with data above the U+10ffff Unicode maximum. Buffer buffer = new Buffer(); buffer.write(ByteString.decodeHex("f4908080")); assertEquals(REPLACEMENT_CODE_POINT, buffer.readUtf8CodePoint()); assertTrue(buffer.exhausted()); }
private MockResponse patchRequest(RecordedRequest request, String expectedRequestContent, String contentType, byte[] responseBody) { assertEquals("PATCH", request.getMethod()); assertTrue("Invalid request content-length", Integer.parseInt(request.getHeader("Content-Length")) > 0); String requestContentType = request.getHeader("Content-Type"); assertNotNull("No content-type", requestContentType); Charset charset = StandardCharsets.ISO_8859_1; if (requestContentType.contains("charset=")) { String charsetName = requestContentType.split("charset=")[1]; charset = Charset.forName(charsetName); } assertEquals("Invalid request body", expectedRequestContent, request.getBody().readString(charset)); Buffer buf = new Buffer(); buf.write(responseBody); return new MockResponse().setResponseCode(201) .setHeader("Content-Length", responseBody.length) .setHeader("Content-Type", contentType) .setBody(buf); }
@Test public void readSurrogateCodePoint() throws Exception { Buffer buffer = new Buffer(); buffer.write(ByteString.decodeHex("eda080")); assertEquals(REPLACEMENT_CODE_POINT, buffer.readUtf8CodePoint()); assertTrue(buffer.exhausted()); buffer.write(ByteString.decodeHex("edbfbf")); assertEquals(REPLACEMENT_CODE_POINT, buffer.readUtf8CodePoint()); assertTrue(buffer.exhausted()); }
private MockResponse postRequest(RecordedRequest request, String expectedRequestContent, String location, String contentType, byte[] responseBody) { assertEquals(1, request.getHeaders().values("Content-Length").size()); assertTrue("Invalid request content-length", Integer.parseInt(request.getHeader("Content-Length")) > 0); String requestContentType = request.getHeader("Content-Type"); assertNotNull("No content-type", requestContentType); Charset charset = StandardCharsets.ISO_8859_1; if (requestContentType.contains("charset=")) { String charsetName = requestContentType.split("charset=")[1]; charset = Charset.forName(charsetName); } assertEquals("Invalid request body", expectedRequestContent, request.getBody().readString(charset)); Buffer buf = new Buffer(); buf.write(responseBody); return new MockResponse() .setHeader("Location", baseUrl + location) .setHeader("Content-Type", contentType) .setHeader("Content-Length", responseBody.length) .setBody(buf) .setResponseCode(201); }