kopia lustrzana https://github.com/gaul/s3proxy
Add support for listing multipart uploads
Only supported in Azure, B2, and S3. Fixes #118.pull/139/merge
rodzic
72138e1278
commit
187eb065aa
|
@ -61,6 +61,16 @@ final class Quirks {
|
|||
"azureblob"
|
||||
);
|
||||
|
||||
static final Set<String> NO_LIST_MULTIPART_UPLOADS = ImmutableSet.of(
|
||||
"atmos",
|
||||
"filesystem",
|
||||
"google-cloud-storage",
|
||||
"openstack-swift",
|
||||
"rackspace-cloudfiles-uk",
|
||||
"rackspace-cloudfiles-us",
|
||||
"transient"
|
||||
);
|
||||
|
||||
/** Blobstores which do not allow listing zero keys. */
|
||||
static final Set<String> NO_LIST_ZERO_KEYS = ImmutableSet.of(
|
||||
"atmos",
|
||||
|
|
|
@ -501,8 +501,8 @@ final class S3ProxyHandler extends AbstractHandler {
|
|||
handleContainerLocation(response, blobStore, path[1]);
|
||||
return;
|
||||
} else if ("".equals(request.getParameter("uploads"))) {
|
||||
handleListMultipartUploads(response, blobStore,
|
||||
uploadId);
|
||||
handleListMultipartUploads(request, response, blobStore,
|
||||
path[1]);
|
||||
return;
|
||||
}
|
||||
handleBlobList(request, response, blobStore, path[1]);
|
||||
|
@ -974,11 +974,64 @@ final class S3ProxyHandler extends AbstractHandler {
|
|||
}
|
||||
}
|
||||
|
||||
private void handleListMultipartUploads(HttpServletResponse response,
|
||||
BlobStore blobStore, String uploadId)
|
||||
throws IOException, S3Exception {
|
||||
// TODO: list all blobs starting with uploadId
|
||||
throw new S3Exception(S3ErrorCode.NOT_IMPLEMENTED);
|
||||
private void handleListMultipartUploads(HttpServletRequest request,
|
||||
HttpServletResponse response, BlobStore blobStore,
|
||||
String container) throws IOException, S3Exception {
|
||||
if (request.getParameter("delimiter") != null ||
|
||||
request.getParameter("prefix") != null ||
|
||||
request.getParameter("max-uploads") != null ||
|
||||
request.getParameter("key-marker") != null ||
|
||||
request.getParameter("upload-id-marker") != null) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
List<MultipartUpload> uploads = blobStore.listMultipartUploads(
|
||||
container);
|
||||
|
||||
try (Writer writer = response.getWriter()) {
|
||||
XMLStreamWriter xml = xmlOutputFactory.createXMLStreamWriter(
|
||||
writer);
|
||||
xml.writeStartDocument();
|
||||
xml.writeStartElement("ListMultipartUploadsResult");
|
||||
xml.writeDefaultNamespace(AWS_XMLNS);
|
||||
|
||||
writeSimpleElement(xml, "Bucket", container);
|
||||
|
||||
// TODO: bogus values
|
||||
xml.writeEmptyElement("KeyMarker");
|
||||
xml.writeEmptyElement("UploadIdMarker");
|
||||
xml.writeEmptyElement("NextKeyMarker");
|
||||
xml.writeEmptyElement("NextUploadIdMarker");
|
||||
xml.writeEmptyElement("Delimiter");
|
||||
xml.writeEmptyElement("Prefix");
|
||||
writeSimpleElement(xml, "MaxUploads", "1000");
|
||||
writeSimpleElement(xml, "IsTruncated", "false");
|
||||
|
||||
for (MultipartUpload upload : uploads) {
|
||||
xml.writeStartElement("Upload");
|
||||
|
||||
writeSimpleElement(xml, "Key", upload.blobName());
|
||||
writeSimpleElement(xml, "UploadId", upload.id());
|
||||
writeInitiatorStanza(xml);
|
||||
writeOwnerStanza(xml);
|
||||
writeSimpleElement(xml, "StorageClass", "STANDARD");
|
||||
|
||||
// TODO: bogus value
|
||||
writeSimpleElement(xml, "Initiated",
|
||||
blobStore.getContext().utils().date()
|
||||
.iso8601DateFormat(new Date()));
|
||||
|
||||
xml.writeEndElement();
|
||||
}
|
||||
|
||||
xml.writeEmptyElement("CommonPrefixes");
|
||||
|
||||
xml.writeEndElement();
|
||||
|
||||
xml.flush();
|
||||
} catch (XMLStreamException xse) {
|
||||
throw new IOException(xse);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleContainerExists(HttpServletResponse response,
|
||||
|
@ -1923,18 +1976,8 @@ final class S3ProxyHandler extends AbstractHandler {
|
|||
writeSimpleElement(xml, "Key", encodeBlob(
|
||||
encodingType, blobName));
|
||||
writeSimpleElement(xml, "UploadId", uploadId);
|
||||
|
||||
// TODO: bogus values
|
||||
xml.writeStartElement("Initiator");
|
||||
|
||||
writeSimpleElement(xml, "ID", FAKE_INITIATOR_ID);
|
||||
writeSimpleElement(xml, "DisplayName",
|
||||
FAKE_INITIATOR_DISPLAY_NAME);
|
||||
|
||||
xml.writeEndElement();
|
||||
|
||||
writeInitiatorStanza(xml);
|
||||
writeOwnerStanza(xml);
|
||||
|
||||
writeSimpleElement(xml, "StorageClass", "STANDARD");
|
||||
|
||||
// TODO: pagination
|
||||
|
@ -2604,6 +2647,18 @@ final class S3ProxyHandler extends AbstractHandler {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: bogus values
|
||||
private static void writeInitiatorStanza(XMLStreamWriter xml)
|
||||
throws XMLStreamException {
|
||||
xml.writeStartElement("Initiator");
|
||||
|
||||
writeSimpleElement(xml, "ID", FAKE_INITIATOR_ID);
|
||||
writeSimpleElement(xml, "DisplayName",
|
||||
FAKE_INITIATOR_DISPLAY_NAME);
|
||||
|
||||
xml.writeEndElement();
|
||||
}
|
||||
|
||||
// TODO: bogus values
|
||||
private static void writeOwnerStanza(XMLStreamWriter xml)
|
||||
throws XMLStreamException {
|
||||
|
|
|
@ -123,6 +123,14 @@ public final class JcloudsS3BlobIntegrationLiveTest
|
|||
super.testCopyIfNoneMatchNegative();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testListMultipartUploads() throws Exception {
|
||||
if (Quirks.NO_LIST_MULTIPART_UPLOADS.contains(blobStoreType)) {
|
||||
throw new SkipException("list multipart uploads not supported");
|
||||
}
|
||||
super.testListMultipartUploads();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void checkCacheControl(Blob blob, String cacheControl) {
|
||||
if (!Quirks.NO_CACHE_CONTROL_SUPPORT.contains(blobStoreType)) {
|
||||
|
|
|
@ -162,6 +162,14 @@ public final class JcloudsS3ClientLiveTest extends S3ClientLiveTest {
|
|||
super.testUpdateObjectCannedACL();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testListMultipartUploads() throws Exception {
|
||||
if (Quirks.NO_LIST_MULTIPART_UPLOADS.contains(blobStoreType)) {
|
||||
throw new SkipException("list multipart uploads not supported");
|
||||
}
|
||||
super.testListMultipartUploads();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void assertCacheControl(S3Object newObject, String string) {
|
||||
if (Quirks.NO_CACHE_CONTROL_SUPPORT.contains(blobStoreType)) {
|
||||
|
|
Ładowanie…
Reference in New Issue