Skip to content

Commit 5819176

Browse files
committed
Consolidate GET and HEAD requests. Support open ranges. Add content-range header
1 parent 4f2c344 commit 5819176

File tree

1 file changed

+39
-78
lines changed

1 file changed

+39
-78
lines changed

src/main/java/com/glencoesoftware/omero/ms/image/region/ImageRegionMicroserviceVerticle.java

Lines changed: 39 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
import io.vertx.core.buffer.Buffer;
5555
import io.vertx.core.eventbus.Message;
5656
import io.vertx.core.eventbus.ReplyException;
57+
import io.vertx.core.http.HttpMethod;
5758
import io.vertx.core.http.HttpServer;
5859
import io.vertx.core.http.HttpServerOptions;
5960
import io.vertx.core.http.HttpServerRequest;
@@ -362,7 +363,7 @@ public void deploy(JsonObject config, Promise<Void> prom) {
362363
.handler(this::downloadFileAnnotation);
363364
router.head(
364365
"/webclient/annotation/:annotationId*")
365-
.handler(this::fileAnnotationMetadata);
366+
.handler(this::downloadFileAnnotation);
366367

367368
// ImageData request handlers
368369
router.get("/webgateway/imgData/:imageId/:keys*").handler(this::getImageData);
@@ -961,76 +962,6 @@ private void getThumbnails(RoutingContext event) {
961962
* @param event Current routing context
962963
*/
963964
private void downloadFileAnnotation(RoutingContext event) {
964-
HttpServerRequest request = event.request();
965-
HttpServerResponse response = event.response();
966-
final AnnotationCtx annotationCtx;
967-
try {
968-
annotationCtx = new AnnotationCtx(request.params(),
969-
event.get("omero.session_key"));
970-
} catch (IllegalArgumentException e) {
971-
if (!response.closed()) {
972-
response.setStatusCode(400).end(e.getMessage());
973-
}
974-
return;
975-
}
976-
annotationCtx.injectCurrentTraceContext();
977-
vertx.eventBus().<JsonObject>request(
978-
ImageRegionVerticle.GET_FILE_ANNOTATION_METADATA_EVENT,
979-
Json.encode(annotationCtx), new Handler<AsyncResult<Message<JsonObject>>>() {
980-
@Override
981-
public void handle(AsyncResult<Message<JsonObject>> result) {
982-
if (result.failed()) {
983-
log.error(result.cause().getMessage());
984-
response.setStatusCode(404);
985-
response.end("Could not get annotation "
986-
+ request.getParam("annotationId"));
987-
return;
988-
}
989-
JsonObject fileInfo = result.result().body();
990-
String fileName = fileInfo.getString("originalFileName");
991-
String filePath = fileInfo.getString("originalFilePath");
992-
//If the path is a directory, send error response
993-
File file = new File(filePath);
994-
if (!file.exists()) {
995-
response.setStatusCode(404);
996-
response.end("File for given Annotation does not exist");
997-
return;
998-
}
999-
if (file.isDirectory()) {
1000-
response.setStatusCode(501);
1001-
response.end("File Annotation of Unsupported File Type");
1002-
return;
1003-
}
1004-
else {
1005-
response.headers().set("Content-Type", "application/octet-stream");
1006-
response.headers().set("Content-Disposition",
1007-
"attachment; filename=\"" + fileName + "\"");
1008-
if (request.headers().contains("Range")) {
1009-
String range = request.getHeader("Range");
1010-
if (range.matches("^bytes=\\d+-\\d+$")) {
1011-
String[] startEndStr =
1012-
range.substring("bytes=".length()).split("-");
1013-
response.sendFile(filePath, Long.valueOf(startEndStr[0]),
1014-
Long.valueOf(startEndStr[1]));
1015-
} else {
1016-
response.setStatusCode(400);
1017-
response.end("Malformed Range header - "
1018-
+ "must be of the form \"bytes=x-y\"");
1019-
}
1020-
} else {
1021-
response.sendFile(filePath);
1022-
}
1023-
}
1024-
}
1025-
});
1026-
}
1027-
1028-
/**
1029-
* Downloads the {@link OriginalFile} associated with the given
1030-
* {@link FileAnnotation}
1031-
* @param event Current routing context
1032-
*/
1033-
private void fileAnnotationMetadata(RoutingContext event) {
1034965
HttpServerRequest request = event.request();
1035966
HttpServerResponse response = event.response();
1036967
final AnnotationCtx annotationCtx;
@@ -1081,31 +1012,61 @@ public void handle(AsyncResult<Message<JsonObject>> result) {
10811012
fileName));
10821013
}
10831014
response.headers().set("Content-Type", contentType);
1084-
response.headers().set("Content-Length", Long.toString(file.length()));
1015+
10851016
response.headers().set("Accept-Ranges", "bytes");
10861017
ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(
10871018
Instant.ofEpochMilli(file.lastModified()),
10881019
ZoneId.of("UTC"));
10891020
DateTimeFormatter formatter =
10901021
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
10911022
response.headers().set("Last-Modified", zonedDateTime.format(formatter));
1023+
response.headers().set("Content-Disposition",
1024+
"attachment; filename=\"" + fileName + "\"");
1025+
1026+
if (request.method() == HttpMethod.HEAD) {
1027+
response.headers().set("Content-Length", Long.toString(file.length()));
1028+
response.end();
1029+
return;
1030+
}
10921031
if (request.headers().contains("Range")) {
10931032
String range = request.getHeader("Range");
1033+
long start;
1034+
long end;
10941035
if (range.matches("^bytes=\\d+-\\d+$")) {
1095-
String[] startEndStr =
1036+
String[] startEndStr =
1037+
range.substring("bytes=".length()).split("-");
1038+
start = Long.valueOf(startEndStr[0]);
1039+
end = Long.valueOf(startEndStr[1]);
1040+
end = Math.min(end, file.length());
1041+
}
1042+
else if (range.matches("^bytes=\\d+-$")) {
1043+
String[] startEndStr =
10961044
range.substring("bytes=".length()).split("-");
1097-
response.sendFile(filePath, Long.valueOf(startEndStr[0]),
1098-
Long.valueOf(startEndStr[1]));
1045+
start = Long.valueOf(startEndStr[0]);
1046+
end = file.length() - 1;
10991047
} else {
11001048
response.setStatusCode(400);
11011049
response.end("Malformed Range header - "
1102-
+ "must be of the form \"bytes=x-y\"");
1050+
+ "must be of the form \"bytes=x-y\" or \"bytes=x-\"");
1051+
return;
11031052
}
1053+
if (start >= file.length()) {
1054+
response.setStatusCode(416);
1055+
response.end("Invalid range");
1056+
return;
1057+
}
1058+
response.setStatusCode(206);
1059+
log.info("Setting content-range");
1060+
response.headers().set("Content-Range",
1061+
String.format("%d-%d/%d", start, end,
1062+
file.length()));
1063+
log.info("Sending file...");
1064+
response.sendFile(filePath, start, end - start + 1);
11041065
} else {
11051066
response.sendFile(filePath);
11061067
}
11071068
}
1108-
}
1109-
});
1069+
}
1070+
});
11101071
}
11111072
}

0 commit comments

Comments
 (0)