2011-10-21 13 views
5

Temelde benim yanıt başlıkları,Http fragmanlarını/altbilgisini bir java servlet içinden yığınlanmış bir yanıt olarak nasıl gönderirim?

Transferi-encoding = chunked ihtiva

Fragman = I veri yazma bittim kez

[I örneğin "SomeTrailer" demek göndermek istediğiniz bazı römork] Servlet outputstream, ben Römork yazıyor "SomeTrailer: [value]", ama bu httpclient tarafından doğru şekilde ayrıştırılmıyor. httpclient, girdi akışının tamamını (fragman dahil) tek bir yığın olarak kabul eder. Ayrıca, veri çıkışı çıktı akışına yazıldıktan sonra başarıya ulaşmadan bir yanıt başlığında fragman yazmayı da denedim.

yardım edin bu konuda herhangi bir iyi kaynakları bulamadı.

+1

bu gerçekten müşteri tarafından gerekli midir? 'TE' ve' Trailer' çok nadiren kullanılıyor, aslında gerçek dünya kodunda hiç görmedim. Servlet API'sı, yığın yanıtları için yerleşik bir desteğe sahiptir (dahası, yanıtın içerik uzunluğunu ayarlamadığınız zaman bunu varsayılan olarak gönderir). Ancak, yığın tepkili treylerler için destek içermiyor. Alternatif olarak, istenen fragmanın değerini özel bir yanıt başlığı olarak ayarlayabilirsiniz (yalnızca, değer US-ASCII uyumluysa ve belirli bir maksimum uzunluğu geçmiyorsa). – BalusC

+0

@BalusC Kullanım durumum, sunucunun sonsuz bir veri akışı gönderiyor olması ve içerik uzunluğunu bilmemesidir. Sunucu kodu, aynı zamanda, müşterinin verileri doğrulamak için kullanacağı bir fragman olarak gönderebilmesi için, sağlama toplamını hesaplar. –

cevap

3

Bunun için basit bir tek iş parçacıklı web sunucusu yazmayı bitirdim. Çıktı oldukça kolaydı. Sunucu oldukça basit. Kod biraz kaba olsa da, ana fikir orada.

ilk yığın ve bir altlık olarak dosyanın sağlama olarak filecontents gönderir o neyi.

import java.io.BufferedReader; 
import java.io.DataOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import java.net.ServerSocket; 
import java.net.Socket; 

import org.apache.commons.codec.digest.DigestUtils; 
import org.apache.commons.io.IOUtils; 
import org.apache.log4j.Logger; 

public class ChunkedResponseServer implements Runnable { 
    private static final Logger LOGGER = Logger.getLogger(ChunkedResponseServer.class); 

    // Space ' ' 
    static final byte SP = 32; 
    // Tab ' ' 
    static final byte HT = 9; 
    // Carriage return 
    static final byte CR = 13; 
    // Line feed character 
    static final byte LF = 10; 

    final int port; 

    private volatile boolean cancelled = false; 

    public ChunkedResponseServer(int port) { 
    LOGGER.info("Chunked response server running on port " + port); 
    this.port = port; 
    } 

    @Override 
    public void run() { 
    ServerSocket serverSocket = null; 
    try { 
     serverSocket = new ServerSocket(port); 
     while (!cancelled) { 
     final Socket connectionSocket = serverSocket.accept(); 
     handle(connectionSocket); 
     } 
    } catch (final IOException e) { 
     throw new RuntimeException(e); 
    } 
    } 

    public void cancel() { 
    LOGGER.info("Shutting down Chunked response Server"); 
    cancelled = true; 
    } 

    private void handle(Socket socket) throws IOException { 
    BufferedReader input = null; 
    DataOutputStream output = null; 
    try { 
     input = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
     output = new DataOutputStream(socket.getOutputStream()); 

     addHeaders(output); 
     addCRLR(output); 

     final String filename = readFilename(input); 
     final byte[] content = readContent(filename); 
     addContentAsChunk(output, content); 

     final String checksum = DigestUtils.md5Hex(content); 
     addLastChunkAndChecksumFooter(output, checksum); 
     addCRLR(output); 

    } finally { 
     IOUtils.closeQuietly(input); 
     IOUtils.closeQuietly(output); 
    } 
    } 

    private void addLastChunkAndChecksumFooter(DataOutputStream output, String checksum) throws IOException { 
    output.writeBytes("0"); 
    addCRLR(output); 
    output.writeBytes("checksum: " + checksum); 
    addCRLR(output); 
    } 

    private void addContentAsChunk(DataOutputStream output, byte[] content) throws IOException { 
    output.writeBytes(Integer.toHexString(content.length)); 
    addCRLR(output); 
    output.write(content); 
    addCRLR(output); 
    } 

    private void addCRLR(DataOutputStream output) throws IOException { 
    output.writeByte(CR); 
    output.writeByte(LF); 
    } 

    private void addHeaders(DataOutputStream output) throws IOException { 
    output.writeBytes("HTTP/1.1 200 OK"); 
    addCRLR(output); 
    output.writeBytes("Content-type: text/plain"); 
    addCRLR(output); 
    output.writeBytes("Transfer-encoding: chunked"); 
    addCRLR(output); 
    output.writeBytes("Trailer: checksum"); 
    addCRLR(output); 
    } 

    private String readFilename(BufferedReader input) throws IOException { 
    final String initialLine = input.readLine(); 
    final String filePath = initialLine.split(" ")[1]; 
    final String[] components = filePath.split("/"); 
    return components[components.length - 1]; 
    } 

    private byte[] readContent(String filename) throws IOException { 
    final InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream(filename); 
    return IOUtils.toByteArray(in); 
    } 
} 
İlgili konular