@@ -44,6 +44,7 @@ public void chunkExtensions() throws Exception {
44
44
// ;foo=;bar=baz Two extensions, one value, one equals
45
45
// ;foo=bar;bar=baz Two extensions, two values
46
46
// ; No extension, only a separator. Not sure if this is valid, but we should be able to ignore it.
47
+ // 0;foo=bar;bar Extensions on the final 0 chunk
47
48
withBody (
48
49
"""
49
50
3;foo=bar\r
@@ -68,10 +69,11 @@ public void chunkExtensions() throws Exception {
68
69
sion\r
69
70
2;\r
70
71
s!\r
71
- 0\r
72
+ 0;foo=bar;bar \r
72
73
\r
73
74
""" )
74
- .assertResult ("Hi mom! Look no extensions!" );
75
+ .assertResult ("Hi mom! Look no extensions!" )
76
+ .assertLeftOverBytes (0 );
75
77
}
76
78
77
79
@ Test
@@ -87,6 +89,7 @@ public void multipleChunks() throws Exception {
87
89
\r
88
90
"""
89
91
).assertResult ("123456789012345678901234567890123456789012345678901234567890" )
92
+ .assertLeftOverBytes (0 )
90
93
.assertNextRead (ChunkedInputStream ::read , -1 );
91
94
}
92
95
@@ -101,7 +104,8 @@ public void ok() throws Exception {
101
104
0\r
102
105
\r
103
106
"""
104
- ).assertResult ("Hi mom!" );
107
+ ).assertResult ("Hi mom!" )
108
+ .assertLeftOverBytes (0 );
105
109
}
106
110
107
111
@ Test
@@ -149,6 +153,30 @@ public void partialHeader() throws IOException {
149
153
assertEquals (inputStream .read (buf ), -1 );
150
154
}
151
155
156
+ @ Test
157
+ public void trailers () throws Exception {
158
+ // It isn't clear if any HTTP server actually users or supports trailers. But, the spec indicates we should at least ignore them.
159
+ // - https://www.rfc-editor.org/rfc/rfc2616.html#section-3.6.1
160
+ withBody (
161
+ """
162
+ 30\r
163
+ There is no fate but what we make for ourselves.\r
164
+ 12\r
165
+
166
+ - Sarah Connor
167
+ \r
168
+ 0\r
169
+ Judgement-Day: August 29, 1997 2:14 AM EDT\r
170
+ \r
171
+ """ )
172
+ .assertResult ("""
173
+ There is no fate but what we make for ourselves.
174
+ - Sarah Connor
175
+ """ )
176
+ // If we correctly read to the end of the InputStream we should not have any bytes left over in the PushbackInputStream
177
+ .assertLeftOverBytes (0 );
178
+ }
179
+
152
180
private Builder withBody (String body ) {
153
181
return new Builder ().withBody (body );
154
182
}
@@ -157,20 +185,44 @@ private PushbackInputStream withParts(String... parts) {
157
185
return new PushbackInputStream (new PieceMealInputStream (parts ));
158
186
}
159
187
188
+ @ SuppressWarnings ("UnusedReturnValue" )
160
189
private static class Builder {
161
190
public String body ;
162
191
163
192
public ChunkedInputStream chunkedInputStream ;
164
193
194
+ public PushbackInputStream pushbackInputStream ;
195
+
196
+ /**
197
+ * Used to ensure the parser worked correctly and was able to read to the end of the encoded body.
198
+ *
199
+ * @param expected the number of expected bytes that were over-read.
200
+ * @return this.
201
+ */
202
+ public Builder assertLeftOverBytes (int expected ) throws IOException {
203
+ int actual = pushbackInputStream .getAvailableBufferedBytesRemaining ();
204
+ if (actual != expected ) {
205
+ if (actual > 0 ) {
206
+ byte [] leftOverBytes = new byte [actual ];
207
+ int leftOverRead = pushbackInputStream .read (leftOverBytes );
208
+ // No reason to think these would not be equal... but they better be.
209
+ assertEquals (leftOverBytes .length , leftOverRead );
210
+ assertEquals (actual , expected , "\n Here is what was left over in the buffer\n [" + new String (leftOverBytes ) + "]" );
211
+ }
212
+ }
213
+
214
+ return this ;
215
+ }
216
+
165
217
public Builder assertNextRead (ThrowingFunction <ChunkedInputStream , Integer > function , int expected ) throws Exception {
166
218
var result = function .apply (chunkedInputStream );
167
219
assertEquals (result , expected );
168
220
return this ;
169
221
}
170
222
171
223
public Builder assertResult (String expected ) throws IOException {
172
- var bis = new PushbackInputStream (new ByteArrayInputStream (body .getBytes (StandardCharsets .UTF_8 )));
173
- chunkedInputStream = new ChunkedInputStream (bis , 2048 );
224
+ pushbackInputStream = new PushbackInputStream (new ByteArrayInputStream (body .getBytes (StandardCharsets .UTF_8 )));
225
+ chunkedInputStream = new ChunkedInputStream (pushbackInputStream , 2048 );
174
226
175
227
String actual = new String (chunkedInputStream .readAllBytes (), StandardCharsets .UTF_8 );
176
228
assertEquals (actual , expected );
0 commit comments