Web services 如何在CXF响应中添加用户HTTP头?

Web services 如何在CXF响应中添加用户HTTP头?,web-services,cxf,Web Services,Cxf,由于某些原因,CXF响应中没有“内容长度”HTTP头。 我决定实现拦截器,但不幸的是,在发送的数据中并没有添加头(使用Wireshark截获)。我可以设置断点,我可以看到拦截器被调用。怎么了 /** * Adds Content-Length header for the outcoming messages */ public class AddContentLengthInterceptor extends AbstractLoggingInterceptor { privat

由于某些原因,CXF响应中没有“内容长度”HTTP头。 我决定实现拦截器,但不幸的是,在发送的数据中并没有添加头(使用Wireshark截获)。我可以设置断点,我可以看到拦截器被调用。怎么了

/**
 * Adds Content-Length header for the outcoming messages
 */
public class AddContentLengthInterceptor extends AbstractLoggingInterceptor {

    private static final String CONTENT_LENGTH_ADDED = AddContentLengthInterceptor.class.getName() + ".log-setup";

    public AddContentLengthInterceptor(String phase) {
        super(phase);
        addBefore(StaxOutInterceptor.class.getName());
    }
    public AddContentLengthInterceptor() {
        this(Phase.PRE_PROTOCOL); // before streaming
    }

    @Override
    protected Logger getLogger() {
        return null;
    }

    @Override
    public void handleMessage(Message message) throws Fault {
        final OutputStream os = message.getContent(OutputStream.class);
        final Writer iowriter = message.getContent(Writer.class);
        if (os == null && iowriter == null) {
            return;
        }

        // ignore double processing of the message
        boolean hasAddedHeader = message.containsKey(CONTENT_LENGTH_ADDED);
        if (!hasAddedHeader) {
            message.put(CONTENT_LENGTH_ADDED, Boolean.TRUE);
            if (os != null) {
                // Write the output while caching it for adding header later
                final CacheAndWriteOutputStream newOut = new CacheAndWriteOutputStream(os);
                message.setContent(OutputStream.class, newOut);
                newOut.registerCallback(new LoggingCallback(message, os));
            }
        }
    }

    class LoggingCallback implements CachedOutputStreamCallback {

        private final Message message;
        private final OutputStream origStream;

        public LoggingCallback(final Message msg, final OutputStream os) {
            this.message = msg;
            this.origStream = os;
        }

        public void onFlush(CachedOutputStream cos) {

        }

        public void onClose(CachedOutputStream cos) {
            long contentLength = cos.size();

            Map<String, List<String>> headers = (Map<String, List<String>>) message.get(Message.PROTOCOL_HEADERS);
            if (headers == null)
                headers = new HashMap<String, List<String>>();
            headers.put("Content-Length", Arrays.asList(String.valueOf(contentLength)));
            message.put(Message.PROTOCOL_HEADERS, headers);

            try {
                // empty out the cache
                cos.lockOutputStream();
                cos.resetOut(null, false);
            } catch (Exception ex) {
                //ignore
            }
            message.setContent(OutputStream.class, origStream);
        }
    }
}

我认为您正在使用传输编码作为分块。这将导致没有内容长度头,因为它在中以这种方式定义

消息不能同时包含内容长度标头字段和 非身份传输编码。如果消息中确实包含 非身份传输编码,必须忽略内容长度

我不太确定,但是,要么是cxf删除了您的头,因为它是不允许的,要么是它设置了,但子层删除了它。据我所知,cxf使用HttpUrlConnection来传输您的消息。该层在正常情况下设置内容长度标题。但由于您使用的是分块传输,该层可能会覆盖它

为了修复它,您必须更改传输编码。而且,由于CXF本身设置了内容长度头,您不再需要编写拦截器


顺便说一句,如果你使用自定义标题,你会发现你的拦截器工作起来就像一个符咒。

看来你是对的!如何以编程方式(没有spring,没有xmls)关闭服务器端的分块?我需要在标题中包含“内容长度”,因为一些古老的Web服务客户端需要它。
    mediaService = new MediaService(ip, rtspPort, streamUri);
    ProviderImpl provider = new ProviderImpl();
    mediaEndpoint = (EndpointImpl) provider.createEndpoint(null, mediaService);
    String mediaServiceURL = MessageFormat.format("http://{0}:{1}/onvif/media_service", ip, String.valueOf(port));
    mediaEndpoint.publish(mediaServiceURL);

    // add "Content-Length" header
    mediaEndpoint.getServer().getEndpoint().getOutInterceptors().add(contentLengthInterceptor);