Skip to content

Commit 58dd868

Browse files
committed
nit
1 parent 3191499 commit 58dd868

File tree

6 files changed

+111
-111
lines changed

6 files changed

+111
-111
lines changed

client/src/main/java/org/asynchttpclient/RequestBuilderBase.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242

4343
import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_TYPE;
4444
import static java.nio.charset.StandardCharsets.UTF_8;
45-
import static org.asynchttpclient.util.HttpUtils.extractCharset;
45+
import static org.asynchttpclient.util.HttpUtils.extractContentTypeCharsetAttribute;
4646
import static org.asynchttpclient.util.HttpUtils.validateSupportedScheme;
4747
import static org.asynchttpclient.util.MiscUtils.isNonEmpty;
4848
import static org.asynchttpclient.util.MiscUtils.withDefault;
@@ -588,7 +588,7 @@ private RequestBuilderBase<?> executeSignatureCalculator() {
588588

589589
private void updateCharset() {
590590
String contentTypeHeader = headers.get(CONTENT_TYPE);
591-
Charset contentTypeCharset = extractCharset(contentTypeHeader);
591+
Charset contentTypeCharset = extractContentTypeCharsetAttribute(contentTypeHeader);
592592
charset = withDefault(contentTypeCharset, withDefault(charset, UTF_8));
593593
if (contentTypeHeader != null && contentTypeHeader.regionMatches(true, 0, "text/", 0, 5) && contentTypeCharset == null) {
594594
// add explicit charset to content-type header

client/src/main/java/org/asynchttpclient/netty/NettyResponse.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434

3535
import static io.netty.handler.codec.http.HttpHeaderNames.*;
3636
import static java.nio.charset.StandardCharsets.UTF_8;
37-
import static org.asynchttpclient.util.HttpUtils.extractCharset;
37+
import static org.asynchttpclient.util.HttpUtils.extractContentTypeCharsetAttribute;
3838
import static org.asynchttpclient.util.MiscUtils.isNonEmpty;
3939
import static org.asynchttpclient.util.MiscUtils.withDefault;
4040

@@ -187,7 +187,7 @@ public ByteBuffer getResponseBodyAsByteBuffer() {
187187

188188
@Override
189189
public String getResponseBody() {
190-
return getResponseBody(withDefault(extractCharset(getContentType()), UTF_8));
190+
return getResponseBody(withDefault(extractContentTypeCharsetAttribute(getContentType()), UTF_8));
191191
}
192192

193193
@Override

client/src/main/java/org/asynchttpclient/netty/request/NettyRequestFactory.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,8 @@ public NettyRequest newNettyRequest(Request request, boolean performConnectReque
198198
}
199199

200200
if (!headers.contains(HOST)) {
201-
headers.set(HOST, hostHeader(request, uri));
201+
String virtualHost = request.getVirtualHost();
202+
headers.set(HOST, virtualHost != null ? virtualHost : hostHeader(uri));
202203
}
203204

204205
// don't override authorization but append

client/src/main/java/org/asynchttpclient/request/body/multipart/MultipartUtils.java

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,18 @@
1616
import io.netty.handler.codec.http.HttpHeaderValues;
1717
import io.netty.handler.codec.http.HttpHeaders;
1818
import org.asynchttpclient.request.body.multipart.part.*;
19-
import org.asynchttpclient.util.StringBuilderPool;
2019

2120
import java.util.ArrayList;
2221
import java.util.List;
23-
import java.util.concurrent.ThreadLocalRandom;
2422

2523
import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_TYPE;
2624
import static java.nio.charset.StandardCharsets.US_ASCII;
2725
import static org.asynchttpclient.util.Assertions.assertNotNull;
26+
import static org.asynchttpclient.util.HttpUtils.*;
2827
import static org.asynchttpclient.util.MiscUtils.isNonEmpty;
2928

3029
public class MultipartUtils {
3130

32-
/**
33-
* The pool of ASCII chars to be used for generating a multipart boundary.
34-
*/
35-
private static byte[] MULTIPART_CHARS = "-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".getBytes(US_ASCII);
36-
3731
/**
3832
* Creates a new multipart entity containing the given parts.
3933
*
@@ -56,12 +50,12 @@ public static MultipartBody newMultipartBody(List<Part> parts, HttpHeaders reque
5650
boundary = (contentTypeHeader.substring(boundaryLocation + "boundary=".length()).trim()).getBytes(US_ASCII);
5751
} else {
5852
// generate boundary and append it to existing Content-Type
59-
boundary = generateBoundary();
60-
contentType = computeContentType(contentTypeHeader, boundary);
53+
boundary = computeMultipartBoundary();
54+
contentType = patchContentTypeWithBoundaryAttribute(contentTypeHeader, boundary);
6155
}
6256
} else {
63-
boundary = generateBoundary();
64-
contentType = computeContentType(HttpHeaderValues.MULTIPART_FORM_DATA, boundary);
57+
boundary = computeMultipartBoundary();
58+
contentType = patchContentTypeWithBoundaryAttribute(HttpHeaderValues.MULTIPART_FORM_DATA, boundary);
6559
}
6660

6761
List<MultipartPart<? extends Part>> multipartParts = generateMultipartParts(parts, boundary);
@@ -90,21 +84,4 @@ public static List<MultipartPart<? extends Part>> generateMultipartParts(List<Pa
9084

9185
return multipartParts;
9286
}
93-
94-
// a random size from 30 to 40
95-
private static byte[] generateBoundary() {
96-
ThreadLocalRandom random = ThreadLocalRandom.current();
97-
byte[] bytes = new byte[random.nextInt(11) + 30];
98-
for (int i = 0; i < bytes.length; i++) {
99-
bytes[i] = MULTIPART_CHARS[random.nextInt(MULTIPART_CHARS.length)];
100-
}
101-
return bytes;
102-
}
103-
104-
private static String computeContentType(CharSequence base, byte[] boundary) {
105-
StringBuilder buffer = StringBuilderPool.DEFAULT.stringBuilder().append(base);
106-
if (base.length() != 0 && base.charAt(base.length() - 1) != ';')
107-
buffer.append(';');
108-
return buffer.append(" boundary=").append(new String(boundary, US_ASCII)).toString();
109-
}
11087
}

client/src/main/java/org/asynchttpclient/util/HttpUtils.java

Lines changed: 92 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import java.nio.ByteBuffer;
2323
import java.nio.charset.Charset;
2424
import java.util.List;
25+
import java.util.concurrent.ThreadLocalRandom;
2526

2627
import static java.nio.charset.StandardCharsets.*;
2728
import static org.asynchttpclient.util.MiscUtils.isNonEmpty;
@@ -33,6 +34,97 @@ public class HttpUtils {
3334

3435
private static final String CONTENT_TYPE_CHARSET_ATTRIBUTE = "charset=";
3536

37+
private static final String CONTENT_TYPE_BOUNDARY_ATTRIBUTE = "boundary=";
38+
39+
private HttpUtils() {
40+
}
41+
42+
public static String hostHeader(Uri uri) {
43+
String host = uri.getHost();
44+
int port = uri.getPort();
45+
return port == -1 || port == uri.getSchemeDefaultPort() ? host : host + ":" + port;
46+
}
47+
48+
public static String originHeader(Uri uri) {
49+
StringBuilder sb = StringBuilderPool.DEFAULT.stringBuilder();
50+
sb.append(uri.isSecured() ? "https://" : "http://").append(uri.getHost());
51+
if (uri.getExplicitPort() != uri.getSchemeDefaultPort()) {
52+
sb.append(':').append(uri.getPort());
53+
}
54+
return sb.toString();
55+
}
56+
57+
public static Charset extractContentTypeCharsetAttribute(String contentType) {
58+
String charsetName = extractContentTypeAttribute(contentType, CONTENT_TYPE_CHARSET_ATTRIBUTE);
59+
return charsetName != null ? Charset.forName(charsetName) : null;
60+
}
61+
62+
public static String extractContentTypeBoundaryAttribute(String contentType) {
63+
return extractContentTypeAttribute(contentType, CONTENT_TYPE_BOUNDARY_ATTRIBUTE);
64+
}
65+
66+
private static String extractContentTypeAttribute(String contentType, String attribute) {
67+
if (contentType == null) {
68+
return null;
69+
}
70+
71+
for (int i = 0; i < contentType.length(); i++) {
72+
if (contentType.regionMatches(true, i, attribute, 0,
73+
attribute.length())) {
74+
int start = i + attribute.length();
75+
76+
// trim left
77+
while (start < contentType.length()) {
78+
char c = contentType.charAt(start);
79+
if (c == ' ' || c == '\'' || c == '"') {
80+
start++;
81+
} else {
82+
break;
83+
}
84+
}
85+
if (start == contentType.length()) {
86+
break;
87+
}
88+
89+
// trim right
90+
int end = start + 1;
91+
while (end < contentType.length()) {
92+
char c = contentType.charAt(end);
93+
if (c == ' ' || c == '\'' || c == '"' || c == ';') {
94+
break;
95+
} else {
96+
end++;
97+
}
98+
}
99+
100+
return contentType.substring(start, end);
101+
}
102+
}
103+
104+
return null;
105+
}
106+
107+
// The pool of ASCII chars to be used for generating a multipart boundary.
108+
private static byte[] MULTIPART_CHARS = "-_1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".getBytes(US_ASCII);
109+
110+
// a random size from 30 to 40
111+
public static byte[] computeMultipartBoundary() {
112+
ThreadLocalRandom random = ThreadLocalRandom.current();
113+
byte[] bytes = new byte[random.nextInt(11) + 30];
114+
for (int i = 0; i < bytes.length; i++) {
115+
bytes[i] = MULTIPART_CHARS[random.nextInt(MULTIPART_CHARS.length)];
116+
}
117+
return bytes;
118+
}
119+
120+
public static String patchContentTypeWithBoundaryAttribute(CharSequence base, byte[] boundary) {
121+
StringBuilder sb = StringBuilderPool.DEFAULT.stringBuilder().append(base);
122+
if (base.length() != 0 && base.charAt(base.length() - 1) != ';') {
123+
sb.append(';');
124+
}
125+
return sb.append(' ').append(CONTENT_TYPE_BOUNDARY_ATTRIBUTE).append(new String(boundary, US_ASCII)).toString();
126+
}
127+
36128
public static void validateSupportedScheme(Uri uri) {
37129
final String scheme = uri.getScheme();
38130
if (scheme == null || !scheme.equalsIgnoreCase("http") && !scheme.equalsIgnoreCase("https")
@@ -64,46 +156,6 @@ public static String getNonEmptyPath(Uri uri) {
64156
return isNonEmpty(uri.getPath()) ? uri.getPath() : "/";
65157
}
66158

67-
public static Charset extractCharset(String contentType) {
68-
if (contentType != null) {
69-
for (int i = 0; i < contentType.length(); i++) {
70-
if (contentType.regionMatches(true, i, CONTENT_TYPE_CHARSET_ATTRIBUTE, 0,
71-
CONTENT_TYPE_CHARSET_ATTRIBUTE.length())) {
72-
int start = i + CONTENT_TYPE_CHARSET_ATTRIBUTE.length();
73-
74-
// trim left
75-
while (start < contentType.length()) {
76-
char c = contentType.charAt(start);
77-
if (c == ' ' || c == '\'' || c == '"') {
78-
start++;
79-
} else {
80-
break;
81-
}
82-
}
83-
if (start == contentType.length()) {
84-
break;
85-
}
86-
87-
// trim right
88-
int end = start + 1;
89-
while (end < contentType.length()) {
90-
char c = contentType.charAt(end);
91-
if (c == ' ' || c == '\'' || c == '"' || c == ';') {
92-
break;
93-
} else {
94-
end++;
95-
}
96-
}
97-
98-
String charsetName = contentType.substring(start, end);
99-
return Charset.forName(charsetName);
100-
}
101-
}
102-
}
103-
104-
return null;
105-
}
106-
107159
public static boolean followRedirect(AsyncHttpClientConfig config, Request request) {
108160
return request.getFollowRedirect() != null ? request.getFollowRedirect() : config.isFollowRedirect();
109161
}
@@ -142,24 +194,4 @@ private static void encodeAndAppendFormField(StringBuilder sb, String field, Cha
142194
}
143195
}
144196
}
145-
146-
public static String hostHeader(Request request, Uri uri) {
147-
String virtualHost = request.getVirtualHost();
148-
if (virtualHost != null)
149-
return virtualHost;
150-
else {
151-
String host = uri.getHost();
152-
int port = uri.getPort();
153-
return port == -1 || port == uri.getSchemeDefaultPort() ? host : host + ":" + port;
154-
}
155-
}
156-
157-
public static String originHeader(Uri uri) {
158-
StringBuilder sb = StringBuilderPool.DEFAULT.stringBuilder();
159-
sb.append(uri.isSecured() ? "https://" : "http://").append(uri.getHost());
160-
if (uri.getExplicitPort() != uri.getSchemeDefaultPort()) {
161-
sb.append(':').append(uri.getPort());
162-
}
163-
return sb.toString();
164-
}
165197
}

client/src/test/java/org/asynchttpclient/util/HttpUtilsTest.java

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525

2626
import java.net.URLEncoder;
2727
import java.nio.ByteBuffer;
28-
import java.nio.charset.CharacterCodingException;
2928
import java.nio.charset.Charset;
3029
import java.util.ArrayList;
3130
import java.util.List;
@@ -36,7 +35,7 @@
3635

3736
public class HttpUtilsTest {
3837

39-
private static String toUsAsciiString(ByteBuffer buf) throws CharacterCodingException {
38+
private static String toUsAsciiString(ByteBuffer buf) {
4039
ByteBuf bb = Unpooled.wrappedBuffer(buf);
4140
try {
4241
return ByteBufUtils.byteBuf2String(US_ASCII, bb);
@@ -110,50 +109,41 @@ public void testIsSameBaseUrlReturnsTrueWhenOneUriHasDefaultPort() {
110109

111110
@Test
112111
public void testExtractCharsetWithoutQuotes() {
113-
Charset charset = HttpUtils.extractCharset("text/html; charset=iso-8859-1");
112+
Charset charset = HttpUtils.extractContentTypeCharsetAttribute("text/html; charset=iso-8859-1");
114113
assertEquals(charset, ISO_8859_1);
115114
}
116115

117116
@Test
118117
public void testExtractCharsetWithSingleQuotes() {
119-
Charset charset = HttpUtils.extractCharset("text/html; charset='iso-8859-1'");
118+
Charset charset = HttpUtils.extractContentTypeCharsetAttribute("text/html; charset='iso-8859-1'");
120119
assertEquals(charset, ISO_8859_1);
121120
}
122121

123122
@Test
124123
public void testExtractCharsetWithDoubleQuotes() {
125-
Charset charset = HttpUtils.extractCharset("text/html; charset=\"iso-8859-1\"");
124+
Charset charset = HttpUtils.extractContentTypeCharsetAttribute("text/html; charset=\"iso-8859-1\"");
126125
assertEquals(charset, ISO_8859_1);
127126
}
128127

129128
@Test
130129
public void testExtractCharsetWithDoubleQuotesAndSpaces() {
131-
Charset charset = HttpUtils.extractCharset("text/html; charset= \"iso-8859-1\" ");
130+
Charset charset = HttpUtils.extractContentTypeCharsetAttribute("text/html; charset= \"iso-8859-1\" ");
132131
assertEquals(charset, ISO_8859_1);
133132
}
134133

135134
@Test
136135
public void testExtractCharsetFallsBackToUtf8() {
137-
Charset charset = HttpUtils.extractCharset(APPLICATION_JSON.toString());
136+
Charset charset = HttpUtils.extractContentTypeCharsetAttribute(APPLICATION_JSON.toString());
138137
assertNull(charset);
139138
}
140139

141140
@Test
142-
public void testGetHostHeaderNoVirtualHost() {
143-
Request request = Dsl.get("http://stackoverflow.com/questions/1057564/pretty-git-branch-graphs").build();
141+
public void testGetHostHeader() {
144142
Uri uri = Uri.create("http://stackoverflow.com/questions/1057564/pretty-git-branch-graphs");
145-
String hostHeader = HttpUtils.hostHeader(request, uri);
143+
String hostHeader = HttpUtils.hostHeader(uri);
146144
assertEquals(hostHeader, "stackoverflow.com", "Incorrect hostHeader returned");
147145
}
148146

149-
@Test
150-
public void testGetHostHeaderHasVirtualHost() {
151-
Request request = Dsl.get("http://stackoverflow.com/questions/1057564").setVirtualHost("example.com").build();
152-
Uri uri = Uri.create("http://stackoverflow.com/questions/1057564/pretty-git-branch-graphs");
153-
String hostHeader = HttpUtils.hostHeader(request, uri);
154-
assertEquals(hostHeader, "example.com", "Incorrect hostHeader returned");
155-
}
156-
157147
@Test
158148
public void testDefaultFollowRedirect() {
159149
Request request = Dsl.get("http://stackoverflow.com/questions/1057564").setVirtualHost("example.com").build();

0 commit comments

Comments
 (0)