почему Firefox не соблюдает кодирование передачи по частям? - PullRequest
3 голосов
/ 11 августа 2011

Я передаю большой документ через контроллер Spring MVC, работающий на Apache Tomcat / 6.0.18

, поскольку он большой и (в конечном итоге) будет генерироваться динамически, я решил использовать chunked Transfer-Encoding.

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.inject.Inject;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.httpclient.ChunkedOutputStream;
import org.apache.commons.net.io.CopyStreamException;
import org.apache.commons.net.io.Util;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class QueryController {  

    @Inject
    QueryService queryService;

    @RequestMapping(value = "/stream")
    public void hellostreamer(HttpServletResponse response) throws CopyStreamException, IOException  {

        response.setHeader("Transfer-Encoding", "chunked");     
        response.setHeader("Content-type", "text/xml");
        InputStream filestream = new FileInputStream("/lotsrecs.xml");      
        ChunkedOutputStream chunkStream = new ChunkedOutputStream(response.getOutputStream());      
        Util.copyStream(filestream,chunkStream);
        chunkStream.close();
        chunkStream.finish();
    }
}

Однако, когда я открываю это в Firefox, я получаю это:

XML Parsing Error: syntax error
Location: http://localhost:8082/streaming-mockup-1.0-SNAPSHOT/stream
Line Number 1, Column 1:

800
^

Вместо того, чтобы читать размеры блоков в виде метаданных о потоке, они считываются как часть потока!

Используя заголовки Live HTTP, я вижу, что заголовок Transfer-Encoding получен:

HTTP/1.1 200 OK

Server: Apache-Coyote/1.1

Transfer-Encoding: chunked
Content-Type: text/xml

Date: Thu, 11 Aug 2011 18:08:07 GMT

Так что я в недоумении, почему размеры чанков не интерпретируются правильно. Если я делаю запрос, используя wget, я также вижу символы размера фрагмента внутри возвращенного документа, так что почему-то они не кодируются правильно. У кого-нибудь есть идея, почему?

Просмотр передачи с помощью wireshark: (обратите внимание, что «800» повторяется во всем потоке) Обратите внимание, что 0x800 = 2048, который является размером фрагмента по умолчанию, используемым классом ChunkedOutputStream.

GET /streaming-mockup-1.0-SNAPSHOT/stream HTTP/1.0    
User-Agent: Wget/1.12 (linux-gnu)    
Accept: */*    
Host: localhost:8082    
Connection: Keep-Alive

HTTP/1.1 200 OK    
Server: Apache-Coyote/1.1    
Transfer-Encoding: chunked    
Content-Type: text/xml    
Date: Thu, 11 Aug 2011 18:47:24 GMT    
Connection: close

800

<records>
  <REC>
    <FUID>412286284WOS1</FUID>
    <UID>WOS:000292284100013</UID>
    <static_data>
      <summary>
        <EWUID uid="WOS:000292284100013" year="2011">

Если я просто копирую в выходной поток напрямую, не создавая ChunkedOutputStream, я вообще не вижу размера чанка:

GET /streaming-mockup-1.0-SNAPSHOT/stream HTTP/1.0
User-Agent: Wget/1.12 (linux-gnu)
Accept: */*
Host: localhost:8082    
Connection: Keep-Alive

HTTP/1.1 200 OK    
Server: Apache-Coyote/1.1    
Transfer-Encoding: chunked    
Content-Type: text/xml    
Date: Thu, 11 Aug 2011 18:51:05 GMT    
Connection: close    

<records>
  <REC>
    <FUID>412286284WOS1</FUID>
    <UID>WOS:000292284100013</UID>
    <static_data>
      <summary>

Так как я узнаю, что это куски? Если бы это было, разве я не увидел бы размеры куска?

1 Ответ

11 голосов
/ 11 августа 2011

Вы уверены, что вам нужно построить ChunkedOutputStream для себя?

Мое понимание (не запутанное практикой) состоит в том, что ServletResponse.getOutputStream() должен обрабатывать порцию для вас, если это уместно (скажем, если клиент не HTTP 1.0 и т. Д.). Если это так, то ответ, который фактически будет отправлен, будет кодироваться по частям внутри по частям, и браузер, конечно, знает только об одном из этих слоев.

Вы пытались запустить сервер где-нибудь через сеть и проверить транзакцию с Wireshark?

Обновление:

GET /streaming-mockup-1.0-SNAPSHOT/stream HTTP/1.0

Клиенты HTTP / 1.0 вообще не обязаны понимать кусочную кодировку (естественно, так как эта кодировка была изобретена только для 1.1).

...