comparison 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
comparison
equal deleted inserted replaced
2007:408f7dd7e503 2008:bba3e529e346
1 package goodjava.webserver;
2
3 import java.io.ByteArrayOutputStream;
4 import java.io.InputStream;
5 import java.io.IOException;
6
7
8 public class ChunkedOutputStream extends ByteArrayOutputStream {
9 private static final byte[] end = "0\r\n\r\n".getBytes();
10 private static final int OPEN = 1;
11 private static final int CLOSING = 2;
12 private static final int CLOSED = 3;
13
14 private final Response response;
15 private int status = OPEN;
16 private int i = 0;
17
18 public ChunkedOutputStream(Response response) {
19 if(response==null) throw new NullPointerException();
20 this.response = response;
21 response.headers.put("Transfer-Encoding","chunked");
22 response.body = new ChunkedInputStream();
23 }
24
25 @Override public synchronized void close() {
26 if( status == OPEN ) {
27 status = CLOSING;
28 notifyAll();
29 }
30 }
31
32 @Override public synchronized void write(int b) {
33 super.write(b);
34 notifyAll();
35 }
36
37 @Override public synchronized void write(byte b[], int off, int len) {
38 super.write(b,off,len);
39 notifyAll();
40 }
41
42 @Override public synchronized void reset() {
43 super.reset();
44 i = 0;
45 }
46
47 private class ChunkedInputStream extends InputStream {
48
49 @Override public int read() {
50 throw new UnsupportedOperationException();
51 }
52
53 @Override public int read(byte[] b,int off,int len) throws IOException {
54 synchronized(ChunkedOutputStream.this) {
55 if( i == count ) {
56 if( status == CLOSED )
57 return -1;
58 if( status == CLOSING ) {
59 System.arraycopy(end,0,b,off,end.length);
60 status = CLOSED;
61 return end.length;
62 }
63 try {
64 ChunkedOutputStream.this.wait();
65 } catch(InterruptedException e) {
66 throw new RuntimeException(e);
67 }
68 return read(b,off,len);
69 }
70 int offOld = off;
71 int left = count - i;
72 int extra = Integer.toHexString(left).length() + 4;
73 int n = Math.min( len - extra, left );
74 byte[] hex = Integer.toHexString(n).getBytes();
75 System.arraycopy( hex, 0, b, off, hex.length );
76 off += hex.length;
77 b[off++] = '\r'; b[off++] = '\n';
78 System.arraycopy(buf,i,b,off,n);
79 off += n;
80 b[off++] = '\r'; b[off++] = '\n';
81 i += n;
82 if( i == count )
83 ChunkedOutputStream.this.reset();
84 return off - offOld;
85 }
86 }
87 }
88 }