【问题标题】:How to get the HTTP response body in CXF when WebService returns code 403?WebService返回代码403时如何获取CXF中的HTTP响应体?
【发布时间】:2019-06-28 20:41:35
【问题描述】:

我正在尝试使用 Apache 的 CXF 库为 WebService 开发客户端应用程序。在这个特定的服务器实现中,当请求中缺少某些数据(例如某人的 ID 号)时,它会返回 HTTP 代码 403(禁止),但响应正文包含应用程序特定的错误详细信息作为 Soap Fault。

例如,这是我使用 SoapUI 收集的响应:


正如您在突出显示的文本中看到的那样,此请求中有一个响应正文。


现在我需要从我的应用程序中检索响应正文。我尝试在SEND_ENDINGPOST_PROTOCOL 等不同阶段使用拦截器,但似乎无法在handleMessage() 方法的Message 参数中找到它。

我错过了什么?

这是我得到的异常和堆栈跟踪:

org.apache.cxf.interceptor.Fault: Could not send Message.
    at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:67)
    at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
    at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:531)
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:440)
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:355)
    at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:313)
    at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
    at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:140)
    at com.sun.proxy.$Proxy36.arquivo(Unknown Source)
    at br.com.dgsistemas.TesteWS.main(TesteWS.java:133)
Caused by: org.apache.cxf.transport.http.HTTPException: HTTP response '403: Forbidden' when communicating with https://www.wsrestrito.caixa.gov.br/siies/WsSolicitacao
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.doProcessResponseCode(HTTPConduit.java:1620)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1627)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1572)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1373)
    at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
    at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:673)
    at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:63)
    ... 9 more

谢谢!

【问题讨论】:

    标签: java soap cxf


    【解决方案1】:

    您是否尝试过为此使用 LoggingInInterceptor (See description),或者扩展它并覆盖 handleMessage 方法。可用于监控所有 SOAP IN 消息

    Example for usage can be found here

    【讨论】:

      【解决方案2】:

      您应该能够扩展 AbstractSoapInterceptor,在 Phase.MARSHAL 阶段注册它,并在您的 handleMessage 覆盖中提取消息。

      使用 SoapMessage.getExchange().getInMessage() 或 .getInFaultMessage() 从 SOAP 响应中提取消息。

      【讨论】:

      • 这里什么都没有。我将 Message 类型转换为 SoapMessage,然后尝试调用您建议的方法,但它们为空。可能是因为消息被分块了?
      【解决方案3】:

      你有两个独立的问题。

      首先,您必须删除分块消息。 http://cxf.apache.org/docs/client-http-transport-including-ssl-support.html#ClientHTTPTransport(includingSSLsupport)-ANoteAboutChunking

      在调用端点之前,您必须禁用分块通信:

         HTTPConduit conduit = (HTTPConduit) client.getConduit();
         HTTPClientPolicy policy = new HTTPClientPolicy();
      
      
         // Chunking is by default enabled in CXF webservices so we have to disable it.     
         policy.setAllowChunking(false);
         conduit.setClient(policy); // update HTTP client's conduit
      

      其次,我认为您必须删除 BOM。您可以在以下维基百科注释中看到它是什么: https://en.wikipedia.org/wiki/Byte_order_mark

      如果您想删除 BOM,请检查: Byte order mark screws up file reading in Java

      注意1:分块消息取决于服务器设置,服务器可能 忽略您的请求设置。

      注意 2:如果您编写一个 流拦截器。分块消息没有Content-Length 标头,虽然实际长度小于预期,但您必须等待来自服务器的更多消息。

      【讨论】:

      • 我可以从拦截器中删除 BOM 吗?
      • 您应该编写一个输入流包装器。查看此示例如何从消息创建输入流:github.com/apache/cxf/blob/master/core/src/main/java/org/apache/…
      • 不幸的是message.getContent(XMLStreamReader.class) 返回null,所以拦截器被跳过了...
      • 覆盖此验证,message.getContent(InputStream.class) 也是 null
      猜你喜欢
      • 1970-01-01
      • 2019-06-05
      • 1970-01-01
      • 1970-01-01
      • 2019-04-20
      • 2018-10-19
      • 2011-04-21
      • 2020-02-17
      • 2013-03-29
      相关资源
      最近更新 更多