From dac6be27ce7121c4db9f88e9b251f3d5c2069dce Mon Sep 17 00:00:00 2001 From: "francesco.mangiacrapa" Date: Tue, 1 Oct 2019 18:00:44 +0200 Subject: [PATCH] # WARNING: head commit changed in the meantime removed unused test classes --- distro/changelog.xml | 3 + .../requesthandler/RequestHandler.java | 32 ++++- .../resolver/services/StorageIDResolver.java | 110 +++++++++++++----- .../datatransfer/resolver/util/Util.java | 30 +++++ 4 files changed, 145 insertions(+), 30 deletions(-) diff --git a/distro/changelog.xml b/distro/changelog.xml index adbadd4..a7680ae 100644 --- a/distro/changelog.xml +++ b/distro/changelog.xml @@ -164,5 +164,8 @@ date="${buildDate}"> [Feature #17630] Support parametric Content-Disposition + [Bug #17650] Bug #17650: URI-Resolver: HEAD request to + StorageID link does not return the "content-disposition + \ No newline at end of file diff --git a/src/main/java/org/gcube/datatransfer/resolver/requesthandler/RequestHandler.java b/src/main/java/org/gcube/datatransfer/resolver/requesthandler/RequestHandler.java index 431af94..15b16eb 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/requesthandler/RequestHandler.java +++ b/src/main/java/org/gcube/datatransfer/resolver/requesthandler/RequestHandler.java @@ -2,6 +2,7 @@ package org.gcube.datatransfer.resolver.requesthandler; import java.io.IOException; import java.net.URI; +import java.util.Arrays; import java.util.List; import javax.servlet.ServletContext; @@ -14,6 +15,8 @@ import javax.ws.rs.container.PreMatching; import javax.ws.rs.container.ResourceContext; import javax.ws.rs.core.Application; import javax.ws.rs.core.Context; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.UriBuilder; import javax.ws.rs.ext.Provider; import org.gcube.common.authorization.library.provider.SecurityTokenProvider; @@ -71,7 +74,21 @@ public class RequestHandler implements ContainerRequestFilter, ContainerResponse log.debug("The resources are: {}", listOfPath); String path = reqContext.getUriInfo().getPath(); + + //HOW TO READ THE QUERY STRING + /*MultivaluedMap queryParameters = reqContext.getUriInfo().getQueryParameters(); + String queryString = ""; + try { + queryString = Util.toQueryString(queryParameters); + }catch (Exception e) { + //silent + log.warn("Error on reading the query string, trying to continue..."); + } + log.debug("The query string is: {}", queryString); + */ + log.debug("The path is: {}", path); + if(path==null || path.isEmpty()) { log.debug("The path is null or empty, redirecting to /index"); @@ -103,7 +120,7 @@ public class RequestHandler implements ContainerRequestFilter, ContainerResponse //Try to manage as Catalogue Request ctlg, ctlg-p, etc. if(!resourceToRedirectFound) { - log.info("Trying to manage as hard-coded case: {}", ConstantsResolver.resourcesHardCoded.toString()); + log.info("Trying to manage as hard-coded case among cases: {}", Arrays.asList(ConstantsResolver.resourcesHardCoded).toString()); String[] hardCode = ConstantsResolver.resourcesHardCoded; for (String resource : hardCode) { @@ -134,7 +151,17 @@ public class RequestHandler implements ContainerRequestFilter, ContainerResponse log.info("No resource/service found to manage the input request '{}'", path); String newPath = String.format("/%s/%s", ConstantsResolver.defaultServiceToRedirect,path); //log.debug("The path to redirect is '{}'", newPath); - URI newRequestURI = reqContext.getUriInfo().getBaseUriBuilder().path(newPath).build(); + //URI newRequestURI = reqContext.getUriInfo().getBaseUriBuilder().path(newPath).build(); + UriBuilder uriBuilder = reqContext.getUriInfo().getBaseUriBuilder(); + //ADDING THE INPUT QUERY STRING + MultivaluedMap queryParameters = reqContext.getUriInfo().getQueryParameters(); + for (String param : queryParameters.keySet()) { + List values = queryParameters.get(param); + if(values!=null && !values.isEmpty()) + uriBuilder.queryParam(param,values.toArray()); + } + + URI newRequestURI = uriBuilder.path(newPath).build(); log.info("Redirect to URI path '{}'", newRequestURI.toString()); reqContext.setRequestUri(newRequestURI); } @@ -152,4 +179,5 @@ public class RequestHandler implements ContainerRequestFilter, ContainerResponse log.info("Token and Scope Provider reset called"); } + } \ No newline at end of file diff --git a/src/main/java/org/gcube/datatransfer/resolver/services/StorageIDResolver.java b/src/main/java/org/gcube/datatransfer/resolver/services/StorageIDResolver.java index 02b141d..196bf1d 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/services/StorageIDResolver.java +++ b/src/main/java/org/gcube/datatransfer/resolver/services/StorageIDResolver.java @@ -24,6 +24,7 @@ import org.gcube.contentmanager.storageclient.wrapper.MemoryType; import org.gcube.contentmanager.storageclient.wrapper.StorageClient; import org.gcube.datatransfer.resolver.ConstantsResolver; import org.gcube.datatransfer.resolver.services.error.ExceptionManager; +import org.gcube.datatransfer.resolver.services.tobackward.StorageMetadataFile; import org.gcube.datatransfer.resolver.storage.StorageClientInstance; import org.gcube.datatransfer.resolver.util.SingleFileStreamingOutput; import org.slf4j.Logger; @@ -46,8 +47,8 @@ public class StorageIDResolver { protected static final String STORAGEID_RESOLVER = "storageid-resolver"; private static final String STORAGE_ID = "storage-id"; - private static Logger logger = LoggerFactory.getLogger(StorageIDResolver.class); - + private static final Logger logger = LoggerFactory.getLogger(StorageIDResolver.class); + private static String help = "https://wiki.gcube-system.org/gcube/URI_Resolver#STORAGE-ID_Resolver"; @@ -134,31 +135,27 @@ public class StorageIDResolver { throw ExceptionManager.notFoundException(httpRequest, "Error on decrypting the "+STORAGE_ID+ " '"+storageId+"'. Is it a valid id?", StorageIDResolver.class, help); } - long size = iClient.getSize().RFileById(toSEID); - - try{ - - MyFile file = iClient.getMetaFile().RFile(toSEID); - logger.debug("MetaFile retrieved from storage? "+ (file!=null)); + //long size = iClient.getSize().RFileById(toSEID); + long size = 0; + + //READING THE METADATA OF FILE FROM STORAGE + StorageMetadataFile metaFile = getStorageMetadataFile(iClient,toSEID); + logger.debug("MetaFile retrieved from storage? "+ (metaFile!=null)); + + if(metaFile!=null) { //Reading the fileName from Storage Metadata only if the passed fileName is null if(fileName==null || fileName.isEmpty()) - fileName= file.getName(); - + fileName= metaFile.getName(); + //Reading the contentType from Storage Metadata only if the passed contentType is null if(contentType==null || contentType.isEmpty()) - contentType = file.getMimeType() - /** - * Gets the storage client instance. - * - * @param storageId the storage id - * @return the storage client instance - * @throws Exception the exception - */; - - }catch (Exception e) { - logger.warn("Error when getting file metadata from storage, printing this warning and trying to continue..", e); + contentType = metaFile.getMimeType(); + + //Reading the content size + size = metaFile.getSize(); } + //CHECKING TO DEFAULT METADATA fileName = fileName==null || fileName.isEmpty()?ConstantsResolver.DEFAULT_FILENAME_FROM_STORAGE_MANAGER:fileName; logger.info("filename retrieved is {}",fileName); @@ -172,15 +169,16 @@ public class StorageIDResolver { ResponseBuilder response = Response .ok(so) .header(ConstantsResolver.CONTENT_DISPOSITION,"attachment; filename=\""+fileName+"\"") - .header(ConstantsResolver.CONTENT_LENGTH, size); + .header(ConstantsResolver.CONTENT_LENGTH, size) + .header("Content-Type",contentType); - if (contentType!= null) - response.header("Content-Type",contentType); +// if (contentType!= null) +// response.header("Content-Type",contentType); return response.build(); } - + /** * Http do head. @@ -195,13 +193,15 @@ public class StorageIDResolver { @Path("/{storage-id}") public Response httpDoHead(@Context HttpServletRequest req, @PathParam(STORAGE_ID) String storageId, - @QueryParam(ConstantsResolver.HPC) Boolean hproxycheck) throws WebApplicationException { + @QueryParam(ConstantsResolver.HPC) boolean hproxycheck) throws WebApplicationException { logger.info(this.getClass().getSimpleName()+" HEAD starts..."); + logger.info("The query string is: {}", req.getQueryString()); + logger.info("Query parameter {} is {}", ConstantsResolver.HPC, hproxycheck); try{ //THIS IS FOR HPROXY CHECK - if(hproxycheck==null || hproxycheck){ + if(hproxycheck){ logger.trace("returning status 200 for Hproxy check"); ResponseBuilder response = Response.status(HttpStatus.SC_OK); return response.build(); @@ -234,6 +234,7 @@ public class StorageIDResolver { * @throws Exception the exception */ protected Response validationPayload(HttpServletRequest httpRequest, String storageId) throws Exception{ + logger.info("validationPayload called"); //Checking mandatory parameter storageId if (storageId == null || storageId.isEmpty()) { @@ -245,6 +246,7 @@ public class StorageIDResolver { IClient iClient = null; storageId = client.getStorageId(); //IT SHOULD BE CHANGED es. removing the suffix '-VLT' logger.info("I'm using the storageId {}",storageId); + try{ iClient = client.getStorageClient().getClient(); toSEID = iClient.getId(storageId); //to Storage Encrypted ID @@ -259,6 +261,26 @@ public class StorageIDResolver { throw ExceptionManager.notFoundException(httpRequest, "Error on decrypting the "+STORAGE_ID+ " '"+storageId+"'. Is it a valid id?", StorageIDResolver.class, help); } + //SETTING DEFAULT METADATA + String fileName = ConstantsResolver.DEFAULT_FILENAME_FROM_STORAGE_MANAGER; + String contentType = ConstantsResolver.DEFAULT_CONTENTTYPE_UNKNOWN_UNKNOWN; + //READING THE METADATA OF FILE FROM STORAGE + StorageMetadataFile metadataFile = getStorageMetadataFile(iClient,toSEID); + logger.debug("MetaFile retrieved from storage? "+ (metadataFile!=null)); + long size = 0; + + if (metadataFile != null) { + + // Reading the fileName from Storage Metadata only if it is not null + if (metadataFile.getName() != null) + fileName = metadataFile.getName(); + + // Reading the contentType from Storage Metadata only if it is not null + if (metadataFile.getMimeType() != null) + contentType = metadataFile.getMimeType(); + + size = metadataFile.getSize(); + } //Building the response InputStream streamToWrite=iClient.get().RFileAsInputStream(toSEID); //input stream @@ -283,7 +305,12 @@ public class StorageIDResolver { if(response==null) throw ExceptionManager.internalErrorException(httpRequest, "Error on validating the file with id: "+storageId, StorageIDResolver.class, help); - + + response = response + .header("Content-Type", contentType) + .header(ConstantsResolver.CONTENT_LENGTH, size) + .header(ConstantsResolver.CONTENT_DISPOSITION,"attachment; filename=\""+fileName+"\""); + return response.build(); } @@ -312,8 +339,35 @@ public class StorageIDResolver { return new StorageClientInstance(client, memory, storageId); } + + + + /** + * Gets the storage metadata file. + * + * @param iClient the i client + * @param toSEID the to SEID + * @return the storage metadata file + */ + public static StorageMetadataFile getStorageMetadataFile(IClient iClient, String toSEID) { + try{ + if(iClient==null) + throw new Exception("The "+IClient.class.getName()+" is not instancied correclty. It is null!"); + + if(toSEID==null || toSEID.isEmpty()) + throw new Exception("Invalid input identifier. The input Storage Encrypted ID is null or empty!"); + + long size = iClient.getSize().RFileById(toSEID); + MyFile myFile = iClient.getMetaFile().RFile(toSEID); + + return new StorageMetadataFile(myFile, size); + }catch (Exception e) { + logger.warn("Error on getting file metadata from storage, printing this warning and trying to continue..", e); + return null; + } + } } diff --git a/src/main/java/org/gcube/datatransfer/resolver/util/Util.java b/src/main/java/org/gcube/datatransfer/resolver/util/Util.java index 0cfeb6e..6bc85d5 100644 --- a/src/main/java/org/gcube/datatransfer/resolver/util/Util.java +++ b/src/main/java/org/gcube/datatransfer/resolver/util/Util.java @@ -3,7 +3,10 @@ */ package org.gcube.datatransfer.resolver.util; +import java.util.List; + import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.core.MultivaluedMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -94,5 +97,32 @@ public class Util { return string; } + + + /** + * To query string. + * + * @param queryParameters the query parameters + * @return the string + */ + public static String toQueryString(MultivaluedMap queryParameters) { + + if(queryParameters==null || queryParameters.isEmpty()) + return ""; + + StringBuilder queryStringBuilder = new StringBuilder(); + for (String key : queryParameters.keySet()) { + List values = queryParameters.get(key); + for (String value : values) { + queryStringBuilder.append(String.format("%s=%s",key,value)); + queryStringBuilder.append("&"); //The series of pairs is separated by the ampersand, '&' + } + } + String queryString = queryStringBuilder.toString(); + queryString = queryString.endsWith("&")?queryString.substring(0,queryString.length()-1):queryString; + log.debug("Query string built: {}",queryString); + return queryString; + + } }