@Override public void sendRequest(ClientRequest request, ClientCallback<ClientExchange> clientCallback) { request.getRequestHeaders().put(PATH, request.getPath()); request.getRequestHeaders().put(SCHEME, "https"); request.getRequestHeaders().put(VERSION, request.getProtocol().toString()); request.getRequestHeaders().put(METHOD, request.getMethod().toString()); request.getRequestHeaders().put(HOST, request.getRequestHeaders().getFirst(Headers.HOST)); request.getRequestHeaders().remove(Headers.HOST); SpdySynStreamStreamSinkChannel sinkChannel; try { sinkChannel = spdyChannel.createStream(request.getRequestHeaders()); } catch (IOException e) { clientCallback.failed(e); return; } SpdyClientExchange exchange = new SpdyClientExchange(this, sinkChannel, request); currentExchanges.put(sinkChannel.getStreamId(), exchange); boolean hasContent = true; String fixedLengthString = request.getRequestHeaders().getFirst(CONTENT_LENGTH); String transferEncodingString = request.getRequestHeaders().getLast(TRANSFER_ENCODING); if (fixedLengthString != null) { try { long length = Long.parseLong(fixedLengthString); hasContent = length != 0; } catch (NumberFormatException e) { handleError(new IOException(e)); return; } } else if (transferEncodingString == null) { hasContent = false; } if (clientCallback != null) { clientCallback.completed(exchange); } if (!hasContent) { // if there is no content we flush the response channel. // otherwise it is up to the user try { sinkChannel.shutdownWrites(); if (!sinkChannel.flush()) { sinkChannel .getWriteSetter() .set( ChannelListeners.flushingChannelListener( null, new ChannelExceptionHandler<StreamSinkChannel>() { @Override public void handleException( StreamSinkChannel channel, IOException exception) { handleError(exception); } })); sinkChannel.resumeWrites(); } } catch (IOException e) { handleError(e); } } else if (!sinkChannel.isWriteResumed()) { try { // TODO: this needs some more thought if (!sinkChannel.flush()) { sinkChannel .getWriteSetter() .set( new ChannelListener<StreamSinkChannel>() { @Override public void handleEvent(StreamSinkChannel channel) { try { if (channel.flush()) { channel.suspendWrites(); } } catch (IOException e) { handleError(e); } } }); sinkChannel.resumeWrites(); } } catch (IOException e) { handleError(e); } } }