Skip to content

Commit

Permalink
minoc: use filenameOverride feature in cutout logic
Browse files Browse the repository at this point in the history
this makes sure that vault cutouts have the real fits file name
and not the opaque vault storage id
  • Loading branch information
pdowler committed Apr 12, 2024
1 parent e21dd84 commit c176621
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 23 deletions.
34 changes: 25 additions & 9 deletions minoc/src/intTest/java/org/opencadc/minoc/FitsOperationsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ public class FitsOperationsTest extends MinocTest {
protected URL filesVaultURL;

private String putContentType = "application/fits";
private String filenameOverridePrefix = null;

static {
Log4jInit.setLevel("org.opencadc.minoc", Level.INFO);
Expand Down Expand Up @@ -217,6 +218,13 @@ public void testSimple() throws Exception {
final URL noclArtifactURL = new URL(filesURL + "/" + noclArtifactURI.toString());
LOGGER.info("no content-length: " + noclArtifactURL);

try {
filenameOverridePrefix = "something-else";
uploadAndCompareCutout(artifactURI, SodaParamValidator.SUB, cutoutSpecs, testFilePrefix);
} finally {
filenameOverridePrefix = null;
}

try {
putContentType = null;
uploadAndCompareCutout(noclArtifactURI, SodaParamValidator.SUB, cutoutSpecs, testFilePrefix);
Expand Down Expand Up @@ -403,31 +411,39 @@ public void testJCMTPolarizationCutout() throws Exception {

private File doCutout(final URI artifactURI, final String queryString, final String testFilePrefix,
final String expectedContentType) throws Exception {
final URL artifactSUBURL = new URL(filesURL + "/" + artifactURI
String auri = artifactURI.toASCIIString();
if (filenameOverridePrefix != null) {
auri += ":fo/" + filenameOverridePrefix + ".fits";
}
final URL artifactSUBURL = new URL(filesURL + "/" + auri
+ (queryString == null ? "" : "?" + queryString));
final File outputFile = Files.createTempFile(testFilePrefix + "-", ".fits").toFile();
LOGGER.debug("Writing cutout to " + outputFile);

// Perform the cutout.
Subject.doAs(userSubject, (PrivilegedExceptionAction<Boolean>) () -> {
LOGGER.debug("Testing cutout with " + artifactSUBURL);
LOGGER.info("Testing cutout with " + artifactSUBURL);
try (final FileOutputStream fileOutputStream = new FileOutputStream(outputFile)) {
final HttpGet cutoutClient = new HttpGet(artifactSUBURL, true);
cutoutClient.setFollowRedirects(true);
cutoutClient.prepare();

Assert.assertEquals("Wrong content type.",
expectedContentType, cutoutClient.getResponseHeader(HttpTransfer.CONTENT_TYPE));
Assert.assertNotNull("Should include Content-Disposition ("
+ cutoutClient.getResponseHeader("Content-Disposition") + ")",
cutoutClient.getResponseHeader("Content-Disposition"));
String cdisp = cutoutClient.getResponseHeader("Content-Disposition");
LOGGER.info("content-disposition: " + cdisp);
Assert.assertNotNull("Should include Content-Disposition (" + cdisp + ")", cdisp);
if (filenameOverridePrefix != null) {
Assert.assertTrue(cdisp.contains(filenameOverridePrefix));
} else {
Assert.assertTrue(cdisp.contains(testFilePrefix));
}

Assert.assertEquals("Should NOT contain " + HttpTransfer.CONTENT_LENGTH, -1L,
cutoutClient.getContentLength());
Assert.assertFalse("Should NOT contain " + HttpTransfer.CONTENT_MD5,
StringUtil.hasText(cutoutClient.getContentMD5()));
Assert.assertFalse("Should NOT contain " + HttpTransfer.CONTENT_ENCODING,
StringUtil.hasText(cutoutClient.getContentEncoding()));
Assert.assertNull("Should NOT contain " + HttpTransfer.CONTENT_MD5, cutoutClient.getContentMD5());
Assert.assertNull("Should NOT contain " + HttpTransfer.DIGEST, cutoutClient.getDigest());
Assert.assertNull("Should NOT contain " + HttpTransfer.CONTENT_ENCODING, cutoutClient.getContentEncoding());

final byte[] buffer = new byte[64 * 1024];
int bytesRead;
Expand Down
39 changes: 25 additions & 14 deletions minoc/src/main/java/org/opencadc/minoc/GetAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,12 @@ public void doAction() throws Exception {
log.debug("Range (" + range + ") ignored in GET with operations");
}

if (!isFITS(artifact)) {
throw new IllegalArgumentException("not a fits file: " + artifactURI);
if (!isFITS(artifact, filenameOverride)) {
String filename = artifactURI.toASCIIString();
if (filenameOverride != null) {
filename += " aka " + filenameOverride;
}
throw new IllegalArgumentException("not a fits file: " + filename);
}

final List<String> conflicts = sodaCutout.getConflicts();
Expand Down Expand Up @@ -270,9 +274,15 @@ private ByteCountOutputStream doByteRangeRequest(Artifact artifact, ByteRange by
private ByteCountOutputStream doOperation(FitsOperations fitsOperations, SodaCutout sodaCutout)
throws NoOverlapException, ReadException, IOException {

String filename = InventoryUtil.computeArtifactFilename(artifactURI);
if (filenameOverride != null) {
filename = filenameOverride;
}

if (sodaCutout.isMETA()) {
log.debug("META supplied");
final String filename = InventoryUtil.computeArtifactFilename(artifactURI) + ".txt";
filename += ".txt";

syncOutput.setHeader(CONTENT_DISPOSITION, "inline; filename=\"" + filename + "\"");
syncOutput.setHeader(HttpTransfer.CONTENT_TYPE, "text/plain");

Expand All @@ -289,9 +299,7 @@ private ByteCountOutputStream doOperation(FitsOperations fitsOperations, SodaCut
final Cutout cutout = new Cutout();
cutout.pixelCutouts = slices;

final String schemePath = artifactURI.getSchemeSpecificPart();
final String fileName = schemePath.substring(schemePath.lastIndexOf("/") + 1);
final CutoutFileNameFormat cutoutFileNameFormat = new CutoutFileNameFormat(fileName);
final CutoutFileNameFormat cutoutFileNameFormat = new CutoutFileNameFormat(filename);
syncOutput.setHeader(CONTENT_DISPOSITION, "inline; filename=\""
+ cutoutFileNameFormat.format(cutout) + "\"");
syncOutput.setHeader(HttpTransfer.CONTENT_TYPE, "application/fits");
Expand Down Expand Up @@ -368,9 +376,7 @@ private ByteCountOutputStream doOperation(FitsOperations fitsOperations, SodaCut
}
}

final String schemePath = artifactURI.getSchemeSpecificPart();
final String fileName = schemePath.substring(schemePath.lastIndexOf("/") + 1);
final CutoutFileNameFormat cutoutFileNameFormat = new CutoutFileNameFormat(fileName);
final CutoutFileNameFormat cutoutFileNameFormat = new CutoutFileNameFormat(filename);
syncOutput.setHeader(CONTENT_DISPOSITION, "inline; filename=\""
+ cutoutFileNameFormat.format(cutout) + "\"");
syncOutput.setHeader(HttpTransfer.CONTENT_TYPE, "application/fits");
Expand All @@ -394,12 +400,17 @@ private <T> T assertSingleWCS(final String key, final List<T> wcsValues) {
}
}

private boolean isFITS(final Artifact artifact) {
private boolean isFITS(final Artifact artifact, String filenameOverride) {
String effectiveType = getEffectiveContentType(artifact.contentType);
final String contentType = (effectiveType != null
? effectiveType : getContentTypeFromFilename(artifact.getURI().getSchemeSpecificPart()));
return StringUtil.hasText(contentType)
&& Arrays.stream(FITS_CONTENT_TYPES).anyMatch(s -> s.equals(contentType));
if (effectiveType == null) {
if (filenameOverride != null) {
effectiveType = getContentTypeFromFilename(filenameOverride);
} else {
effectiveType = getContentTypeFromFilename(artifact.getURI().getSchemeSpecificPart());
}
}
final String contentType = effectiveType;
return contentType != null && Arrays.stream(FITS_CONTENT_TYPES).anyMatch(s -> s.equals(contentType));
}

private String getEffectiveContentType(String s) {
Expand Down

0 comments on commit c176621

Please sign in to comment.