-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added UTF-8 encoding for blob names in methods that are used to build… #5943
Changes from 8 commits
9230cc1
6b94186
a665c1a
1227465
55ac267
b18fbed
009d5ab
995e411
aa04de2
4b527de
9bcd0a0
2172d80
6489555
dfb9416
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,7 @@ | |
import com.azure.storage.blob.models.BlobAccessConditions; | ||
import com.azure.storage.blob.models.DeleteSnapshotsOptionType; | ||
import com.azure.storage.blob.models.LeaseAccessConditions; | ||
import com.azure.storage.common.Utility; | ||
import com.azure.storage.common.policy.StorageSharedKeyCredentialPolicy; | ||
import reactor.core.Disposable; | ||
import reactor.core.Exceptions; | ||
|
@@ -126,6 +127,8 @@ public final class BlobBatch { | |
/** | ||
* Adds a delete blob operation to the batch. | ||
* | ||
* <p>Blob name is encoded to UTF-8 using the {@link com.azure.storage.common.Utility#urlEncode(String)} method.</p> | ||
* | ||
* <p><strong>Code sample</strong></p> | ||
* | ||
* {@codesnippet com.azure.storage.blob.batch.BlobBatch.deleteBlob#String-String} | ||
|
@@ -137,12 +140,15 @@ public final class BlobBatch { | |
* @throws UnsupportedOperationException If this batch has already added an operation of another type. | ||
*/ | ||
public Response<Void> deleteBlob(String containerName, String blobName) { | ||
return deleteBlobHelper(String.format(PATH_TEMPLATE, containerName, blobName), null, null); | ||
return deleteBlobHelper(String.format(PATH_TEMPLATE, containerName, | ||
Utility.urlEncode(Utility.urlDecode(blobName))), null, null); | ||
} | ||
|
||
/** | ||
* Adds a delete blob operation to the batch. | ||
* | ||
* <p>Blob name is encoded to UTF-8 using the {@link com.azure.storage.common.Utility#urlEncode(String)} method.</p> | ||
* | ||
* <p><strong>Code sample</strong></p> | ||
* | ||
* {@codesnippet com.azure.storage.blob.batch.BlobBatch.deleteBlob#String-String-DeleteSnapshotsOptionType-BlobAccessConditions} | ||
|
@@ -157,8 +163,8 @@ public Response<Void> deleteBlob(String containerName, String blobName) { | |
*/ | ||
public Response<Void> deleteBlob(String containerName, String blobName, | ||
DeleteSnapshotsOptionType deleteOptions, BlobAccessConditions blobAccessConditions) { | ||
return deleteBlobHelper(String.format(PATH_TEMPLATE, containerName, blobName), | ||
deleteOptions, blobAccessConditions); | ||
return deleteBlobHelper(String.format(PATH_TEMPLATE, containerName, | ||
Utility.urlEncode(Utility.urlDecode(blobName))), deleteOptions, blobAccessConditions); | ||
} | ||
|
||
/** | ||
|
@@ -206,6 +212,8 @@ private Response<Void> deleteBlobHelper(String urlPath, DeleteSnapshotsOptionTyp | |
/** | ||
* Adds a set tier operation to the batch. | ||
* | ||
* <p>Blob name is encoded to UTF-8 using the {@link com.azure.storage.common.Utility#urlEncode(String)} method.</p> | ||
* | ||
* <p><strong>Code sample</strong></p> | ||
* | ||
* {@codesnippet com.azure.storage.blob.batch.BlobBatch.setBlobAccessTier#String-String-AccessTier} | ||
|
@@ -218,12 +226,15 @@ private Response<Void> deleteBlobHelper(String urlPath, DeleteSnapshotsOptionTyp | |
* @throws UnsupportedOperationException If this batch has already added an operation of another type. | ||
*/ | ||
public Response<Void> setBlobAccessTier(String containerName, String blobName, AccessTier accessTier) { | ||
return setBlobAccessTierHelper(String.format(PATH_TEMPLATE, containerName, blobName), accessTier, null); | ||
return setBlobAccessTierHelper(String.format(PATH_TEMPLATE, containerName, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comment about calling the next overload. |
||
Utility.urlEncode(Utility.urlDecode(blobName))), accessTier, null); | ||
} | ||
|
||
/** | ||
* Adds a set tier operation to the batch. | ||
* | ||
* <p>Blob name is encoded to UTF-8 using the {@link com.azure.storage.common.Utility#urlEncode(String)} method.</p> | ||
* | ||
* <p><strong>Code sample</strong></p> | ||
* | ||
* {@codesnippet com.azure.storage.blob.batch.BlobBatch.setBlobAccessTier#String-String-AccessTier-LeaseAccessConditions} | ||
|
@@ -238,8 +249,8 @@ public Response<Void> setBlobAccessTier(String containerName, String blobName, A | |
*/ | ||
public Response<Void> setBlobAccessTier(String containerName, String blobName, AccessTier accessTier, | ||
LeaseAccessConditions leaseAccessConditions) { | ||
return setBlobAccessTierHelper(String.format(PATH_TEMPLATE, containerName, blobName), accessTier, | ||
leaseAccessConditions); | ||
return setBlobAccessTierHelper(String.format(PATH_TEMPLATE, containerName, | ||
Utility.urlEncode(Utility.urlDecode(blobName))), accessTier, leaseAccessConditions); | ||
} | ||
|
||
/** | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,6 +24,7 @@ | |
import com.azure.storage.blob.BlobContainerAsyncClient; | ||
import com.azure.storage.blob.BlobServiceVersion; | ||
import com.azure.storage.blob.BlobUrlParts; | ||
import com.azure.storage.common.Utility; | ||
import com.azure.storage.common.implementation.Constants; | ||
import com.azure.storage.common.StorageSharedKeyCredential; | ||
import com.azure.storage.common.implementation.connectionstring.StorageAuthenticationSettings; | ||
|
@@ -104,6 +105,8 @@ public EncryptedBlobClientBuilder() { | |
/** | ||
* Creates a {@link EncryptedBlobClient} based on options set in the Builder. | ||
* | ||
* <p>Blob name is encoded to UTF-8 using the {@link com.azure.storage.common.Utility#urlEncode(String)} method.</p> | ||
* | ||
* <p><strong>Code Samples</strong></p> | ||
* | ||
* {@codesnippet com.azure.storage.blob.specialized.cryptography.EncryptedBlobClientBuilder.buildEncryptedBlobAsyncClient} | ||
|
@@ -118,6 +121,8 @@ public EncryptedBlobClient buildEncryptedBlobClient() { | |
/** | ||
* Creates a {@link EncryptedBlobAsyncClient} based on options set in the Builder. | ||
* | ||
* <p>Blob name is encoded to UTF-8 using the {@link com.azure.storage.common.Utility#urlEncode(String)} method.</p> | ||
* | ||
* <p><strong>Code Samples</strong></p> | ||
* | ||
* {@codesnippet com.azure.storage.blob.specialized.cryptography.EncryptedBlobClientBuilder.buildEncryptedBlobClient} | ||
|
@@ -324,6 +329,8 @@ public EncryptedBlobClientBuilder connectionString(String connectionString) { | |
* with blobs in the root container, it is best to set the endpoint to the account url and specify the blob name | ||
* separately using the {@link EncryptedBlobClientBuilder#blobName(String) blobName} method.</p> | ||
* | ||
* <p>Blob name is encoded to UTF-8 using the {@link com.azure.storage.common.Utility#urlEncode(String)} method.</p> | ||
* | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems like it's setting us up for double encoding since they're already handing us an endpoint. I thought we agreed to have an overload that accepts a doNotEncodeBlobName flag or whatever it should be called. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I think there was also a communication mishap on my behalf when I told you about the last approach I discussed with Alan. There are several reasons why I think it's best to just implicitly do encoding for the user instead of letting the responsibility rest with them:
The bottomline is that I believe implicit encoding is the most user-friendly way as long as we make sure we don't double encode anywhere in the flow. What do you think? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't see that you were doing a urlDecode before urlEncode in the setters. In that case, I think I'm fine with the PR as long as you add the update to return the unencoded name since we're assuming that will be the most common case And can you actually also add to either the existing test or a new test that passes in an already encoded name and ensures it doesn't get double encoded. And also getting the name off of one client and passing it to another and again checking it doesn't get double encoded? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will add said getter and test changes. |
||
* @param endpoint URL of the service | ||
* @return the updated EncryptedBlobClientBuilder object | ||
* @throws IllegalArgumentException If {@code endpoint} is {@code null} or is a malformed URL. | ||
|
@@ -365,12 +372,15 @@ public EncryptedBlobClientBuilder containerName(String containerName) { | |
/** | ||
* Sets the name of the blob. | ||
* | ||
* <p>Blob name is encoded to UTF-8 using the {@link com.azure.storage.common.Utility#urlEncode(String)} method.</p> | ||
* | ||
* @param blobName Name of the blob. | ||
* @return the updated EncryptedBlobClientBuilder object | ||
* @throws NullPointerException If {@code blobName} is {@code null} | ||
*/ | ||
public EncryptedBlobClientBuilder blobName(String blobName) { | ||
this.blobName = Objects.requireNonNull(blobName, "'blobName' cannot be null."); | ||
this.blobName = Utility.urlEncode(Utility.urlDecode(Objects.requireNonNull(blobName, | ||
"'blobName' cannot be null."))); | ||
return this; | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -76,6 +76,8 @@ public class BlobAsyncClient extends BlobAsyncClientBase { | |
/** | ||
* Package-private constructor for use by {@link BlobClientBuilder}. | ||
* | ||
* <p>Blob name is encoded to UTF-8 using the {@link com.azure.storage.common.Utility#urlEncode(String)} method.</p> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think these comments on the constructors are accurate because the encoding happens in the builder. It seems like it's more accurate to say these constructors expect that the blobName is already properly encoded. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought of adding said comments wherever a As a side note, there are some cases where the |
||
* | ||
* @param pipeline The pipeline used to send and receive service requests. | ||
* @param url The endpoint where to send service requests. | ||
* @param serviceVersion The version of the service to receive requests. | ||
|
@@ -94,6 +96,8 @@ protected BlobAsyncClient(HttpPipeline pipeline, String url, BlobServiceVersion | |
/** | ||
* Creates a new {@link BlobAsyncClient} linked to the {@code snapshot} of this blob resource. | ||
* | ||
* <p>Blob name is encoded to UTF-8 using the {@link com.azure.storage.common.Utility#urlEncode(String)} method.</p> | ||
* | ||
* @param snapshot the identifier for a specific snapshot of this blob | ||
* @return a {@link BlobAsyncClient} used to interact with the specific snapshot. | ||
*/ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -129,6 +129,8 @@ public BlobUrlParts setContainerName(String containerName) { | |
/** | ||
* Gets the blob name that will be used as part of the URL path. | ||
* | ||
* <p>Blob name is encoded to UTF-8 using the {@link com.azure.storage.common.Utility#urlEncode(String)} method.</p> | ||
* | ||
* @return the blob name. | ||
*/ | ||
public String getBlobName() { | ||
|
@@ -138,11 +140,13 @@ public String getBlobName() { | |
/** | ||
* Sets the blob name that will be used as part of the URL path. | ||
* | ||
* <p>Blob name is encoded to UTF-8 using the {@link com.azure.storage.common.Utility#urlEncode(String)} method.</p> | ||
* | ||
* @param blobName The blob name. | ||
* @return the updated BlobUrlParts object. | ||
*/ | ||
public BlobUrlParts setBlobName(String blobName) { | ||
this.blobName = blobName; | ||
this.blobName = Utility.urlEncode(Utility.urlDecode(blobName)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Overload to skip encoding? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See answer about overloads and double encoding above. |
||
return this; | ||
} | ||
|
||
|
@@ -211,6 +215,8 @@ public BlobUrlParts setUnparsedParameters(Map<String, String[]> unparsedParamete | |
/** | ||
* Converts the blob URL parts to a {@link URL}. | ||
* | ||
* <p>Blob name is encoded to UTF-8 using the {@link com.azure.storage.common.Utility#urlEncode(String)} method.</p> | ||
* | ||
* @return A {@code URL} to the blob resource composed of all the elements in this object. | ||
* @throws IllegalStateException The fields present on the BlobUrlParts object were insufficient to construct a | ||
* valid URL or were ill-formatted. | ||
|
@@ -267,6 +273,8 @@ public URL toUrl() { | |
* is no path element for the container, the name of this blob in the root container will be set as the | ||
* containerName field in the resulting {@code BlobURLParts}.</p> | ||
* | ||
* <p>Blob name is encoded to UTF-8 using the {@link com.azure.storage.common.Utility#urlEncode(String)} method.</p> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Another place that feels likely to give us double encoding since we are taking in a URL There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See answer about overloads and double encoding above. |
||
* | ||
* @param url The {@code URL} to be parsed. | ||
* @return A {@link BlobUrlParts} object containing all the components of a BlobURL. | ||
* @throws IllegalArgumentException If {@code url} is a malformed {@link URL}. | ||
|
@@ -290,6 +298,8 @@ public static BlobUrlParts parse(String url) { | |
* is no path element for the container, the name of this blob in the root container will be set as the | ||
* containerName field in the resulting {@code BlobURLParts}.</p> | ||
* | ||
* <p>Blob name is encoded to UTF-8 using the {@link com.azure.storage.common.Utility#urlEncode(String)} method.</p> | ||
* | ||
* @param url The {@code URL} to be parsed. | ||
* @return A {@link BlobUrlParts} object containing all the components of a BlobURL. | ||
*/ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,6 +38,7 @@ | |
import com.azure.storage.blob.models.ReliableDownloadOptions; | ||
import com.azure.storage.blob.models.SourceModifiedAccessConditions; | ||
import com.azure.storage.blob.models.StorageAccountInfo; | ||
import com.azure.storage.common.Utility; | ||
import com.azure.storage.common.implementation.Constants; | ||
import com.azure.storage.common.implementation.StorageImplUtils; | ||
import reactor.core.publisher.Flux; | ||
|
@@ -91,6 +92,8 @@ public class BlobAsyncClientBase { | |
/** | ||
* Package-private constructor for use by {@link SpecializedBlobClientBuilder}. | ||
* | ||
* <p>Blob name is encoded to UTF-8 using the {@link com.azure.storage.common.Utility#urlEncode(String)} method.</p> | ||
* | ||
* @param pipeline The pipeline used to send and receive service requests. | ||
* @param url The endpoint where to send service requests. | ||
* @param serviceVersion The version of the service to receive requests. | ||
|
@@ -112,7 +115,7 @@ protected BlobAsyncClientBase(HttpPipeline pipeline, String url, BlobServiceVers | |
|
||
this.accountName = accountName; | ||
this.containerName = containerName; | ||
this.blobName = blobName; | ||
this.blobName = Utility.urlEncode(Utility.urlDecode(blobName)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't we encode in the builder, so encoding in the constructor again would be double encoding? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See answer about overloads and double encoding above. |
||
this.snapshot = snapshot; | ||
this.customerProvidedKey = customerProvidedKey; | ||
} | ||
|
@@ -161,6 +164,8 @@ public final String getContainerName() { | |
/** | ||
* Get the blob name. | ||
* | ||
* <p>Blob name is encoded to UTF-8 using the {@link com.azure.storage.common.Utility#urlEncode(String)} method.</p> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I also don't know that we should specify what method is doing the encoding since Utilities are supposed to be implementation details There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should also probably be decoding on gets if we are encoding on sets. For one, we want it to round trip. For another, what if someone gets the name of one blob so they can set it as the name of a blob in a different container. Now we encode the name on setting it for the first blob, don't decode it in the getter, then encode it again in the second builder. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree we can leave out which method is used for encoding as long as we specify is UTF-8. As for the getters, even though we won't incur in any double encoding (see comment about that and overloads above), it sounds good to me so that users will always get to see and manipulate the original name of the blob. |
||
* | ||
* <p><strong>Code Samples</strong></p> | ||
* | ||
* {@codesnippet com.azure.storage.blob.specialized.BlobAsyncClientBase.getBlobName} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should just call into the next overload so we don't have to worry about missing formatting/encoding logic in one of them
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right, let's make it call the next overload.