1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.bremersee.data.minio;
18
19 import io.minio.errors.BucketPolicyTooLargeException;
20 import io.minio.errors.ErrorResponseException;
21 import io.minio.errors.InsufficientDataException;
22 import io.minio.errors.InternalException;
23 import io.minio.errors.InvalidResponseException;
24 import io.minio.errors.ServerException;
25 import io.minio.errors.XmlParserException;
26 import io.minio.messages.ErrorResponse;
27 import java.io.IOException;
28 import java.util.Optional;
29 import okhttp3.Response;
30 import org.springframework.util.StringUtils;
31
32
33
34
35
36
37 public class DefaultMinioErrorHandler extends AbstractMinioErrorHandler {
38
39 static final String ERROR_CODE_PREFIX = "MINIO_";
40
41 @Override
42 public MinioException map(Throwable t) {
43 if (t instanceof IllegalArgumentException) {
44 return new MinioException(
45 400,
46 ERROR_CODE_PREFIX + "BAD_REQUEST",
47 StringUtils.hasText(t.getMessage()) ? t.getMessage() : "Bad request.",
48 t);
49 }
50 if (t instanceof IOException) {
51 return new MinioException(
52 500,
53 ERROR_CODE_PREFIX + "IO_ERROR",
54 StringUtils.hasText(t.getMessage()) ? t.getMessage() : "IO operation failed.",
55 t);
56 }
57 if (t instanceof io.minio.errors.MinioException) {
58 return mapMinioException((io.minio.errors.MinioException) t);
59 }
60 return new MinioException(
61 500,
62 ERROR_CODE_PREFIX + "UNSPECIFIED",
63 StringUtils.hasText(t.getMessage()) ? t.getMessage() : "Unmapped minio error.",
64 t);
65 }
66
67 private MinioException mapMinioException(io.minio.errors.MinioException e) {
68 int status = 500;
69 String errorCode = ERROR_CODE_PREFIX + "UNSPECIFIED";
70 String message = StringUtils.hasText(e.getMessage())
71 ? e.getMessage()
72 : "Unspecified minio error.";
73
74 if (e instanceof BucketPolicyTooLargeException) {
75 status = 400;
76 errorCode = ERROR_CODE_PREFIX + "BUCKET_POLICY_TOO_LARGE";
77 message = e.toString();
78
79 } else if (e instanceof ErrorResponseException) {
80 ErrorResponseException ere = (ErrorResponseException) e;
81 status = getStatus(ere);
82 errorCode = getErrorCode(ere);
83 message = getMessage(ere);
84
85 } else if (e instanceof InsufficientDataException) {
86 status = 400;
87 errorCode = ERROR_CODE_PREFIX + "INSUFFICIENT_DATA";
88
89 } else if (e instanceof InternalException) {
90 errorCode = ERROR_CODE_PREFIX + "INTERNAL_ERROR";
91
92 } else if (e instanceof InvalidResponseException) {
93 errorCode = ERROR_CODE_PREFIX + "INVALID_RESPONSE";
94
95 } else if (e instanceof ServerException) {
96 errorCode = ERROR_CODE_PREFIX + "SERVER_EXCEPTION";
97
98 } else if (e instanceof XmlParserException) {
99 errorCode = ERROR_CODE_PREFIX + "XML_PARSER_ERROR";
100 }
101 return new MinioException(status, errorCode, message, e);
102 }
103
104 private int getStatus(ErrorResponseException e) {
105 return Optional.of(e)
106 .map(ErrorResponseException::errorResponse)
107 .map(ErrorResponse::code)
108 .map(code -> getStatus(code, e.response()))
109 .orElse(500);
110 }
111
112 private int getStatus(String errorCode, Response response) {
113
114 switch (errorCode) {
115 case "AmbiguousGrantByEmailAddress":
116 case "AuthorizationHeaderMalformed":
117 case "BadDigest":
118 case "CredentialsNotSupported":
119 case "EntityTooSmall":
120 case "EntityTooLarge":
121 case "ExpiredToken":
122 case "IllegalLocationConstraintException":
123 case "IllegalVersioningConfigurationException":
124 case "IncompleteBody":
125 case "IncorrectNumberOfFilesInPostRequest":
126 case "InlineDataTooLarge":
127 case "InvalidAccessPoint":
128 case "InvalidArgument":
129 case "InvalidBucketName":
130 case "InvalidDigest":
131 case "InvalidEncryptionAlgorithmError":
132 case "InvalidLocationConstraint":
133 case "InvalidPart":
134 case "InvalidPartOrder":
135 case "InvalidPolicyDocument":
136 case "InvalidRequest":
137 case "InvalidSOAPRequest":
138 case "InvalidStorageClass":
139 case "InvalidTargetBucketForLogging":
140 case "InvalidToken":
141 case "InvalidURI":
142 case "KeyTooLongError":
143 case "MalformedACLError":
144 case "MalformedPOSTRequest":
145 case "MalformedXML":
146 case "MaxMessageLengthExceeded":
147 case "MaxPostPreDataLengthExceededError":
148 case "MetadataTooLarge":
149 case "MissingRequestBodyError":
150 case "MissingSecurityElement":
151 case "MissingSecurityHeader":
152 case "NoLoggingStatusForKey":
153 case "RequestIsNotMultiPartContent":
154 case "RequestTimeout":
155 case "RequestTorrentOfBucketError":
156 case "ServerSideEncryptionConfigurationNotFoundError":
157 case "TokenRefreshRequired":
158 case "TooManyAccessPoints":
159 case "TooManyBuckets":
160 case "UnexpectedContent":
161 case "UnresolvableGrantByEmailAddress":
162 case "UserKeyMustBeSpecified":
163 case "InvalidTag":
164 case "MalformedPolicy":
165 return 400;
166 case "UnauthorizedAccess":
167 return 401;
168 case "AccessDenied":
169 case "AccountProblem":
170 case "AllAccessDisabled":
171 case "CrossLocationLoggingProhibited":
172 case "InvalidAccessKeyId":
173 case "InvalidObjectState":
174 case "InvalidPayer":
175 case "InvalidSecurity":
176 case "NotSignedUp":
177 case "RequestTimeTooSkewed":
178 case "SignatureDoesNotMatch":
179 return 403;
180 case "ResourceNotFound":
181 case "NoSuchAccessPoint":
182 case "NoSuchBucket":
183 case "NoSuchKey":
184 case "NoSuchObject":
185 case "NoSuchUpload":
186 case "NoSuchVersion":
187 case "NoSuchLifecycleConfiguration":
188 case "NoSuchBucketPolicy":
189 case "NoSuchObjectLockConfiguration":
190 case "NoSuchOutpost":
191 case "NoSuchTagSet":
192 case "UnsupportedOperation":
193 return 404;
194 case "MethodNotAllowed":
195 return 405;
196 case "BucketAlreadyExists":
197 case "BucketAlreadyOwnedByYou":
198 case "BucketNotEmpty":
199 case "InvalidBucketState":
200 case "OperationAborted":
201 case "InvalidOutpostState":
202 return 409;
203 case "MissingContentLength":
204 return 411;
205 case "PreconditionFailed":
206 return 412;
207 case "InvalidRange":
208 return 416;
209 case "InternalError":
210 return 500;
211 case "NotImplemented":
212 return 501;
213 case "ServiceUnavailable":
214 case "SlowDown":
215 return 503;
216 default:
217 return Optional.ofNullable(response)
218 .map(Response::code)
219 .filter(code -> code >= 400)
220 .orElse(400);
221 }
222 }
223
224 private String getErrorCode(ErrorResponseException e) {
225 return Optional.of(e)
226 .map(ErrorResponseException::errorResponse)
227 .map(ErrorResponse::code)
228 .orElse(ERROR_CODE_PREFIX + "UNSPECIFIED_ERROR_RESPONSE");
229 }
230
231 private String getMessage(ErrorResponseException e) {
232 return Optional.of(e)
233 .map(ErrorResponseException::errorResponse)
234 .map(ErrorResponse::message)
235 .orElseGet(() -> StringUtils.hasText(e.getMessage())
236 ? e.getMessage()
237 : "Unspecified error response.");
238 }
239
240 }