public ByteBuffer generate(short version, Fields headers) { // TODO: ByteArrayOutputStream is quite inefficient, but grows on demand; optimize using // ByteBuffer ? final Charset iso1 = StandardCharsets.ISO_8859_1; ByteArrayOutputStream buffer = new ByteArrayOutputStream(headers.getSize() * 64); writeCount(version, buffer, headers.getSize()); for (Fields.Field header : headers) { String name = header.getName().toLowerCase(Locale.ENGLISH); byte[] nameBytes = name.getBytes(iso1); writeNameLength(version, buffer, nameBytes.length); buffer.write(nameBytes, 0, nameBytes.length); // Most common path first String value = header.getValue(); byte[] valueBytes = value.getBytes(iso1); if (header.hasMultipleValues()) { List<String> values = header.getValues(); for (int i = 1; i < values.size(); ++i) { byte[] moreValueBytes = values.get(i).getBytes(iso1); byte[] newValueBytes = new byte[valueBytes.length + 1 + moreValueBytes.length]; System.arraycopy(valueBytes, 0, newValueBytes, 0, valueBytes.length); newValueBytes[valueBytes.length] = 0; System.arraycopy( moreValueBytes, 0, newValueBytes, valueBytes.length + 1, moreValueBytes.length); valueBytes = newValueBytes; } } writeValueLength(version, buffer, valueBytes.length); buffer.write(valueBytes, 0, valueBytes.length); } return compress(version, buffer.toByteArray()); }
private static ByteBuffer convertFields(String contentDisposition, Fields fields) { try { if (fields == null || fields.isEmpty()) { contentDisposition += "\r\n"; return ByteBuffer.wrap(contentDisposition.getBytes(StandardCharsets.US_ASCII)); } ByteArrayOutputStream buffer = new ByteArrayOutputStream((fields.getSize() + 1) * contentDisposition.length()); buffer.write(contentDisposition.getBytes(StandardCharsets.US_ASCII)); for (Fields.Field field : fields) { buffer.write(field.getName().getBytes(StandardCharsets.US_ASCII)); buffer.write(COLON_SPACE_BYTES); buffer.write(field.getValue().getBytes(StandardCharsets.UTF_8)); buffer.write(CR_LF_BYTES); } buffer.write(CR_LF_BYTES); return ByteBuffer.wrap(buffer.toByteArray()); } catch (IOException x) { throw new RuntimeIOException(x); } }
@Override public void onReply(Stream stream, ReplyInfo replyInfo) { HttpExchange exchange = getHttpExchange(); if (exchange == null) return; try { HttpResponse response = exchange.getResponse(); Fields fields = replyInfo.getHeaders(); short spdy = stream.getSession().getVersion(); HttpVersion version = HttpVersion.fromString(fields.get(HTTPSPDYHeader.VERSION.name(spdy)).getValue()); response.version(version); String[] status = fields.get(HTTPSPDYHeader.STATUS.name(spdy)).getValue().split(" ", 2); Integer code = Integer.parseInt(status[0]); response.status(code); String reason = status.length < 2 ? HttpStatus.getMessage(code) : status[1]; response.reason(reason); if (responseBegin(exchange)) { for (Fields.Field field : fields) { String name = field.getName(); if (HTTPSPDYHeader.from(spdy, name) != null) continue; // TODO: handle multiple values properly HttpField httpField = new HttpField(name, field.getValue()); responseHeader(exchange, httpField); } if (responseHeaders(exchange)) { if (replyInfo.isClose()) { responseSuccess(exchange); } } } } catch (Exception x) { responseFailure(x); } }