use of org.apache.flink.runtime.rest.handler.RestHandlerException 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.runtime.rest.handler.RestHandlerException in project flink by apache.
the class JarUploadHandlerTest method testRejectNonJarFiles.
@Test
public void testRejectNonJarFiles() throws Exception {
final Path uploadedFile = Files.createFile(jarDir.resolve("katrin.png"));
final HandlerRequest<EmptyRequestBody> request = createRequest(uploadedFile);
try {
jarUploadHandler.handleRequest(request, mockDispatcherGateway).get();
fail("Expected exception not thrown.");
} catch (final ExecutionException e) {
final Throwable throwable = ExceptionUtils.stripCompletionException(e.getCause());
assertThat(throwable, instanceOf(RestHandlerException.class));
final RestHandlerException restHandlerException = (RestHandlerException) throwable;
assertThat(restHandlerException.getHttpResponseStatus(), equalTo(HttpResponseStatus.BAD_REQUEST));
}
}
use of org.apache.flink.runtime.rest.handler.RestHandlerException in project flink by apache.
the class JarHandlerUtils method getProgramArgs.
/**
* Parse program arguments in jar run or plan request.
*/
private static <R extends JarRequestBody, M extends MessageParameters> List<String> getProgramArgs(HandlerRequest<R> request, Logger log) throws RestHandlerException {
JarRequestBody requestBody = request.getRequestBody();
@SuppressWarnings("deprecation") List<String> programArgs = tokenizeArguments(fromRequestBodyOrQueryParameter(emptyToNull(requestBody.getProgramArguments()), () -> getQueryParameter(request, ProgramArgsQueryParameter.class), null, log));
List<String> programArgsList = fromRequestBodyOrQueryParameter(requestBody.getProgramArgumentsList(), () -> request.getQueryParameter(ProgramArgQueryParameter.class), null, log);
if (!programArgsList.isEmpty()) {
if (!programArgs.isEmpty()) {
throw new RestHandlerException("Confusing request: programArgs and programArgsList are specified, please, use only programArgsList", HttpResponseStatus.BAD_REQUEST);
}
return programArgsList;
} else {
return programArgs;
}
}
use of org.apache.flink.runtime.rest.handler.RestHandlerException in project flink by apache.
the class JarUploadHandler method handleRequest.
@Override
@VisibleForTesting
public CompletableFuture<JarUploadResponseBody> handleRequest(@Nonnull final HandlerRequest<EmptyRequestBody> request, @Nonnull final RestfulGateway gateway) throws RestHandlerException {
Collection<File> uploadedFiles = request.getUploadedFiles();
if (uploadedFiles.size() != 1) {
throw new RestHandlerException("Exactly 1 file must be sent, received " + uploadedFiles.size() + '.', HttpResponseStatus.BAD_REQUEST);
}
final Path fileUpload = uploadedFiles.iterator().next().toPath();
return CompletableFuture.supplyAsync(() -> {
if (!fileUpload.getFileName().toString().endsWith(".jar")) {
throw new CompletionException(new RestHandlerException("Only Jar files are allowed.", HttpResponseStatus.BAD_REQUEST));
} else {
final Path destination = jarDir.resolve(UUID.randomUUID() + "_" + fileUpload.getFileName());
try {
Files.move(fileUpload, destination);
} catch (IOException e) {
throw new CompletionException(new RestHandlerException(String.format("Could not move uploaded jar file [%s] to [%s].", fileUpload, destination), HttpResponseStatus.INTERNAL_SERVER_ERROR, e));
}
return new JarUploadResponseBody(destination.normalize().toString());
}
}, executor);
}
use of org.apache.flink.runtime.rest.handler.RestHandlerException in project flink by apache.
the class CheckpointConfigHandler method createCheckpointConfigInfo.
private static CheckpointConfigInfo createCheckpointConfigInfo(AccessExecutionGraph executionGraph) throws RestHandlerException {
final CheckpointCoordinatorConfiguration checkpointCoordinatorConfiguration = executionGraph.getCheckpointCoordinatorConfiguration();
if (checkpointCoordinatorConfiguration == null) {
throw new RestHandlerException("Checkpointing is not enabled for this job (" + executionGraph.getJobID() + ").", HttpResponseStatus.NOT_FOUND, RestHandlerException.LoggingBehavior.IGNORE);
} else {
CheckpointRetentionPolicy retentionPolicy = checkpointCoordinatorConfiguration.getCheckpointRetentionPolicy();
CheckpointConfigInfo.ExternalizedCheckpointInfo externalizedCheckpointInfo = new CheckpointConfigInfo.ExternalizedCheckpointInfo(retentionPolicy != CheckpointRetentionPolicy.NEVER_RETAIN_AFTER_TERMINATION, retentionPolicy != CheckpointRetentionPolicy.RETAIN_ON_CANCELLATION);
String stateBackendName = executionGraph.getStateBackendName().orElse(null);
String checkpointStorageName = executionGraph.getCheckpointStorageName().orElse(null);
return new CheckpointConfigInfo(checkpointCoordinatorConfiguration.isExactlyOnce() ? CheckpointConfigInfo.ProcessingMode.EXACTLY_ONCE : CheckpointConfigInfo.ProcessingMode.AT_LEAST_ONCE, checkpointCoordinatorConfiguration.getCheckpointInterval(), checkpointCoordinatorConfiguration.getCheckpointTimeout(), checkpointCoordinatorConfiguration.getMinPauseBetweenCheckpoints(), checkpointCoordinatorConfiguration.getMaxConcurrentCheckpoints(), externalizedCheckpointInfo, stateBackendName, checkpointStorageName, checkpointCoordinatorConfiguration.isUnalignedCheckpointsEnabled(), checkpointCoordinatorConfiguration.getTolerableCheckpointFailureNumber(), checkpointCoordinatorConfiguration.getAlignedCheckpointTimeout(), checkpointCoordinatorConfiguration.isEnableCheckpointsAfterTasksFinish());
}
}
Aggregations