Skip to content

Commit ae9ed29

Browse files
authored
Merge pull request quarkusio#52773 from tomsontom/52767-multipart-bug
Handle empty multipart content
2 parents 96c1720 + 080f6a9 commit ae9ed29

File tree

2 files changed

+82
-0
lines changed

2 files changed

+82
-0
lines changed

independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/multipart/MultipartParser.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ private void preamble(final ByteBuffer buffer) {
143143
} else if (subState == -1) {
144144
if (b == CR) {
145145
subState = -2;
146+
} else if (b == DASH) {
147+
subState = -3;
146148
}
147149
} else if (subState == -2) {
148150
if (b == LF) {
@@ -153,6 +155,13 @@ private void preamble(final ByteBuffer buffer) {
153155
} else {
154156
subState = -1;
155157
}
158+
} else if (subState == -3) {
159+
if (b == DASH) {
160+
state = -1; // we are done
161+
return;
162+
} else {
163+
subState = -1;
164+
}
156165
}
157166
}
158167
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package org.jboss.resteasy.reactive.server.core.multipart;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertTrue;
5+
6+
import java.io.IOException;
7+
import java.nio.ByteBuffer;
8+
import java.nio.charset.StandardCharsets;
9+
import java.util.ArrayList;
10+
11+
import org.jboss.resteasy.reactive.common.util.CaseInsensitiveMap;
12+
import org.jboss.resteasy.reactive.server.core.multipart.MultipartParser.PartHandler;
13+
import org.junit.jupiter.api.Test;
14+
15+
public class MultipartParserTest {
16+
@Test
17+
public void testEmpty() throws IOException {
18+
var boundary = "----geckoformboundary781efa46e46556855951be27ee89788e";
19+
var content = "\r\n------geckoformboundary781efa46e46556855951be27ee89788e--\r\n";
20+
var handler = new MultipartParser.PartHandler() {
21+
public void beginPart(final CaseInsensitiveMap<String> headers) {
22+
}
23+
24+
public void data(final ByteBuffer buffer) throws IOException {
25+
}
26+
27+
public void endPart() {
28+
}
29+
};
30+
var parser = MultipartParser.beginParse(handler, boundary.getBytes(StandardCharsets.US_ASCII), "UTF-8");
31+
parser.parse(ByteBuffer.wrap(content.getBytes(StandardCharsets.UTF_8)));
32+
assertTrue(parser.isComplete());
33+
}
34+
35+
@Test
36+
public void testSimple() throws IOException {
37+
var boundary = "----geckoformboundary5ced44e8f9bd18901d8eff2729601699";
38+
var content = "\r\n------geckoformboundary5ced44e8f9bd18901d8eff2729601699\r\n"
39+
+ "Content-Disposition: form-data; name=\"param-a\"\r\n"
40+
+ "\r\n"
41+
+ "Sample A\r\n"
42+
+ "------geckoformboundary5ced44e8f9bd18901d8eff2729601699\r\n"
43+
+ "Content-Disposition: form-data; name=\"param-b\"\r\n"
44+
+ "\r\n"
45+
+ "Sample B\r\n"
46+
+ "------geckoformboundary5ced44e8f9bd18901d8eff2729601699--\r\n";
47+
var allHeaders = new ArrayList<CaseInsensitiveMap<String>>();
48+
var allData = new ArrayList<String>();
49+
var handler = new PartHandler() {
50+
public void beginPart(final CaseInsensitiveMap<String> headers) {
51+
allHeaders.add(headers);
52+
}
53+
54+
public void data(final ByteBuffer buffer) throws IOException {
55+
allData.add(StandardCharsets.UTF_8.decode(buffer).toString());
56+
}
57+
58+
public void endPart() {
59+
}
60+
};
61+
var parser = MultipartParser.beginParse(handler, boundary.getBytes(StandardCharsets.US_ASCII), "UTF-8");
62+
parser.parse(ByteBuffer.wrap(content.getBytes(StandardCharsets.UTF_8)));
63+
assertTrue(parser.isComplete());
64+
assertTrue(allHeaders.size() == 2);
65+
assertTrue(allData.size() == 2);
66+
67+
assertEquals(allHeaders.get(0).get("Content-Disposition").get(0), "form-data; name=\"param-a\"");
68+
assertEquals(allHeaders.get(1).get("Content-Disposition").get(0), "form-data; name=\"param-b\"");
69+
70+
assertEquals(allData.get(0), "Sample A");
71+
assertEquals(allData.get(1), "Sample B");
72+
}
73+
}

0 commit comments

Comments
 (0)