如何在 CXF Out Fault Interceptor 中将 HTTP STATUS 代码设置为 500 以外的值?

How to set the HTTP STATUS code to other than 500 in CXF Out Fault Interceptor?

我正在编写 CXF OutFaultInterceptor 以在 Mule ESB 版本 3.8.1 中实现 SOAP Web 服务时抛出自定义 SOAP 错误消息

问题是对于每个 SOAP 错误,我从服务器获取 HTTP STATUS CODE 500。我想根据错误类型更改状态代码,例如 400 错误请求。

如何操作?

我尝试将 MESSAGE.RESPONSE_CODE 设置为 400,将 PHASE 设置为 PRE_STREAM 和 MARSHAL。

但是不行。下面是示例代码:

public class SampleCxfFaultInterceptor extends AbstractSoapInterceptor {

    private static final Logger LOGGER = LoggerFactory.getLogger(EservicesCxfFaultInterceptor.class);

    public SampleCxfFaultInterceptor() {
        super(Phase.PRE_STREAM);
    }

    public void handleMessage(SoapMessage soapMessage) throws Fault {

        Fault fault = (Fault) soapMessage.getContent(Exception.class);

        if (fault.getCause() instanceof org.mule.api.transformer.TransformerMessagingException) {

                LOGGER.error("INTERNAL ERROR OCCURED WHILE PROCESSING REQUEST);
                soapMessage.remove(Message.RESPONSE_CODE);
                soapMessage.put(Message.RESPONSE_CODE,new Integer(400));
                Element detail = fault.getOrCreateDetail();
                Element errorDetail = detail.getOwnerDocument().createElement("errorDetail");
                Element errorCode = errorDetail.getOwnerDocument().createElement("errorCode");
                Element message = errorDetail.getOwnerDocument().createElement("message");
                errorCode.setTextContent("500");
                message.setTextContent("INTERNAL_ERROR");
                errorDetail.appendChild(errorCode);
                errorDetail.appendChild(message);
                detail.appendChild(errorDetail);                

        }

    }

    private Throwable getOriginalCause(Throwable t) {
        if (t instanceof ComponentException && t.getCause() != null) {
            return t.getCause();
        } else {
            return t;
        }
    }

预期结果是将 HTTP 状态代码获取为 400。

但我得到这样的结果:HTTP/1.1 500

确保您也覆盖了 handleFault 方法并直接在 HttpServletResponse 对象上设置状态:

import javax.servlet.http.HttpServletResponse;

import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.binding.soap.interceptor.AbstractSoapInterceptor;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.message.Exchange;
import org.apache.cxf.message.Message;
import org.apache.cxf.message.MessageUtils;
import org.apache.cxf.phase.Phase;
import org.apache.cxf.transport.http.AbstractHTTPDestination;

public class SampleCxfFaultInterceptor extends AbstractSoapInterceptor
{
    ...

    public SampleCxfFaultInterceptor() {
        super(Phase.PRE_STREAM);
    }

    private void setHttpResponseStatus(final SoapMessage message, final int status)
    {
        // skip if inbound
        if (!MessageUtils.isOutbound(message))
        {
            return;
        }

        // outbound
        final Exchange exchange = message.getExchange();
        final Message outMessage = Optional.ofNullable(exchange.getOutMessage()).orElse(exchange.getOutFaultMessage());
        final HttpServletResponse httpResponse = (HttpServletResponse) outMessage.get(AbstractHTTPDestination.HTTP_RESPONSE);
        if (httpResponse != null)
        {
            httpResponse.setStatus(status);
        }
        /*
         * else this is likely SOAP over some non-HTTP transport protocol
         */
        /*
         * Prevent any further processing by other interceptors
         */
        message.getInterceptorChain().abort();

    }

    @Override
    public void handleMessage(final SoapMessage message) throws Fault
    {
        // example setting HTTP status to 400
        setHttpResponseStatus(message, 400);
    }

    @Override
    public void handleFault(final SoapMessage message)
    {
        // example setting HTTP status to 400
        setHttpResponseStatus(message, 400);
    }
}

已通过 CXF 3.x API 验证。

我用

设置状态

httpResponse.setStatus(status);

没用。

我设法发现 AbstractHTTPDestination class 的 getReponseCodeFromMessage 方法在发送过程结束时触发,其中状态由 Message.RESPONSE_CODE header 出消息。

我所做的是在 out 拦截器中设置这个 header,如下所示:

import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.interceptor.Fault;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.springframework.stereotype.Component;
import org.apache.cxf.message.Message;

import static org.apache.cxf.phase.Phase.POST_PROTOCOL;

@Component
public class TestOutIInterceptor extends AbstractPhaseInterceptor<SoapMessage> {
    
        public TestOutIInterceptor() {
            super(POST_PROTOCOL);
        }
    
        @Override
        public void handleMessage(SoapMessage message) throws Fault {
            int customHttpHeaderValue = 400;
            message.getExchange().getOutMessage().put(Message.RESPONSE_CODE, customHttpHeaderValue);
        }
    }
}

HTTP 状态正在设置为 400