由于某种原因,没有'内容长度' 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);
}
}
}
现在创建了服务器端端点:
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);
答案 0 :(得分:1)
我认为您正在使用Transfer-Encoding作为分块。这导致没有内容长度标头,因为它在RFC中以这种方式定义。
消息不得包含Content-Length头字段和a 非身份转移编码。如果消息确实包含a 非身份转移编码,必须忽略内容长度。
我不完全确定,但是cxf会删除你的标题,因为它是不允许的,或者它设置但子图层会将其删除。据我所知,cxf使用HttpUrlConnection来传输你的消息。并且该层在正常情况下设置Content-length头。但由于您正在使用分块传输,该层可能会覆盖它。
要修复它,您必须更改Transfer-Encoding。由于CXF本身设置了内容长度标题,因此您不再需要编写拦截器。
顺便说一句,如果你使用自定义标题,你会发现你的拦截器就像一个魅力。