2015-07-09 5 views
1

По какой-то причине HTTP-заголовки Content-Length в CXF-ответе отсутствуют. Я решил реализовать перехватчик, который делает это, но, к сожалению, в отправленных данных нет добавленного заголовка (перехватывается с использованием Wireshark). Я могу установить точку останова, и я вижу, что перехватчик вызывается. Что не так?Как добавить пользовательские заголовки HTTP в ответ CXF?

/** 
* 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); 

ответ

1

Я думаю, что вы используете Transfer-Encoding, как фрагментированный. Это приводит к отсутствию заголовка длины контента, поскольку он определен таким образом в RFC.

Сообщения НЕ ДОЛЖНЫ включать как поле заголовка Content-Length, так и кодирование передачи неидентификации . Если сообщение содержит не-идентификационное кодирование передачи, длина контента ДОЛЖНА быть проигнорирована.

Я не совсем уверен, но либо cxf удаляет ваш заголовок, поскольку он не разрешен, либо он устанавливает, но суб-слои удаляют его. Насколько я знаю, cxf использует HttpUrlConnection для передачи вашего сообщения. И этот уровень устанавливает заголовок Content-length в обычных случаях. Но поскольку вы используете передачу с чередованием, этот слой может переопределить его.

Чтобы исправить это, вы должны изменить свое кодирование передачи. И поскольку CXF сам устанавливает заголовок длины контента, вам больше не нужно писать свой Interceptor.

Кстати, если вы используете пользовательский заголовок, вы поймете, что ваш перехватчик работает как шарм.

+0

Кажется, вы правы! Как я могу отключить chunking на серверной стороне программно (нет весны, нет xmls)? Мне нужно иметь «Content-Length» в заголовках, как это требует какой-то античный клиент webservice. – 4ntoine

Смежные вопросы