繁体   English   中英

Helidon Web 客户端处理 400 错误请求

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM