Web services 如何在CXF响应中添加用户HTTP头?
由于某些原因,CXF响应中没有“内容长度”HTTP头。 我决定实现拦截器,但不幸的是,在发送的数据中并没有添加头(使用Wireshark截获)。我可以设置断点,我可以看到拦截器被调用。怎么了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
/**
* 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);