当WebService返回代码403时,如何在CXF中获取HTTP响应正文?

8
我正在尝试使用Apache的CXF库开发一个WebService的客户端应用程序。在这个特定的服务器实现中,当请求中缺少一些数据(例如某人的ID号码)时,它会返回HTTP代码403(禁止),但响应体作为Soap Fault包含了应用程序特定的错误详情。
例如,这是我使用SoapUI收集到的响应: Response in the SoapUI 如您在高亮文本中看到的,这个请求有一个响应体。
现在我需要从我的应用程序中检索响应体。我尝试在不同阶段使用拦截器,例如SEND_ENDINGPOST_PROTOCOL,但似乎无法在给定的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

谢谢!

3个回答

0

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

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


我将Message类型转换为SoapMessage,然后尝试调用您建议的方法,但它们为空。也许是因为消息被分块了? - Leandragem

0

你有两个独立的问题。

首先,你需要移除分块消息。 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:如果编写流拦截器,则可以同时处理BOM和分块消息。分块消息没有Content-Length头,而实际长度小于预期时,您必须等待来自服务器的更多消息。


我可以在拦截器中删除BOM吗? - Leandragem
你应该编写一个输入流包装器。查看此示例以了解如何从消息创建输入流:https://github.com/apache/cxf/blob/master/core/src/main/java/org/apache/cxf/interceptor/StaxInInterceptor.java - rockfarkas
不幸的是,message.getContent(XMLStreamReader.class) 返回 null,因此拦截器被跳过了... - Leandragem
覆盖此验证,message.getContent(InputStream.class) 也是 null - Leandragem

-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接