Mercurial Hosting > luan
diff src/goodjava/webserver/ChunkedOutputStream.java @ 2008:bba3e529e346 default tip
chunked encoding
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Wed, 27 Aug 2025 01:14:17 -0600 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/goodjava/webserver/ChunkedOutputStream.java Wed Aug 27 01:14:17 2025 -0600 @@ -0,0 +1,88 @@ +package goodjava.webserver; + +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.IOException; + + +public class ChunkedOutputStream extends ByteArrayOutputStream { + private static final byte[] end = "0\r\n\r\n".getBytes(); + private static final int OPEN = 1; + private static final int CLOSING = 2; + private static final int CLOSED = 3; + + private final Response response; + private int status = OPEN; + private int i = 0; + + public ChunkedOutputStream(Response response) { + if(response==null) throw new NullPointerException(); + this.response = response; + response.headers.put("Transfer-Encoding","chunked"); + response.body = new ChunkedInputStream(); + } + + @Override public synchronized void close() { + if( status == OPEN ) { + status = CLOSING; + notifyAll(); + } + } + + @Override public synchronized void write(int b) { + super.write(b); + notifyAll(); + } + + @Override public synchronized void write(byte b[], int off, int len) { + super.write(b,off,len); + notifyAll(); + } + + @Override public synchronized void reset() { + super.reset(); + i = 0; + } + + private class ChunkedInputStream extends InputStream { + + @Override public int read() { + throw new UnsupportedOperationException(); + } + + @Override public int read(byte[] b,int off,int len) throws IOException { + synchronized(ChunkedOutputStream.this) { + if( i == count ) { + if( status == CLOSED ) + return -1; + if( status == CLOSING ) { + System.arraycopy(end,0,b,off,end.length); + status = CLOSED; + return end.length; + } + try { + ChunkedOutputStream.this.wait(); + } catch(InterruptedException e) { + throw new RuntimeException(e); + } + return read(b,off,len); + } + int offOld = off; + int left = count - i; + int extra = Integer.toHexString(left).length() + 4; + int n = Math.min( len - extra, left ); + byte[] hex = Integer.toHexString(n).getBytes(); + System.arraycopy( hex, 0, b, off, hex.length ); + off += hex.length; + b[off++] = '\r'; b[off++] = '\n'; + System.arraycopy(buf,i,b,off,n); + off += n; + b[off++] = '\r'; b[off++] = '\n'; + i += n; + if( i == count ) + ChunkedOutputStream.this.reset(); + return off - offOld; + } + } + } +}