Mar*_*234 9 java java-http-client
Java 11java.net.http.HttpClient似乎不检查 HTTP 状态代码,重定向除外(如果启用)。wiki和 Java API 文档中找到的所有示例始终假设 HTTP 请求是成功的,即它们似乎从不检查响应的状态代码。
这很可能永远不是所需的行为,因为来自 HTTP 500(服务器错误)响应的错误页面可能具有不同的格式或没有格式,因此应用程序无法处理。
应该在哪里检查 HTTP 状态代码?
的文档HttpResponse.BodyHandler包含以下示例片段:
BodyHandler<Path> bodyHandler = (rspInfo) -> rspInfo.statusCode() == 200
? BodySubscribers.ofFile(Paths.get("/tmp/f"))
: BodySubscribers.replacing(Paths.get("/NULL"));
Run Code Online (Sandbox Code Playgroud)
但是,您必须检查两次状态代码,一次在BodyHandler上面显示的情况下,一次在处理响应时(因为尝试从中读取正文"/NULL"会失败)。
对我来说,仅执行 HTTP 状态代码检查似乎是最合理的BodyHandler,例如:
BodyHandler<Path> bodyHandler = (rspInfo) -> {
if (rspInfo.statusCode() == 200) {
return BodySubscribers.ofFile(Paths.get("/tmp/f"));
} else {
throw new RuntimeException("Request failed");
}
};
Run Code Online (Sandbox Code Playgroud)
但是,BodyHandler文档没有提及是否允许抛出异常,或者HttpClient在这种情况下会如何表现。
让我感到惊讶的是,JDK 似乎没有提供开箱即用的处理不成功 HTTP 响应的功能,还是我忽略了某些东西?
尝试HttpClient很好地捕获用户代码引发的异常 - 但这不是处理非 200 状态的推荐方法。您将依赖于未指定的行为(尽管它可能会按照您的预期进行)。
如果您想在状态为 != 200 的情况下返回异常,那么我的建议是编写一个正文订阅者:
另一方面 - 如果您想要在 status != 200 的情况下使用不同的结果类型,您可以编写一个BodyHandler返回元组(响应,错误)的元组,其中响应是一种类型,错误是另一种类型。像这样的东西:
record Response<R,T>(R response, T error) {}
static class ErrorBodyHandler<R,T> implements BodyHandler<Response<R,T>> {
final BodyHandler<R> responseHandler;
final BodyHandler<T> errorHandler;
public ErrorBodyHandler(BodyHandler<R> responseHandler, BodyHandler<T> errorHandler) {
this.responseHandler = responseHandler;
this.errorHandler = errorHandler;
}
@Override
public BodySubscriber<Response<R, T>> apply(ResponseInfo responseInfo) {
if (responseInfo.statusCode() == 200) {
return BodySubscribers.mapping(responseHandler.apply(responseInfo),
(r) -> new Response<>(r, null));
} else {
return BodySubscribers.mapping(errorHandler.apply(responseInfo),
(t) -> new Response<>(null, t));
}
}
}
public static void main(String[] args) throws Exception {
var client = HttpClient.newHttpClient();
var handler = new ErrorBodyHandler<>(BodyHandlers.ofFileDownload(Path.of(".")),
BodyHandlers.ofString());
var request = HttpRequest
.newBuilder(URI.create("http://host:port/"))
.build();
var httpResponse =
client.send(request, handler);
if (httpResponse.statusCode() == 200) {
Path path = httpResponse.body().response();
} else {
String error = httpResponse.body().error();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5485 次 |
| 最近记录: |