URL encode blob names when client requests it

This allows support for characters which XML 1.0 cannot represent and
improves compatibility with newer versions of the AWS CLI.
Fixes #104.
pull/102/merge
Derrek Leute 2015-12-11 10:18:07 -05:00 zatwierdzone przez Andrew Gaul
rodzic 23cff3a61d
commit d8c73bc86d
1 zmienionych plików z 38 dodań i 5 usunięć

Wyświetl plik

@ -23,8 +23,10 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PushbackInputStream;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
@ -140,6 +142,7 @@ final class S3ProxyHandler extends AbstractHandler {
"AWSAccessKeyId",
"delete",
"delimiter",
"encoding-type",
"Expires",
"location",
"marker",
@ -955,6 +958,7 @@ final class S3ProxyHandler extends AbstractHandler {
String blobStoreType = getBlobStoreType(blobStore);
ListContainerOptions options = new ListContainerOptions();
String delimiter = request.getParameter("delimiter");
String encodingType = request.getParameter("encoding-type");
if (delimiter != null) {
options.delimiter(delimiter);
} else {
@ -1002,7 +1006,8 @@ final class S3ProxyHandler extends AbstractHandler {
if (prefix == null) {
xml.writeEmptyElement("Prefix");
} else {
writeSimpleElement(xml, "Prefix", prefix);
writeSimpleElement(xml, "Prefix", encodeBlob(
request.getParameter("encoding-type"), prefix));
}
writeSimpleElement(xml, "MaxKeys", String.valueOf(maxKeys));
@ -1010,17 +1015,24 @@ final class S3ProxyHandler extends AbstractHandler {
if (marker == null) {
xml.writeEmptyElement("Marker");
} else {
writeSimpleElement(xml, "Marker", marker);
writeSimpleElement(xml, "Marker", encodeBlob(
request.getParameter("encoding-type"), marker));
}
if (delimiter != null) {
writeSimpleElement(xml, "Delimiter", delimiter);
writeSimpleElement(xml, "Delimiter", encodeBlob(
request.getParameter("encoding-type"), delimiter));
}
if (encodingType != null && encodingType.equals("url")) {
writeSimpleElement(xml, "Encoding-Type", encodingType);
}
String nextMarker = set.getNextMarker();
if (nextMarker != null) {
writeSimpleElement(xml, "IsTruncated", "true");
writeSimpleElement(xml, "NextMarker", nextMarker);
writeSimpleElement(xml, "NextMarker", encodeBlob(
request.getParameter("encoding-type"), nextMarker));
if (BLOBSTORE_OPAQUE_MARKERS.contains(blobStoreType)) {
lastKeyToMarker.put(Maps.immutableEntry(containerName,
Iterables.getLast(set).getName()), nextMarker);
@ -1649,6 +1661,8 @@ final class S3ProxyHandler extends AbstractHandler {
List<MultipartPart> parts = blobStore.listMultipartUpload(mpu);
String encodingType = request.getParameter("encoding-type");
try (Writer writer = response.getWriter()) {
XMLStreamWriter xml = xmlOutputFactory.createXMLStreamWriter(
writer);
@ -1656,8 +1670,13 @@ final class S3ProxyHandler extends AbstractHandler {
xml.writeStartElement("ListPartsResult");
xml.writeDefaultNamespace(AWS_XMLNS);
if (encodingType != null && encodingType.equals("url")) {
writeSimpleElement(xml, "Encoding-Type", encodingType);
}
writeSimpleElement(xml, "Bucket", containerName);
writeSimpleElement(xml, "Key", blobName);
writeSimpleElement(xml, "Key", encodeBlob(
request.getParameter("encoding-type"), blobName));
writeSimpleElement(xml, "UploadId", uploadId);
// TODO: bogus values
@ -2283,4 +2302,18 @@ final class S3ProxyHandler extends AbstractHandler {
private static boolean startsWithIgnoreCase(String string, String prefix) {
return string.toLowerCase().startsWith(prefix.toLowerCase());
}
// Encode blob name if client requests it. This allows for characters
// which XML 1.0 cannot represent.
private static String encodeBlob(String encodingType, String blobName) {
if (encodingType != null && encodingType.equals("url")) {
try {
return URLEncoder.encode(blobName, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw Throwables.propagate(e);
}
} else {
return blobName;
}
}
}