Add XML elements to S3Exception

This allows more descriptive errors, e.g., giving argument name when
returning InvalidArgument.
pull/59/head
Andrew Gaul 2015-05-01 05:00:59 -07:00
rodzic abc1bc4910
commit 7fde437a7b
1 zmienionych plików z 34 dodań i 26 usunięć

Wyświetl plik

@ -18,8 +18,6 @@ package org.gaul.s3proxy;
import static java.util.Objects.requireNonNull; import static java.util.Objects.requireNonNull;
import static com.google.common.base.Preconditions.checkArgument;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
@ -202,11 +200,14 @@ final class S3ProxyHandler extends AbstractHandler {
try { try {
doHandle(target, baseRequest, request, response); doHandle(target, baseRequest, request, response);
} catch (ContainerNotFoundException cnfe) { } catch (ContainerNotFoundException cnfe) {
sendSimpleErrorResponse(response, S3ErrorCode.NO_SUCH_BUCKET); S3ErrorCode code = S3ErrorCode.NO_SUCH_BUCKET;
sendSimpleErrorResponse(response, code, code.getMessage(),
ImmutableMap.<String, String>of());
baseRequest.setHandled(true); baseRequest.setHandled(true);
return; return;
} catch (S3Exception se) { } catch (S3Exception se) {
sendSimpleErrorResponse(response, se.getError()); sendSimpleErrorResponse(response, se.getError(),
se.getMessage(), se.getElements());
baseRequest.setHandled(true); baseRequest.setHandled(true);
return; return;
} }
@ -246,11 +247,9 @@ final class S3ProxyHandler extends AbstractHandler {
if (defaultBlobStore == null && !hasDateHeader && !hasXAmzDateHeader && if (defaultBlobStore == null && !hasDateHeader && !hasXAmzDateHeader &&
request.getParameter("Expires") == null) { request.getParameter("Expires") == null) {
sendSimpleErrorResponse(response, S3ErrorCode.ACCESS_DENIED, throw new S3Exception(S3ErrorCode.ACCESS_DENIED,
"AWS authentication requires a valid Date or" + "AWS authentication requires a valid Date or" +
" x-amz-date header", null, null); " x-amz-date header");
baseRequest.setHandled(true);
return;
} }
// TODO: apply sanity checks to X-Amz-Date // TODO: apply sanity checks to X-Amz-Date
@ -763,10 +762,8 @@ final class S3ProxyHandler extends AbstractHandler {
throw new S3Exception(S3ErrorCode.BUCKET_ALREADY_EXISTS, ae); throw new S3Exception(S3ErrorCode.BUCKET_ALREADY_EXISTS, ae);
} }
if (!created) { if (!created) {
S3ErrorCode errorCode = S3ErrorCode.BUCKET_ALREADY_OWNED_BY_YOU; throw new S3Exception(S3ErrorCode.BUCKET_ALREADY_OWNED_BY_YOU,
sendSimpleErrorResponse(response, null, null, ImmutableMap.of("BucketName", containerName));
errorCode, errorCode.getMessage(), "BucketName",
containerName);
} }
} }
@ -1521,16 +1518,9 @@ final class S3ProxyHandler extends AbstractHandler {
} }
private void sendSimpleErrorResponse(HttpServletResponse response, private void sendSimpleErrorResponse(HttpServletResponse response,
S3ErrorCode code) throws IOException { S3ErrorCode code, String message,
sendSimpleErrorResponse(response, code, code.getMessage(), null, null); Map<String, String> elements) throws IOException {
} logger.debug("{} {}", code, elements);
private void sendSimpleErrorResponse(HttpServletResponse response,
S3ErrorCode code, String message, String element, String characters)
throws IOException {
checkArgument(!(element == null ^ characters == null),
"Must specify neither or both element and characters");
logger.debug("{} {} {}", code, element, characters);
try (Writer writer = response.getWriter()) { try (Writer writer = response.getWriter()) {
XMLStreamWriter xml = xmlOutputFactory.createXMLStreamWriter( XMLStreamWriter xml = xmlOutputFactory.createXMLStreamWriter(
@ -1542,8 +1532,8 @@ final class S3ProxyHandler extends AbstractHandler {
writeSimpleElement(xml, "Code", code.getErrorCode()); writeSimpleElement(xml, "Code", code.getErrorCode());
writeSimpleElement(xml, "Message", message); writeSimpleElement(xml, "Message", message);
if (element != null) { for (Map.Entry<String, String> entry : elements.entrySet()) {
writeSimpleElement(xml, element, characters); writeSimpleElement(xml, entry.getKey(), entry.getValue());
} }
writeSimpleElement(xml, "RequestId", FAKE_REQUEST_ID); writeSimpleElement(xml, "RequestId", FAKE_REQUEST_ID);
@ -1562,19 +1552,37 @@ final class S3ProxyHandler extends AbstractHandler {
@SuppressWarnings("serial") @SuppressWarnings("serial")
static class S3Exception extends Exception { static class S3Exception extends Exception {
private final S3ErrorCode error; private final S3ErrorCode error;
private final Map<String, String> elements;
S3Exception(S3ErrorCode error) { S3Exception(S3ErrorCode error) {
this(error, null); this(error, error.getMessage(), (Throwable) null,
ImmutableMap.<String, String>of());
}
S3Exception(S3ErrorCode error, String message) {
this(error, message, (Throwable) null,
ImmutableMap.<String, String>of());
} }
S3Exception(S3ErrorCode error, Throwable cause) { S3Exception(S3ErrorCode error, Throwable cause) {
super(cause); this(error, error.getMessage(), cause,
ImmutableMap.<String, String>of());
}
S3Exception(S3ErrorCode error, String message, Throwable cause,
Map<String, String> elements) {
super(message, cause);
this.error = requireNonNull(error); this.error = requireNonNull(error);
this.elements = ImmutableMap.copyOf(elements);
} }
S3ErrorCode getError() { S3ErrorCode getError() {
return error; return error;
} }
Map<String, String> getElements() {
return elements;
}
} }
/** /**