annotate src/goodjava/webserver/ChunkedOutputStream.java @ 2010:f45ed55f5c11 default tip

fix chunked encoding
author Franklin Schmidt <fschmidt@gmail.com>
date Tue, 02 Sep 2025 06:00:41 -0600
parents bba3e529e346
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2008
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
1 package goodjava.webserver;
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
2
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
3 import java.io.ByteArrayOutputStream;
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
4 import java.io.InputStream;
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
5 import java.io.IOException;
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
6
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
7
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
8 public class ChunkedOutputStream extends ByteArrayOutputStream {
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
9 private static final byte[] end = "0\r\n\r\n".getBytes();
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
10 private static final int OPEN = 1;
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
11 private static final int CLOSING = 2;
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
12 private static final int CLOSED = 3;
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
13
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
14 private final Response response;
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
15 private int status = OPEN;
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
16 private int i = 0;
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
17
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
18 public ChunkedOutputStream(Response response) {
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
19 if(response==null) throw new NullPointerException();
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
20 this.response = response;
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
21 response.headers.put("Transfer-Encoding","chunked");
2010
f45ed55f5c11 fix chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents: 2008
diff changeset
22 response.headers.put("X-Accel-Buffering","no");
2008
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
23 response.body = new ChunkedInputStream();
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
24 }
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
25
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
26 @Override public synchronized void close() {
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
27 if( status == OPEN ) {
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
28 status = CLOSING;
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
29 notifyAll();
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
30 }
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
31 }
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
32
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
33 @Override public synchronized void write(int b) {
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
34 super.write(b);
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
35 notifyAll();
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
36 }
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
37
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
38 @Override public synchronized void write(byte b[], int off, int len) {
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
39 super.write(b,off,len);
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
40 notifyAll();
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
41 }
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
42
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
43 @Override public synchronized void reset() {
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
44 super.reset();
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
45 i = 0;
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
46 }
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
47
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
48 private class ChunkedInputStream extends InputStream {
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
49
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
50 @Override public int read() {
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
51 throw new UnsupportedOperationException();
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
52 }
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
53
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
54 @Override public int read(byte[] b,int off,int len) throws IOException {
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
55 synchronized(ChunkedOutputStream.this) {
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
56 if( i == count ) {
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
57 if( status == CLOSED )
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
58 return -1;
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
59 if( status == CLOSING ) {
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
60 System.arraycopy(end,0,b,off,end.length);
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
61 status = CLOSED;
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
62 return end.length;
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
63 }
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
64 try {
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
65 ChunkedOutputStream.this.wait();
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
66 } catch(InterruptedException e) {
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
67 throw new RuntimeException(e);
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
68 }
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
69 return read(b,off,len);
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
70 }
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
71 int offOld = off;
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
72 int left = count - i;
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
73 int extra = Integer.toHexString(left).length() + 4;
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
74 int n = Math.min( len - extra, left );
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
75 byte[] hex = Integer.toHexString(n).getBytes();
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
76 System.arraycopy( hex, 0, b, off, hex.length );
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
77 off += hex.length;
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
78 b[off++] = '\r'; b[off++] = '\n';
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
79 System.arraycopy(buf,i,b,off,n);
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
80 off += n;
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
81 b[off++] = '\r'; b[off++] = '\n';
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
82 i += n;
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
83 if( i == count )
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
84 ChunkedOutputStream.this.reset();
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
85 return off - offOld;
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
86 }
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
87 }
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
88 }
bba3e529e346 chunked encoding
Franklin Schmidt <fschmidt@gmail.com>
parents:
diff changeset
89 }