mirror of
https://github.com/halo-dev/plugin-s3.git
synced 2025-10-16 23:39:51 +00:00
perf: improve more friendly exception messages (#113)
```release-note 友好地提示异常信息 ``` fixes https://github.com/halo-dev/plugin-s3/issues/105 验证方法: 1. ak/sk乱输,发生接收到403状态码(接收错误状态码) 2. endpoint网址改成不存在的,如.com改成.comaaa(未知主机) 3. endpoint端口改成没监听的(超时)
This commit is contained in:
42
src/main/java/run/halo/s3os/S3ExceptionHandler.java
Normal file
42
src/main/java/run/halo/s3os/S3ExceptionHandler.java
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package run.halo.s3os;
|
||||||
|
|
||||||
|
import lombok.experimental.UtilityClass;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.server.ServerWebInputException;
|
||||||
|
import software.amazon.awssdk.core.exception.SdkException;
|
||||||
|
import software.amazon.awssdk.services.s3.model.S3Exception;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@UtilityClass
|
||||||
|
public class S3ExceptionHandler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map user configuration caused S3 exception to ServerWebInputException
|
||||||
|
* @param throwable Exception
|
||||||
|
* @return ServerWebInputException or original exception
|
||||||
|
*/
|
||||||
|
public static Throwable map(Throwable throwable) {
|
||||||
|
if (throwable instanceof S3Exception s3e) {
|
||||||
|
log.error("S3Exception occurred", s3e);
|
||||||
|
return new ServerWebInputException(String.format(
|
||||||
|
"The object storage service returned an error status code %d. Please check the storage "
|
||||||
|
+ "policy configuration and make sure your account and service are working properly.",
|
||||||
|
s3e.statusCode()));
|
||||||
|
}
|
||||||
|
if (throwable instanceof SdkException sdke && sdke.getMessage() != null
|
||||||
|
&& sdke.getMessage().contains("UnknownHostException")) {
|
||||||
|
log.error("UnknownHostException occurred", sdke);
|
||||||
|
return new ServerWebInputException(
|
||||||
|
"Received an UnknownHostException, please check if the endpoint is entered correctly, "
|
||||||
|
+ "especially for any spaces before or after the endpoint.");
|
||||||
|
}
|
||||||
|
if (throwable instanceof SdkException sdke && sdke.getMessage() != null
|
||||||
|
&& sdke.getMessage().contains("Connect timed out")) {
|
||||||
|
log.error("ConnectTimeoutException occurred", sdke);
|
||||||
|
return new ServerWebInputException(
|
||||||
|
"Received a ConnectTimeoutException, please check if the endpoint is entered correctly, "
|
||||||
|
+ "and make sure your object storage service is working properly.");
|
||||||
|
}
|
||||||
|
return throwable;
|
||||||
|
}
|
||||||
|
}
|
@@ -1,5 +1,13 @@
|
|||||||
package run.halo.s3os;
|
package run.halo.s3os;
|
||||||
|
|
||||||
|
import static run.halo.s3os.S3OsAttachmentHandler.OBJECT_KEY;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
@@ -9,38 +17,18 @@ import org.springframework.security.core.context.ReactiveSecurityContextHolder;
|
|||||||
import org.springframework.security.core.context.SecurityContext;
|
import org.springframework.security.core.context.SecurityContext;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.web.server.ResponseStatusException;
|
import org.springframework.web.server.ResponseStatusException;
|
||||||
import org.springframework.web.util.UriUtils;
|
|
||||||
import reactor.core.publisher.Flux;
|
import reactor.core.publisher.Flux;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
import reactor.core.scheduler.Schedulers;
|
import reactor.core.scheduler.Schedulers;
|
||||||
import run.halo.app.core.extension.attachment.Attachment;
|
import run.halo.app.core.extension.attachment.Attachment;
|
||||||
import run.halo.app.core.extension.attachment.Constant;
|
|
||||||
import run.halo.app.core.extension.attachment.Policy;
|
import run.halo.app.core.extension.attachment.Policy;
|
||||||
import run.halo.app.extension.ConfigMap;
|
import run.halo.app.extension.ConfigMap;
|
||||||
import run.halo.app.extension.Metadata;
|
|
||||||
import run.halo.app.extension.ReactiveExtensionClient;
|
import run.halo.app.extension.ReactiveExtensionClient;
|
||||||
import run.halo.app.infra.utils.JsonUtils;
|
|
||||||
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
|
|
||||||
import software.amazon.awssdk.regions.Region;
|
|
||||||
import software.amazon.awssdk.services.s3.S3Client;
|
import software.amazon.awssdk.services.s3.S3Client;
|
||||||
import software.amazon.awssdk.services.s3.S3Configuration;
|
|
||||||
import software.amazon.awssdk.services.s3.model.HeadObjectRequest;
|
import software.amazon.awssdk.services.s3.model.HeadObjectRequest;
|
||||||
import software.amazon.awssdk.services.s3.model.ListObjectsV2Request;
|
import software.amazon.awssdk.services.s3.model.ListObjectsV2Request;
|
||||||
import software.amazon.awssdk.services.s3.model.S3Object;
|
import software.amazon.awssdk.services.s3.model.S3Object;
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import static run.halo.s3os.S3OsAttachmentHandler.OBJECT_KEY;
|
|
||||||
|
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@@ -103,7 +91,8 @@ public class S3LinkServiceImpl implements S3LinkService {
|
|||||||
listObjectsV2Response.nextContinuationToken(),
|
listObjectsV2Response.nextContinuationToken(),
|
||||||
listObjectsV2Response.isTruncated()));
|
listObjectsV2Response.isTruncated()));
|
||||||
});
|
});
|
||||||
});
|
})
|
||||||
|
.onErrorMap(S3ExceptionHandler::map);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -155,7 +144,8 @@ public class S3LinkServiceImpl implements S3LinkService {
|
|||||||
.getKey() : null, tokenState.currToken,
|
.getKey() : null, tokenState.currToken,
|
||||||
limitedObjects.size() == pageSize);
|
limitedObjects.size() == pageSize);
|
||||||
});
|
});
|
||||||
});
|
})
|
||||||
|
.onErrorMap(S3ExceptionHandler::map);
|
||||||
}
|
}
|
||||||
|
|
||||||
record TokenState(String currToken, String nextToken) {
|
record TokenState(String currToken, String nextToken) {
|
||||||
@@ -200,6 +190,7 @@ public class S3LinkServiceImpl implements S3LinkService {
|
|||||||
.flatMap(client::create)
|
.flatMap(client::create)
|
||||||
.thenReturn(new LinkResult.LinkResultItem(objectKey, true, null));
|
.thenReturn(new LinkResult.LinkResultItem(objectKey, true, null));
|
||||||
}))
|
}))
|
||||||
|
.onErrorMap(S3ExceptionHandler::map)
|
||||||
.onErrorResume(throwable ->
|
.onErrorResume(throwable ->
|
||||||
Mono.just(new LinkResult.LinkResultItem(objectKey, false, throwable.getMessage())));
|
Mono.just(new LinkResult.LinkResultItem(objectKey, false, throwable.getMessage())));
|
||||||
}
|
}
|
||||||
|
@@ -82,7 +82,8 @@ public class S3OsAttachmentHandler implements AttachmentHandler {
|
|||||||
final var properties = getProperties(context.configMap());
|
final var properties = getProperties(context.configMap());
|
||||||
return upload(context, properties)
|
return upload(context, properties)
|
||||||
.subscribeOn(Schedulers.boundedElastic())
|
.subscribeOn(Schedulers.boundedElastic())
|
||||||
.map(objectDetail -> this.buildAttachment(properties, objectDetail));
|
.map(objectDetail -> this.buildAttachment(properties, objectDetail))
|
||||||
|
.onErrorMap(S3ExceptionHandler::map);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,6 +117,7 @@ public class S3OsAttachmentHandler implements AttachmentHandler {
|
|||||||
})
|
})
|
||||||
.thenReturn(context);
|
.thenReturn(context);
|
||||||
})
|
})
|
||||||
|
.onErrorMap(S3ExceptionHandler::map)
|
||||||
.map(DeleteContext::attachment);
|
.map(DeleteContext::attachment);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,7 +154,8 @@ public class S3OsAttachmentHandler implements AttachmentHandler {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
SdkPresigner::close)
|
SdkPresigner::close)
|
||||||
.subscribeOn(Schedulers.boundedElastic());
|
.subscribeOn(Schedulers.boundedElastic())
|
||||||
|
.onErrorMap(S3ExceptionHandler::map);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
package run.halo.s3os;
|
package run.halo.s3os;
|
||||||
|
|
||||||
import java.time.Instant;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
Reference in New Issue
Block a user