use of com.webpieces.http2engine.api.StreamWriter in project webpieces by deanhiller.
the class TestC5_1StreamStates method testSection5_1ReceiveBadFrameAfterReceiveRstStreamFrame.
/**
* An endpoint MUST NOT send frames other than PRIORITY on a closed stream. An endpoint
* that receives any frame other than PRIORITY after receiving a ----RST_STREAM---- MUST
* treat that as a stream error (Section 5.4.2) of type STREAM_CLOSED. Similarly, an
* endpoint that receives any frames after receiving a frame with the
* END_STREAM flag set MUST treat that as a connection error (Section 5.4.1) of
* type STREAM_CLOSED, unless the frame is permitted as described below.
*
*/
@Test
public void testSection5_1ReceiveBadFrameAfterReceiveRstStreamFrame() {
MockStreamWriter mockWriter = new MockStreamWriter();
MockResponseListener listener1 = new MockResponseListener();
listener1.setIncomingRespDefault(CompletableFuture.<StreamWriter>completedFuture(mockWriter));
Http2Request request = sendRequestToServer(listener1);
sendResetFromServer(listener1, request);
DataFrame dataFrame = new DataFrame(request.getStreamId(), false);
mockChannel.write(dataFrame);
//remote receives goAway
GoAwayFrame goAway = (GoAwayFrame) mockChannel.getFrameAndClear();
Assert.assertEquals(Http2ErrorCode.STREAM_CLOSED, goAway.getKnownErrorCode());
DataWrapper debugData = goAway.getDebugData();
String msg = debugData.createStringFromUtf8(0, debugData.getReadableSize());
Assert.assertEquals("ConnectionException: MockHttp2Channel1:stream1:(CLOSED_STREAM) " + "Stream must have been closed as it no longer exists. high mark=1 " + "your frame=DataFrame{streamId=1, endStream=false, data.len=0, padding=0}", msg);
Assert.assertTrue(mockChannel.isClosed());
Assert.assertEquals(0, listener1.getReturnValuesIncomingResponse().size());
//send new request on closed connection
Http2Request request1 = Requests.createRequest();
CompletableFuture<StreamWriter> future = httpSocket.openStream().process(request1, listener1);
ConnectionClosedException intercept = (ConnectionClosedException) TestAssert.intercept(future);
Assert.assertTrue(intercept.getMessage().contains("Connection closed or closing"));
Assert.assertEquals(0, mockChannel.getFramesAndClear().size());
}
use of com.webpieces.http2engine.api.StreamWriter in project webpieces by deanhiller.
the class TestC5_1StreamStates method testSection5_1ReceiveValidFramesAfterSendRstStreamFrame.
/**
* If this state is reached as a result of sending a RST_STREAM frame, the
* peer that receives the RST_STREAM might have already sent — or enqueued for
* sending — frames on the stream that cannot be withdrawn. An endpoint MUST ignore
* frames that it receives on closed streams after it has sent a RST_STREAM frame. An
* endpoint MAY choose to limit the period over which it ignores frames and
* treat frames that arrive after this time as being in error.
* @throws TimeoutException
* @throws ExecutionException
* @throws InterruptedException
*/
@Test
public void testSection5_1ReceiveValidFramesAfterSendRstStreamFrame() throws InterruptedException, ExecutionException, TimeoutException {
MockResponseListener listener1 = new MockResponseListener();
listener1.setIncomingRespDefault(CompletableFuture.<StreamWriter>completedFuture(null));
Http2Request request1 = Requests.createRequest();
StreamHandle stream = httpSocket.openStream();
CompletableFuture<StreamWriter> future = stream.process(request1, listener1);
@SuppressWarnings("unused") StreamWriter writer = future.get(2, TimeUnit.SECONDS);
Http2Msg req = mockChannel.getFrameAndClear();
Assert.assertEquals(request1, req);
RstStreamFrame rst = new RstStreamFrame(request1.getStreamId(), Http2ErrorCode.CANCEL);
CompletableFuture<Void> cancel = stream.cancel(rst);
cancel.get(2, TimeUnit.SECONDS);
Http2Msg svrRst = mockChannel.getFrameAndClear();
Assert.assertEquals(rst, svrRst);
//simulate server responding before receiving the cancel
Http2Response resp1 = Requests.createEosResponse(request1.getStreamId());
//endOfStream=true
mockChannel.write(resp1);
// Assert.assertEquals(0, mockChannel.getFramesAndClear().size());
// Assert.assertFalse(mockChannel.isClosed());
//
// Assert.assertEquals(0, listener1.getReturnValuesIncomingResponse().size());
}
use of com.webpieces.http2engine.api.StreamWriter in project webpieces by deanhiller.
the class ProxyResponse method sendChunkedResponse.
private CompletableFuture<Void> sendChunkedResponse(Http2Response resp, byte[] bytes, final Compression compression) {
boolean compressed = false;
Compression usingCompression;
if (compression == null) {
usingCompression = new NoCompression();
} else {
usingCompression = compression;
compressed = true;
resp.addHeader(new Http2Header(Http2HeaderName.CONTENT_ENCODING, usingCompression.getCompressionType()));
}
log.info("sending RENDERHTML response. size=" + bytes.length + " code=" + resp + " for domain=" + routerRequest.domain + " path" + routerRequest.relativePath + " responseSender=" + stream);
boolean isCompressed = compressed;
// Send the headers and get the responseid.
return stream.sendResponse(resp).thenCompose(writer -> {
List<DataFrame> frames = possiblyCompress(bytes, usingCompression, isCompressed);
CompletableFuture<StreamWriter> future = CompletableFuture.completedFuture(writer);
for (int i = 0; i < frames.size(); i++) {
DataFrame f = frames.get(i);
if (i == frames.size() - 1)
f.setEndOfStream(true);
future = future.thenCompose(v -> {
return writer.processPiece(f);
});
}
return future;
}).thenApply(w -> null);
}
use of com.webpieces.http2engine.api.StreamWriter in project webpieces by deanhiller.
the class StaticFileReader method runAsyncFileRead.
private CompletableFuture<Void> runAsyncFileRead(RequestInfo info, RenderStaticResponse renderStatic) throws IOException {
boolean isFile = true;
String fullFilePath = renderStatic.getFilePath();
if (fullFilePath == null) {
isFile = false;
fullFilePath = renderStatic.getDirectory() + renderStatic.getRelativePath();
}
String extension = null;
int lastDirIndex = fullFilePath.lastIndexOf("/");
int lastDot = fullFilePath.lastIndexOf(".");
if (lastDot > lastDirIndex) {
extension = fullFilePath.substring(lastDot + 1);
}
ResponseEncodingTuple tuple = responseCreator.createResponse(info.getRequest(), StatusCode.HTTP_200_OK, extension, "application/octet-stream", false);
Http2Response response = tuple.response;
//On startup, we protect developers from breaking clients. In http, all files that change
//must also change the hash automatically and the %%{ }%% tag generates those hashes so the
//files loaded are always the latest
Long timeMs = config.getStaticFileCacheTimeSeconds();
if (timeMs != null)
response.addHeader(new Http2Header(Http2HeaderName.CACHE_CONTROL, "max-age=" + timeMs));
Path file;
Compression compr = compressionLookup.createCompressionStream(info.getRouterRequest().encodings, extension, tuple.mimeType);
//during startup as I don't feel like paying a cpu penalty for compressing while live
if (compr != null && compr.getCompressionType().equals(routerConfig.getStartupCompression())) {
response.addHeader(new Http2Header(Http2HeaderName.CONTENT_ENCODING, compr.getCompressionType()));
File routesCache = renderStatic.getTargetCache();
File fileReference;
if (isFile) {
String fileName = fullFilePath.substring(lastDirIndex + 1);
fileReference = new File(routesCache, fileName);
} else {
fileReference = new File(routesCache, renderStatic.getRelativePath());
}
fullFilePath = fileReference.getAbsolutePath();
file = fetchFile("Compressed File from cache=", fullFilePath + ".gz");
} else {
file = fetchFile("File=", fullFilePath);
}
AsynchronousFileChannel asyncFile = AsynchronousFileChannel.open(file, options, fileExecutor);
CompletableFuture<StreamWriter> future;
try {
log.info(() -> "sending chunked file via async read=" + file);
long length = file.toFile().length();
AtomicLong remaining = new AtomicLong(length);
future = info.getResponseSender().sendResponse(response).thenCompose(s -> readLoop(s, info.getPool(), file, asyncFile, 0, remaining));
} catch (Throwable e) {
future = new CompletableFuture<StreamWriter>();
future.completeExceptionally(e);
}
return //our finally block for failures
future.handle((s, exc) -> handleClose(info, s, exc)).thenAccept(s -> empty());
}
use of com.webpieces.http2engine.api.StreamWriter in project webpieces by deanhiller.
the class Layer2Http1_1Handler method processData.
private CompletableFuture<Void> processData(FrontendSocketImpl socket, DataFrame msg) {
PermitQueue permitQueue = socket.getPermitQueue();
return permitQueue.runRequest(() -> {
Http1_1StreamImpl stream = socket.getCurrentStream();
StreamWriter requestWriter = stream.getRequestWriter();
if (msg.isEndOfStream())
stream.setSentFullRequest(true);
return requestWriter.processPiece(msg).thenApply(w -> {
stream.setRequestWriter(w);
if (!msg.isEndOfStream())
permitQueue.releasePermit();
return null;
});
});
}
Aggregations