Skip to content

Commit 757fcb7

Browse files
author
Stephane Landelle
committed
Turn MultipartRequestEntity into a static MultipartBodyFactory
1 parent 0674fd1 commit 757fcb7

File tree

6 files changed

+40
-104
lines changed

6 files changed

+40
-104
lines changed

api/src/main/java/org/asynchttpclient/multipart/MultipartBody.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public class MultipartBody implements RandomAccessBody {
3737

3838
private final byte[] boundary;
3939
private final long contentLength;
40+
private final String contentType;
4041
private final List<Part> parts;
4142
// FIXME why keep all of them open?
4243
private final List<RandomAccessFile> files = new ArrayList<RandomAccessFile>();
@@ -57,6 +58,7 @@ enum FileLocation {
5758
public MultipartBody(List<Part> parts, String contentType, long contentLength, byte[] boundary) {
5859
this.boundary = boundary;
5960
this.contentLength = contentLength;
61+
this.contentType = contentType;
6062
this.parts = parts;
6163
}
6264

@@ -70,6 +72,10 @@ public long getContentLength() {
7072
return contentLength;
7173
}
7274

75+
public String getContentType() {
76+
return contentType;
77+
}
78+
7379
public long read(ByteBuffer buffer) throws IOException {
7480
try {
7581
int overallLength = 0;

api/src/main/java/org/asynchttpclient/multipart/MultipartRequestEntity.java renamed to api/src/main/java/org/asynchttpclient/multipart/MultipartBodyFactory.java

Lines changed: 23 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,7 @@
2323
import org.asynchttpclient.FluentCaseInsensitiveStringsMap;
2424
import org.asynchttpclient.util.StandardCharsets;
2525

26-
/**
27-
* This class is an adaptation of the Apache HttpClient implementation
28-
*
29-
* @link http://hc.apache.org/httpclient-3.x/
30-
*/
31-
public class MultipartRequestEntity implements RequestEntity {
26+
public final class MultipartBodyFactory {
3227

3328
/**
3429
* The Content-Type for multipart/form-data.
@@ -40,36 +35,23 @@ public class MultipartRequestEntity implements RequestEntity {
4035
*/
4136
private static byte[] MULTIPART_CHARS = "-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".getBytes(StandardCharsets.US_ASCII);
4237

43-
/**
44-
* Generates a random multipart boundary string.
45-
*
46-
* @return
47-
*/
48-
private static byte[] generateMultipartBoundary() {
49-
Random rand = new Random();
50-
byte[] bytes = new byte[rand.nextInt(11) + 30]; // a random size from 30 to 40
51-
for (int i = 0; i < bytes.length; i++) {
52-
bytes[i] = MULTIPART_CHARS[rand.nextInt(MULTIPART_CHARS.length)];
53-
}
54-
return bytes;
38+
private MultipartBodyFactory() {
5539
}
56-
57-
private final byte[] multipartBoundary;
58-
59-
private final String contentType;
60-
61-
private final long contentLength;
62-
40+
6341
/**
6442
* Creates a new multipart entity containing the given parts.
6543
*
6644
* @param parts
6745
* The parts to include.
6846
*/
69-
public MultipartRequestEntity(List<Part> parts, FluentCaseInsensitiveStringsMap requestHeaders) {
47+
public static MultipartBody newMultipartBody(List<Part> parts, FluentCaseInsensitiveStringsMap requestHeaders) {
7048
if (parts == null) {
7149
throw new IllegalArgumentException("parts cannot be null");
7250
}
51+
52+
byte[] multipartBoundary;
53+
String contentType;
54+
7355
String contentTypeHeader = requestHeaders.getFirstValue("Content-Type");
7456
if (isNonEmpty(contentTypeHeader)) {
7557
int boundaryLocation = contentTypeHeader.indexOf("boundary=");
@@ -80,38 +62,31 @@ public MultipartRequestEntity(List<Part> parts, FluentCaseInsensitiveStringsMap
8062
} else {
8163
// generate boundary and append it to existing Content-Type
8264
multipartBoundary = generateMultipartBoundary();
83-
contentType = computeContentType(contentTypeHeader);
65+
contentType = computeContentType(contentTypeHeader, multipartBoundary);
8466
}
8567
} else {
8668
multipartBoundary = generateMultipartBoundary();
87-
contentType = computeContentType(MULTIPART_FORM_CONTENT_TYPE);
69+
contentType = computeContentType(MULTIPART_FORM_CONTENT_TYPE, multipartBoundary);
8870
}
8971

90-
contentLength = Part.getLengthOfParts(parts, multipartBoundary);
72+
long contentLength = Part.getLengthOfParts(parts, multipartBoundary);
73+
74+
return new MultipartBody(parts, contentType, contentLength, multipartBoundary);
9175
}
9276

93-
private String computeContentType(String base) {
77+
private static byte[] generateMultipartBoundary() {
78+
Random rand = new Random();
79+
byte[] bytes = new byte[rand.nextInt(11) + 30]; // a random size from 30 to 40
80+
for (int i = 0; i < bytes.length; i++) {
81+
bytes[i] = MULTIPART_CHARS[rand.nextInt(MULTIPART_CHARS.length)];
82+
}
83+
return bytes;
84+
}
85+
86+
private static String computeContentType(String base, byte[] multipartBoundary) {
9487
StringBuilder buffer = new StringBuilder(base);
9588
if (!base.endsWith(";"))
9689
buffer.append(";");
9790
return buffer.append(" boundary=").append(new String(multipartBoundary, StandardCharsets.US_ASCII)).toString();
9891
}
99-
100-
/**
101-
* Returns the MIME boundary string that is used to demarcate boundaries of this part. The first call to this method will implicitly create a new boundary string. To create a
102-
* boundary string first the HttpMethodParams.MULTIPART_BOUNDARY parameter is considered. Otherwise a random one is generated.
103-
*
104-
* @return The boundary string of this entity in ASCII encoding.
105-
*/
106-
public byte[] getMultipartBoundary() {
107-
return multipartBoundary;
108-
}
109-
110-
public long getContentLength() {
111-
return contentLength;
112-
}
113-
114-
public String getContentType() {
115-
return contentType;
116-
}
11792
}

api/src/main/java/org/asynchttpclient/multipart/RequestEntity.java

Lines changed: 0 additions & 36 deletions
This file was deleted.

api/src/test/java/org/asynchttpclient/multipart/MultipartBodyTest.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,10 @@ private static File getTestfile() {
6464
private static void compareContentLength(final List<Part> parts) {
6565
Assert.assertNotNull(parts);
6666
// get expected values
67-
MultipartRequestEntity mre = new MultipartRequestEntity(parts, new FluentCaseInsensitiveStringsMap());
68-
final long expectedContentLength = mre.getContentLength();
6967

7068
// get real bytes
71-
final Body multipartBody = new MultipartBody(parts, mre.getContentType(), expectedContentLength, mre.getMultipartBoundary());
69+
final Body multipartBody = MultipartBodyFactory.newMultipartBody(parts, new FluentCaseInsensitiveStringsMap());
70+
final long expectedContentLength = multipartBody.getContentLength();
7271
try {
7372
final ByteBuffer buffer = ByteBuffer.allocate(8192);
7473
boolean last = false;

providers/grizzly/src/main/java/org/asynchttpclient/providers/grizzly/bodyhandler/PartsBodyHandler.java

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import org.asynchttpclient.Body;
1717
import org.asynchttpclient.Request;
1818
import org.asynchttpclient.multipart.MultipartBody;
19-
import org.asynchttpclient.multipart.MultipartRequestEntity;
19+
import org.asynchttpclient.multipart.MultipartBodyFactory;
2020
import org.asynchttpclient.multipart.Part;
2121
import org.asynchttpclient.providers.grizzly.FeedableBodyGenerator;
2222
import org.asynchttpclient.providers.grizzly.GrizzlyAsyncHttpProvider;
@@ -46,12 +46,9 @@ public boolean doHandle(final FilterChainContext ctx,
4646
throws IOException {
4747

4848
final List<Part> parts = request.getParts();
49-
final MultipartRequestEntity mre = new MultipartRequestEntity(parts, request.getHeaders());
50-
final long contentLength = mre.getContentLength();
51-
final String contentType = mre.getContentType();
52-
final byte[] multipartBoundary = mre.getMultipartBoundary();
53-
requestPacket.setContentLengthLong(contentLength);
54-
requestPacket.setContentType(contentType);
49+
final MultipartBody multipartBody = MultipartBodyFactory.newMultipartBody(parts, request.getHeaders());
50+
requestPacket.setContentLengthLong(multipartBody.getContentLength());
51+
requestPacket.setContentType(multipartBody.getContentType());
5552
if (GrizzlyAsyncHttpProvider.LOGGER.isDebugEnabled()) {
5653
GrizzlyAsyncHttpProvider.LOGGER.debug(
5754
"REQUEST(modified): contentLength={}, contentType={}",
@@ -64,7 +61,7 @@ public boolean doHandle(final FilterChainContext ctx,
6461
final FeedableBodyGenerator generator = new FeedableBodyGenerator() {
6562
@Override
6663
public Body createBody() throws IOException {
67-
return new MultipartBody(parts, contentType, contentLength, multipartBoundary);
64+
return multipartBody;
6865
}
6966
};
7067
generator.setFeeder(new FeedableBodyGenerator.BaseFeeder(generator) {

providers/netty/src/main/java/org/asynchttpclient/providers/netty/request/body/NettyMultipartBody.java

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,15 @@
1919

2020
import org.asynchttpclient.FluentCaseInsensitiveStringsMap;
2121
import org.asynchttpclient.multipart.MultipartBody;
22-
import org.asynchttpclient.multipart.MultipartRequestEntity;
22+
import org.asynchttpclient.multipart.MultipartBodyFactory;
2323
import org.asynchttpclient.multipart.Part;
2424

2525
public class NettyMultipartBody implements NettyBody {
2626

27-
private final long contentLength;
28-
private final String contentType;
2927
private final MultipartBody multipartBody;
3028

3129
public NettyMultipartBody(List<Part> parts, FluentCaseInsensitiveStringsMap headers) {
32-
MultipartRequestEntity mre = new MultipartRequestEntity(parts, headers);
33-
contentType = mre.getContentType();
34-
contentLength = mre.getContentLength();
35-
multipartBody = new MultipartBody(parts, contentType, contentLength, mre.getMultipartBoundary());
30+
multipartBody = MultipartBodyFactory.newMultipartBody(parts, headers);
3631
}
3732

3833
public MultipartBody getMultipartBody() {
@@ -41,11 +36,11 @@ public MultipartBody getMultipartBody() {
4136

4237
@Override
4338
public long getContentLength() {
44-
return contentLength;
39+
return multipartBody.getContentLength();
4540
}
4641

4742
@Override
4843
public String getContentType() {
49-
return contentType;
44+
return multipartBody.getContentType();
5045
}
5146
}

0 commit comments

Comments
 (0)