use of org.apache.flink.shaded.netty4.io.netty.handler.codec.http.HttpHeaders.Names.CONNECTION in project flink by apache.
the class HistoryServerStaticFileServerHandler method respondWithFile.
/**
* Response when running with leading JobManager.
*/
private void respondWithFile(ChannelHandlerContext ctx, HttpRequest request, String requestPath) throws IOException, ParseException, RestHandlerException {
// make sure we request the "index.html" in case there is a directory request
if (requestPath.endsWith("/")) {
requestPath = requestPath + "index.html";
}
if (!requestPath.contains(".")) {
// we assume that the path ends in either .html or .js
requestPath = requestPath + ".json";
}
// convert to absolute path
final File file = new File(rootPath, requestPath);
if (!file.exists()) {
// file does not exist. Try to load it with the classloader
ClassLoader cl = HistoryServerStaticFileServerHandler.class.getClassLoader();
try (InputStream resourceStream = cl.getResourceAsStream("web" + requestPath)) {
boolean success = false;
try {
if (resourceStream != null) {
URL root = cl.getResource("web");
URL requested = cl.getResource("web" + requestPath);
if (root != null && requested != null) {
URI rootURI = new URI(root.getPath()).normalize();
URI requestedURI = new URI(requested.getPath()).normalize();
// expected scope.
if (!rootURI.relativize(requestedURI).equals(requestedURI)) {
LOG.debug("Loading missing file from classloader: {}", requestPath);
// ensure that directory to file exists.
file.getParentFile().mkdirs();
Files.copy(resourceStream, file.toPath());
success = true;
}
}
}
} catch (Throwable t) {
LOG.error("error while responding", t);
} finally {
if (!success) {
LOG.debug("Unable to load requested file {} from classloader", requestPath);
throw new NotFoundException("File not found.");
}
}
}
}
StaticFileServerHandler.checkFileValidity(file, rootPath, LOG);
// cache validation
final String ifModifiedSince = request.headers().get(IF_MODIFIED_SINCE);
if (ifModifiedSince != null && !ifModifiedSince.isEmpty()) {
SimpleDateFormat dateFormatter = new SimpleDateFormat(StaticFileServerHandler.HTTP_DATE_FORMAT, Locale.US);
Date ifModifiedSinceDate = dateFormatter.parse(ifModifiedSince);
// Only compare up to the second because the datetime format we send to the client
// does not have milliseconds
long ifModifiedSinceDateSeconds = ifModifiedSinceDate.getTime() / 1000;
long fileLastModifiedSeconds = file.lastModified() / 1000;
if (ifModifiedSinceDateSeconds == fileLastModifiedSeconds) {
if (LOG.isDebugEnabled()) {
LOG.debug("Responding 'NOT MODIFIED' for file '" + file.getAbsolutePath() + '\'');
}
StaticFileServerHandler.sendNotModified(ctx);
return;
}
}
if (LOG.isDebugEnabled()) {
LOG.debug("Responding with file '" + file.getAbsolutePath() + '\'');
}
// Don't need to close this manually. Netty's DefaultFileRegion will take care of it.
final RandomAccessFile raf;
try {
raf = new RandomAccessFile(file, "r");
} catch (FileNotFoundException e) {
if (LOG.isDebugEnabled()) {
LOG.debug("Could not find file {}.", file.getAbsolutePath());
}
HandlerUtils.sendErrorResponse(ctx, request, new ErrorResponseBody("File not found."), NOT_FOUND, Collections.emptyMap());
return;
}
try {
long fileLength = raf.length();
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
StaticFileServerHandler.setContentTypeHeader(response, file);
// the job overview should be updated as soon as possible
if (!requestPath.equals("/joboverview.json")) {
StaticFileServerHandler.setDateAndCacheHeaders(response, file);
}
if (HttpHeaders.isKeepAlive(request)) {
response.headers().set(CONNECTION, HttpHeaders.Values.KEEP_ALIVE);
}
HttpHeaders.setContentLength(response, fileLength);
// write the initial line and the header.
ctx.write(response);
// write the content.
ChannelFuture lastContentFuture;
if (ctx.pipeline().get(SslHandler.class) == null) {
ctx.write(new DefaultFileRegion(raf.getChannel(), 0, fileLength), ctx.newProgressivePromise());
lastContentFuture = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
} else {
lastContentFuture = ctx.writeAndFlush(new HttpChunkedInput(new ChunkedFile(raf, 0, fileLength, 8192)), ctx.newProgressivePromise());
// HttpChunkedInput will write the end marker (LastHttpContent) for us.
}
// close the connection, if no keep-alive is needed
if (!HttpHeaders.isKeepAlive(request)) {
lastContentFuture.addListener(ChannelFutureListener.CLOSE);
}
} catch (Exception e) {
raf.close();
LOG.error("Failed to serve file.", e);
throw new RestHandlerException("Internal server error.", INTERNAL_SERVER_ERROR);
}
}
use of org.apache.flink.shaded.netty4.io.netty.handler.codec.http.HttpHeaders.Names.CONNECTION in project flink by apache.
the class NettyClient method connect.
// ------------------------------------------------------------------------
// Client connections
// ------------------------------------------------------------------------
ChannelFuture connect(final InetSocketAddress serverSocketAddress) {
checkState(bootstrap != null, "Client has not been initialized yet.");
// --------------------------------------------------------------------
// Child channel pipeline for accepted connections
// --------------------------------------------------------------------
bootstrap.handler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel channel) throws Exception {
// SSL handler should be added first in the pipeline
if (clientSSLFactory != null) {
SslHandler sslHandler = clientSSLFactory.createNettySSLHandler(channel.alloc(), serverSocketAddress.getAddress().getCanonicalHostName(), serverSocketAddress.getPort());
channel.pipeline().addLast("ssl", sslHandler);
}
channel.pipeline().addLast(protocol.getClientChannelHandlers());
}
});
try {
return bootstrap.connect(serverSocketAddress);
} catch (ChannelException e) {
if ((e.getCause() instanceof java.net.SocketException && e.getCause().getMessage().equals("Too many open files")) || (e.getCause() instanceof ChannelException && e.getCause().getCause() instanceof java.net.SocketException && e.getCause().getCause().getMessage().equals("Too many open files"))) {
throw new ChannelException("The operating system does not offer enough file handles to open the network connection. " + "Please increase the number of available file handles.", e.getCause());
} else {
throw e;
}
}
}
use of org.apache.flink.shaded.netty4.io.netty.handler.codec.http.HttpHeaders.Names.CONNECTION in project flink by apache.
the class ClientTest method testServerClosesChannel.
/**
* Tests that a server channel close, closes the connection and removes it from the established
* connections.
*/
@Test
public void testServerClosesChannel() throws Exception {
AtomicKvStateRequestStats stats = new AtomicKvStateRequestStats();
final MessageSerializer<KvStateInternalRequest, KvStateResponse> serializer = new MessageSerializer<>(new KvStateInternalRequest.KvStateInternalRequestDeserializer(), new KvStateResponse.KvStateResponseDeserializer());
Client<KvStateInternalRequest, KvStateResponse> client = null;
Channel serverChannel = null;
try {
client = new Client<>("Test Client", 1, serializer, stats);
final LinkedBlockingQueue<ByteBuf> received = new LinkedBlockingQueue<>();
final AtomicReference<Channel> channel = new AtomicReference<>();
serverChannel = createServerChannel(new ChannelDataCollectingHandler(channel, received));
InetSocketAddress serverAddress = getKvStateServerAddress(serverChannel);
// Requests
KvStateInternalRequest request = new KvStateInternalRequest(new KvStateID(), new byte[0]);
Future<KvStateResponse> future = client.sendRequest(serverAddress, request);
received.take();
assertEquals(1, stats.getNumConnections());
channel.get().close().await();
try {
future.get();
fail("Did not throw expected server failure");
} catch (ExecutionException e) {
if (!(e.getCause() instanceof ClosedChannelException)) {
fail("Did not throw expected Exception");
}
// Expected
}
assertEquals(0L, stats.getNumConnections());
// Counts can take some time to propagate
while (stats.getNumSuccessful() != 0L || stats.getNumFailed() != 1L) {
Thread.sleep(100L);
}
assertEquals(1L, stats.getNumRequests());
assertEquals(0L, stats.getNumSuccessful());
assertEquals(1L, stats.getNumFailed());
} finally {
if (client != null) {
try {
client.shutdown().get();
} catch (Exception e) {
e.printStackTrace();
}
Assert.assertTrue(client.isEventGroupShutdown());
}
if (serverChannel != null) {
serverChannel.close();
}
assertEquals("Channel leak", 0L, stats.getNumConnections());
}
}
use of org.apache.flink.shaded.netty4.io.netty.handler.codec.http.HttpHeaders.Names.CONNECTION in project flink by apache.
the class ClientTest method testFailureClosesChannel.
/**
* Tests that a server failure closes the connection and removes it from the established
* connections.
*/
@Test
public void testFailureClosesChannel() throws Exception {
AtomicKvStateRequestStats stats = new AtomicKvStateRequestStats();
final MessageSerializer<KvStateInternalRequest, KvStateResponse> serializer = new MessageSerializer<>(new KvStateInternalRequest.KvStateInternalRequestDeserializer(), new KvStateResponse.KvStateResponseDeserializer());
Client<KvStateInternalRequest, KvStateResponse> client = null;
Channel serverChannel = null;
try {
client = new Client<>("Test Client", 1, serializer, stats);
final LinkedBlockingQueue<ByteBuf> received = new LinkedBlockingQueue<>();
final AtomicReference<Channel> channel = new AtomicReference<>();
serverChannel = createServerChannel(new ChannelDataCollectingHandler(channel, received));
InetSocketAddress serverAddress = getKvStateServerAddress(serverChannel);
// Requests
List<Future<KvStateResponse>> futures = new ArrayList<>();
KvStateInternalRequest request = new KvStateInternalRequest(new KvStateID(), new byte[0]);
futures.add(client.sendRequest(serverAddress, request));
futures.add(client.sendRequest(serverAddress, request));
ByteBuf buf = received.take();
assertNotNull("Receive timed out", buf);
buf.release();
buf = received.take();
assertNotNull("Receive timed out", buf);
buf.release();
assertEquals(1L, stats.getNumConnections());
Channel ch = channel.get();
assertNotNull("Channel not active", ch);
// Respond with failure
ch.writeAndFlush(MessageSerializer.serializeServerFailure(serverChannel.alloc(), new RuntimeException("Expected test server failure")));
try {
futures.remove(0).get();
fail("Did not throw expected server failure");
} catch (ExecutionException e) {
if (!(e.getCause() instanceof RuntimeException)) {
fail("Did not throw expected Exception");
}
// Expected
}
try {
futures.remove(0).get();
fail("Did not throw expected server failure");
} catch (ExecutionException e) {
if (!(e.getCause() instanceof RuntimeException)) {
fail("Did not throw expected Exception");
}
// Expected
}
assertEquals(0L, stats.getNumConnections());
// Counts can take some time to propagate
while (stats.getNumSuccessful() != 0L || stats.getNumFailed() != 2L) {
Thread.sleep(100L);
}
assertEquals(2L, stats.getNumRequests());
assertEquals(0L, stats.getNumSuccessful());
assertEquals(2L, stats.getNumFailed());
} finally {
if (client != null) {
try {
client.shutdown().get();
} catch (Exception e) {
e.printStackTrace();
}
Assert.assertTrue(client.isEventGroupShutdown());
}
if (serverChannel != null) {
serverChannel.close();
}
assertEquals("Channel leak", 0L, stats.getNumConnections());
}
}
use of org.apache.flink.shaded.netty4.io.netty.handler.codec.http.HttpHeaders.Names.CONNECTION in project flink by apache.
the class RestClientTest method testConnectionClosedHandling.
/**
* Tests that we fail the operation if the remote connection closes.
*/
@Test
public void testConnectionClosedHandling() throws Exception {
final Configuration config = new Configuration();
config.setLong(RestOptions.IDLENESS_TIMEOUT, 5000L);
try (final ServerSocket serverSocket = new ServerSocket(0);
final RestClient restClient = new RestClient(config, TestingUtils.defaultExecutor())) {
final String targetAddress = "localhost";
final int targetPort = serverSocket.getLocalPort();
// start server
final CompletableFuture<Socket> socketCompletableFuture = CompletableFuture.supplyAsync(CheckedSupplier.unchecked(() -> NetUtils.acceptWithoutTimeout(serverSocket)));
final CompletableFuture<EmptyResponseBody> responseFuture = restClient.sendRequest(targetAddress, targetPort, new TestMessageHeaders(), EmptyMessageParameters.getInstance(), EmptyRequestBody.getInstance(), Collections.emptyList());
Socket connectionSocket = null;
try {
connectionSocket = socketCompletableFuture.get(TIMEOUT, TimeUnit.SECONDS);
} catch (TimeoutException ignored) {
// could not establish a server connection --> see that the response failed
socketCompletableFuture.cancel(true);
}
if (connectionSocket != null) {
// close connection
connectionSocket.close();
}
try {
responseFuture.get();
} catch (ExecutionException ee) {
if (!ExceptionUtils.findThrowable(ee, IOException.class).isPresent()) {
throw ee;
}
}
}
}
Aggregations