From 096b7826d92686d256f57e5fc60d352c8f6f8521 Mon Sep 17 00:00:00 2001 From: Matt Houglum Date: Wed, 14 Aug 2019 19:53:38 +0000 Subject: [PATCH 1/2] Small refactoring to signUrl code. This commit attempts to refactor some of the functionality in signUrl such that it's easier to follow and will be easier to add functionality for generating virtual hosted-style signed URLs. The branch containing the changes is shown below; this commit is mostly trying to separate refactoring from new functionality being added: https://github.com/houglum/google-cloud-java/compare/6e0f6ef..b52205b This commit also contains a couple of small doc tweaks. --- .../com/google/cloud/storage/Storage.java | 10 ++-- .../com/google/cloud/storage/StorageImpl.java | 51 +++++++++++-------- 2 files changed, 38 insertions(+), 23 deletions(-) diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java index 9c7f5b581023..3c29ca24a58a 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/Storage.java @@ -958,7 +958,8 @@ public static SignUrlOption withMd5() { * Use it if signature should include the blob's canonicalized extended headers. When used, * users of the signed URL should include the canonicalized extended headers with their request. * - * @see + * @see Request + * Headers */ public static SignUrlOption withExtHeaders(Map extHeaders) { return new SignUrlOption(Option.EXT_HEADERS, extHeaders); @@ -986,13 +987,16 @@ public static SignUrlOption withV4Signature() { * get it from the environment. * * @see Service - * account + * Accounts */ public static SignUrlOption signWith(ServiceAccountSigner signer) { return new SignUrlOption(Option.SERVICE_ACCOUNT_CRED, signer); } - /** Use a different host name than the default host name 'storage.googleapis.com' */ + /** + * Use a different host name than the default host name 'https://storage.googleapis.com'. This + * must also include the scheme component of the URI. + */ public static SignUrlOption withHostName(String hostName) { return new SignUrlOption(Option.HOST_NAME, hostName); } diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java index 6f127ac5fb0c..db03cea94f92 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java @@ -50,6 +50,7 @@ import com.google.cloud.storage.Acl.Entity; import com.google.cloud.storage.spi.v1.StorageRpc; import com.google.cloud.storage.spi.v1.StorageRpc.RewriteResponse; +import com.google.common.base.CharMatcher; import com.google.common.base.Function; import com.google.common.base.Preconditions; import com.google.common.base.Strings; @@ -636,23 +637,24 @@ public URL signUrl(BlobInfo blobInfo, long duration, TimeUnit unit, SignUrlOptio getOptions().getClock().millisTime() + unit.toMillis(duration), TimeUnit.MILLISECONDS); - StringBuilder stPath = new StringBuilder(); - if (!blobInfo.getBucket().startsWith(PATH_DELIMITER)) { - stPath.append(PATH_DELIMITER); + String storageXmlHostName = + optionMap.get(SignUrlOption.Option.HOST_NAME) != null + ? (String) optionMap.get(SignUrlOption.Option.HOST_NAME) + : STORAGE_XML_HOST_NAME; + + // The bucket name itself should never contain a forward slash. However, parts already existed + // in the code to check for this, so we remove the forward slashes to be safe here. + String bucketName = CharMatcher.anyOf(PATH_DELIMITER).trimFrom(blobInfo.getBucket()); + String escapedBlobName = ""; + if (!Strings.isNullOrEmpty(blobInfo.getName())) { + escapedBlobName = + UrlEscapers.urlFragmentEscaper().escape(blobInfo.getName()) + .replace("?", "%3F") + .replace(";", "%3B"); } - stPath.append(blobInfo.getBucket()); - if (!blobInfo.getBucket().endsWith(PATH_DELIMITER) - && !Strings.isNullOrEmpty(blobInfo.getName())) { - stPath.append(PATH_DELIMITER); - } - if (blobInfo.getName().startsWith(PATH_DELIMITER)) { - stPath.setLength(stPath.length() - 1); - } - - String escapedName = UrlEscapers.urlFragmentEscaper().escape(blobInfo.getName()); - stPath.append(escapedName.replace("?", "%3F").replace(";", "%3B")); - URI path = URI.create(stPath.toString()); + String stPath = constructResourceUriPath(bucketName, escapedBlobName); + URI path = URI.create(stPath); try { SignatureInfo signatureInfo = @@ -660,11 +662,7 @@ public URL signUrl(BlobInfo blobInfo, long duration, TimeUnit unit, SignUrlOptio String unsignedPayload = signatureInfo.constructUnsignedPayload(); byte[] signatureBytes = credentials.sign(unsignedPayload.getBytes(UTF_8)); StringBuilder stBuilder = new StringBuilder(); - if (optionMap.get(SignUrlOption.Option.HOST_NAME) == null) { - stBuilder.append(STORAGE_XML_HOST_NAME).append(path); - } else { - stBuilder.append(optionMap.get(SignUrlOption.Option.HOST_NAME)).append(path); - } + stBuilder.append(storageXmlHostName).append(path); if (isV4) { BaseEncoding encoding = BaseEncoding.base16().lowerCase(); @@ -688,6 +686,19 @@ public URL signUrl(BlobInfo blobInfo, long duration, TimeUnit unit, SignUrlOptio } } + private String constructResourceUriPath(String slashlessBucketName, String escapedBlobName) { + StringBuilder pathBuilder = new StringBuilder(); + pathBuilder.append(PATH_DELIMITER).append(slashlessBucketName); + if (Strings.isNullOrEmpty(escapedBlobName)) { + return pathBuilder.toString(); + } + if (!escapedBlobName.startsWith(PATH_DELIMITER)) { + pathBuilder.append(PATH_DELIMITER); + } + pathBuilder.append(escapedBlobName); + return pathBuilder.toString(); + } + /** * Builds signature info. * From ae8e31254da5b0b000625fdfec8237817c3c3fbf Mon Sep 17 00:00:00 2001 From: Matt Houglum Date: Fri, 16 Aug 2019 23:07:45 +0000 Subject: [PATCH 2/2] Run `mvn com.coveo:fmt-maven-plugin:format`. --- .../src/main/java/com/google/cloud/storage/StorageImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java index db03cea94f92..7547ff117e92 100644 --- a/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java +++ b/google-cloud-clients/google-cloud-storage/src/main/java/com/google/cloud/storage/StorageImpl.java @@ -648,7 +648,8 @@ public URL signUrl(BlobInfo blobInfo, long duration, TimeUnit unit, SignUrlOptio String escapedBlobName = ""; if (!Strings.isNullOrEmpty(blobInfo.getName())) { escapedBlobName = - UrlEscapers.urlFragmentEscaper().escape(blobInfo.getName()) + UrlEscapers.urlFragmentEscaper() + .escape(blobInfo.getName()) .replace("?", "%3F") .replace(";", "%3B"); }