use of org.apache.flink.shaded.netty4.io.netty.handler.stream.ChunkedFile 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.stream.ChunkedFile in project netty by netty.
the class FileServerHandler method channelRead0.
@Override
public void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
RandomAccessFile raf = null;
long length = -1;
try {
raf = new RandomAccessFile(msg, "r");
length = raf.length();
} catch (Exception e) {
ctx.writeAndFlush("ERR: " + e.getClass().getSimpleName() + ": " + e.getMessage() + '\n');
return;
} finally {
if (length < 0 && raf != null) {
raf.close();
}
}
ctx.write("OK: " + raf.length() + '\n');
if (ctx.pipeline().get(SslHandler.class) == null) {
// SSL not enabled - can use zero-copy file transfer.
ctx.write(new DefaultFileRegion(raf.getChannel(), 0, length));
} else {
// SSL enabled - cannot use zero-copy file transfer.
ctx.write(new ChunkedFile(raf));
}
ctx.writeAndFlush("\n");
}
use of org.apache.flink.shaded.netty4.io.netty.handler.stream.ChunkedFile in project netty by netty.
the class HttpStaticFileServerHandler method channelRead0.
@Override
public void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) throws Exception {
this.request = request;
if (!request.decoderResult().isSuccess()) {
sendError(ctx, BAD_REQUEST);
return;
}
if (!GET.equals(request.method())) {
sendError(ctx, METHOD_NOT_ALLOWED);
return;
}
final boolean keepAlive = HttpUtil.isKeepAlive(request);
final String uri = request.uri();
final String path = sanitizeUri(uri);
if (path == null) {
sendError(ctx, FORBIDDEN);
return;
}
File file = new File(path);
if (file.isHidden() || !file.exists()) {
sendError(ctx, NOT_FOUND);
return;
}
if (file.isDirectory()) {
if (uri.endsWith("/")) {
sendListing(ctx, file, uri);
} else {
sendRedirect(ctx, uri + '/');
}
return;
}
if (!file.isFile()) {
sendError(ctx, FORBIDDEN);
return;
}
// Cache Validation
String ifModifiedSince = request.headers().get(HttpHeaderNames.IF_MODIFIED_SINCE);
if (ifModifiedSince != null && !ifModifiedSince.isEmpty()) {
SimpleDateFormat dateFormatter = new SimpleDateFormat(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) {
sendNotModified(ctx);
return;
}
}
RandomAccessFile raf;
try {
raf = new RandomAccessFile(file, "r");
} catch (FileNotFoundException ignore) {
sendError(ctx, NOT_FOUND);
return;
}
long fileLength = raf.length();
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
HttpUtil.setContentLength(response, fileLength);
setContentTypeHeader(response, file);
setDateAndCacheHeaders(response, file);
if (!keepAlive) {
response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.CLOSE);
} else if (request.protocolVersion().equals(HTTP_1_0)) {
response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
}
// Write the initial line and the header.
ctx.write(response);
// Write the content.
ChannelFuture sendFileFuture;
ChannelFuture lastContentFuture;
if (ctx.pipeline().get(SslHandler.class) == null) {
sendFileFuture = ctx.write(new DefaultFileRegion(raf.getChannel(), 0, fileLength), ctx.newProgressivePromise());
// Write the end marker.
lastContentFuture = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
} else {
sendFileFuture = ctx.writeAndFlush(new HttpChunkedInput(new ChunkedFile(raf, 0, fileLength, 8192)), ctx.newProgressivePromise());
// HttpChunkedInput will write the end marker (LastHttpContent) for us.
lastContentFuture = sendFileFuture;
}
sendFileFuture.addListener(new ChannelProgressiveFutureListener() {
@Override
public void operationProgressed(ChannelProgressiveFuture future, long progress, long total) {
if (total < 0) {
// total unknown
System.err.println(future.channel() + " Transfer progress: " + progress);
} else {
System.err.println(future.channel() + " Transfer progress: " + progress + " / " + total);
}
}
@Override
public void operationComplete(ChannelProgressiveFuture future) {
System.err.println(future.channel() + " Transfer complete.");
}
});
// Decide whether to close the connection or not.
if (!keepAlive) {
// Close the connection when the whole content is written out.
lastContentFuture.addListener(ChannelFutureListener.CLOSE);
}
}
use of org.apache.flink.shaded.netty4.io.netty.handler.stream.ChunkedFile in project netty by netty.
the class Http2StaticFileServerHandler method channelRead.
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof Http2HeadersFrame) {
Http2HeadersFrame headersFrame = (Http2HeadersFrame) msg;
this.stream = headersFrame.stream();
if (!GET.toString().equals(headersFrame.headers().method().toString())) {
sendError(ctx, METHOD_NOT_ALLOWED);
return;
}
final String uri = headersFrame.headers().path().toString();
final String path = sanitizeUri(uri);
if (path == null) {
sendError(ctx, FORBIDDEN);
return;
}
File file = new File(path);
if (file.isHidden() || !file.exists()) {
sendError(ctx, NOT_FOUND);
return;
}
if (file.isDirectory()) {
if (uri.endsWith("/")) {
sendListing(ctx, file, uri);
} else {
sendRedirect(ctx, uri + '/');
}
return;
}
if (!file.isFile()) {
sendError(ctx, FORBIDDEN);
return;
}
// Cache Validation
CharSequence ifModifiedSince = headersFrame.headers().get(HttpHeaderNames.IF_MODIFIED_SINCE);
if (ifModifiedSince != null && !ifModifiedSince.toString().isEmpty()) {
SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US);
Date ifModifiedSinceDate = dateFormatter.parse(ifModifiedSince.toString());
// 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) {
sendNotModified(ctx);
return;
}
}
RandomAccessFile raf;
try {
raf = new RandomAccessFile(file, "r");
} catch (FileNotFoundException ignore) {
sendError(ctx, NOT_FOUND);
return;
}
long fileLength = raf.length();
Http2Headers headers = new DefaultHttp2Headers();
headers.status("200");
headers.setLong(HttpHeaderNames.CONTENT_LENGTH, fileLength);
setContentTypeHeader(headers, file);
setDateAndCacheHeaders(headers, file);
// Write the initial line and the header.
ctx.writeAndFlush(new DefaultHttp2HeadersFrame(headers).stream(stream));
// Write the content.
ChannelFuture sendFileFuture;
sendFileFuture = ctx.writeAndFlush(new Http2DataChunkedInput(new ChunkedFile(raf, 0, fileLength, 8192), stream), ctx.newProgressivePromise());
sendFileFuture.addListener(new ChannelProgressiveFutureListener() {
@Override
public void operationProgressed(ChannelProgressiveFuture future, long progress, long total) {
if (total < 0) {
// total unknown
System.err.println(future.channel() + " Transfer progress: " + progress);
} else {
System.err.println(future.channel() + " Transfer progress: " + progress + " / " + total);
}
}
@Override
public void operationComplete(ChannelProgressiveFuture future) {
System.err.println(future.channel() + " Transfer complete.");
}
});
} else {
// Unsupported message type
System.out.println("Unsupported message type: " + msg);
}
}
use of org.apache.flink.shaded.netty4.io.netty.handler.stream.ChunkedFile in project blade by biezhi.
the class StaticFileHandler method handle.
/**
* print static file to client
*
* @param webContext web context
* @throws Exception
*/
@Override
public void handle(WebContext webContext) throws Exception {
Request request = webContext.getRequest();
ChannelHandlerContext ctx = webContext.getChannelHandlerContext();
if (!HttpConst.METHOD_GET.equals(request.method())) {
sendError(ctx, METHOD_NOT_ALLOWED);
return;
}
Instant start = Instant.now();
String uri = URLDecoder.decode(request.uri(), "UTF-8");
String method = StringKit.padRight(request.method(), 6);
String cleanURL = getCleanURL(request, uri);
// webjars
if (cleanURL.startsWith(Const.WEB_JARS)) {
InputStream input = getResourceStreamFromJar(uri);
writeWithJarFile(request, ctx, uri, start, cleanURL, method, input);
return;
}
// jar file
if (BladeKit.runtimeIsJAR()) {
InputStream input = StaticFileHandler.class.getResourceAsStream(cleanURL);
writeWithJarFile(request, ctx, uri, start, cleanURL, method, input);
return;
}
// disk file
final String path = sanitizeUri(cleanURL);
if (path == null) {
log403(log, method, uri);
throw new ForbiddenException();
}
File file = new File(path);
if (file.isHidden() || !file.exists()) {
// gradle resources path
File resourcesDirectory = getGradleResourcesDirectory();
if (resourcesDirectory.isDirectory()) {
file = new File(resourcesDirectory.getPath() + "/" + cleanURL.substring(1));
if (file.isHidden() || !file.exists()) {
throw new NotFoundException(uri);
}
} else {
throw new NotFoundException(uri);
}
}
if (file.isDirectory() && showFileList) {
sendListing(ctx, uri, getFileMetas(file), cleanURL);
return;
}
if (!file.isFile()) {
sendError(ctx, FORBIDDEN);
return;
}
// Cache Validation
if (isHttp304(ctx, request, file.length(), file.lastModified())) {
log304(log, method, uri);
return;
}
HttpResponse httpResponse = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
setContentTypeHeader(httpResponse, file);
setDateAndCacheHeaders(httpResponse, file);
if (request.useGZIP()) {
File output = new File(file.getPath() + ".gz");
IOKit.compressGZIP(file, output);
file = output;
setGzip(httpResponse);
}
RandomAccessFile raf;
try {
raf = new RandomAccessFile(file, "r");
} catch (FileNotFoundException ignore) {
sendError(ctx, NOT_FOUND);
return;
}
long fileLength = raf.length();
httpResponse.headers().set(HttpConst.CONTENT_LENGTH, fileLength);
if (request.keepAlive()) {
httpResponse.headers().set(HttpConst.CONNECTION, HttpConst.KEEP_ALIVE);
}
// Write the initial line and the header.
ctx.write(httpResponse);
// Write the content.
ChannelFuture sendFileFuture;
ChannelFuture lastContentFuture;
if (ctx.pipeline().get(SslHandler.class) == null) {
sendFileFuture = ctx.write(new DefaultFileRegion(raf.getChannel(), 0, fileLength), ctx.newProgressivePromise());
// Write the end marker.
lastContentFuture = ctx.writeAndFlush(LastHttpContent.EMPTY_LAST_CONTENT);
} else {
sendFileFuture = ctx.writeAndFlush(new HttpChunkedInput(new ChunkedFile(raf, 0, fileLength, 8192)), ctx.newProgressivePromise());
// HttpChunkedInput will write the end marker (LastHttpContent) for us.
lastContentFuture = sendFileFuture;
}
sendFileFuture.addListener(ProgressiveFutureListener.build(raf));
// Decide whether to close the connection or not.
if (!request.keepAlive()) {
lastContentFuture.addListener(ChannelFutureListener.CLOSE);
}
log200AndCost(log, start, method, uri);
}
Aggregations