![](/img/trans.png)
[英]Spring WebFlux WebClient - How to resolve 400 Bad Request
[英]Helidon Webclient Handle 400 Bad Request
我是 Helidon 框架的新手,开始使用带有 JDK11 的 Helidon 2 来实现我们的微服务。 根据要求,我们需要调用外部 HTTP/HTTPS 端点,为此开始从以下资源探索 helidon webclient。 https://helidon.io/docs/v2/#/se/webclient/01_introduction
https://medium.com/helidon/helidon-web-client-72e22f5d509a它适用于成功场景,但是对于错误用例(例如 400.Bad Request),我们希望捕获外部抛出的错误消息API,但没有得到任何方便的方法,并且总是最终得到堆栈跟踪
Caused by: io.helidon.webclient.WebClientException: Request failed with code 400
at io.helidon.webclient.WebClientRequestBuilderImpl.getContentFromClientResponse(WebClientRequestBuilderImpl.java:615)
at io.helidon.common.reactive.MultiMapperPublisher$MapperSubscriber.onNext(MultiMapperPublisher.java:73)
at io.helidon.common.reactive.DeferredScalarSubscription.complete(DeferredScalarSubscription.java:91)
at io.helidon.common.reactive.MultiFromCompletionStage$CompletionStageSubscription.accept(MultiFromCompletionStage.java:72)
at io.helidon.common.reactive.MultiFromCompletionStage$CompletionStageSubscription.accept(MultiFromCompletionStage.java:52)
at io.helidon.common.reactive.MultiFromCompletionStage$AtomicBiConsumer.accept(MultiFromCompletionStage.java:95)
at io.helidon.common.reactive.MultiFromCompletionStage$AtomicBiConsumer.accept(MultiFromCompletionStage.java:88)
at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:859)
at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:837)
at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:506)
at java.base/java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:2073)
at io.helidon.webclient.NettyClientHandler.lambda$channelRead0$8(NettyClientHandler.java:200)
at java.base/java.util.concurrent.CompletableFuture.uniRunNow(CompletableFuture.java:815)
at java.base/java.util.concurrent.CompletableFuture.uniRunStage(CompletableFuture.java:799)
at java.base/java.util.concurrent.CompletableFuture.thenRun(CompletableFuture.java:2121)
at io.helidon.webclient.NettyClientHandler.lambda$channelRead0$9(NettyClientHandler.java:193)
at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:859)
at java.base/java.util.concurrent.CompletableFuture.uniWhenCompleteStage(CompletableFuture.java:883)
at java.base/java.util.concurrent.CompletableFuture.whenComplete(CompletableFuture.java:2251)
at java.base/java.util.concurrent.CompletableFuture.whenComplete(CompletableFuture.java:143)
at io.helidon.webclient.NettyClientHandler.channelRead0(NettyClientHandler.java:186)
at io.helidon.webclient.NettyClientHandler.channelRead0(NettyClientHandler.java:61)
at io.netty.channel.SimpleChannelInboundHandler.channelRead(SimpleChannelInboundHandler.java:99)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.handler.codec.MessageToMessageDecoder.channelRead(MessageToMessageDecoder.java:103)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.CombinedChannelDuplexHandler$DelegatingChannelHandlerContext.fireChannelRead(CombinedChannelDuplexHandler.java:436)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:324)
at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:311)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:432)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276)
at io.netty.channel.CombinedChannelDuplexHandler.channelRead(CombinedChannelDuplexHandler.java:251)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.handler.logging.LoggingHandler.channelRead(LoggingHandler.java:271)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1504)
at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1253)
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1300)
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:508)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:447)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:166)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:719)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
... 1 more
关于调试 此外,这是我看到的实现
private MessageBodyReadableContent getContentFromClientResponse(WebClientResponse response) {
if (response.status().code() >= Status.MOVED_PERMANENTLY_301.code()) {
throw new WebClientException("Request failed with code " + response.status().code());
} else {
return response.content();
}
}
所以它显然会抛出 301 以上的任何内容,因此无法获得响应内容。 外部端点抛出带有 400 Bad request 的消息,我们希望使用 Helidon webclient 捕获此消息。
{
"errorCode": "FSS-177",
"errorDescription": "FileSize is too minimum for Multipart upload",
"errorParameters": []
}
如果我遗漏任何东西,任何人都可以在这里提供帮助。
使用 WebClient 获取响应实体有两种方法:
方法 1 - 直接获取实体
client.get()
.uri("http://localhost:8080/greet")
.request(String.class)
.forSingle(System.out::println);
这种方法直接读取实体,但由于无法表示失败,如果响应代码高于 400,我们将抛出异常,让您知道出现问题。 如果你需要失败的实体,你应该使用
方法 2 - 获得响应
client.get()
.uri("http://localhost:8080/greet")
.request()
.forSingle(response -> {
System.out.println(response.status());
response.content()
.as(String.class)
.forSingle(System.out::println);
});
这种方法首先给你一个响应,它让你可以访问状态、标题和实体。 然后你可以读取实体来处理它,即使状态在错误范围内
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.