Skip to content

Commit

Permalink
Request and Response encoding should use a Charset and not a String, c…
Browse files Browse the repository at this point in the history
…lose #817
  • Loading branch information
Stephane Landelle committed Feb 11, 2015
1 parent 3c851b2 commit d35ba38
Show file tree
Hide file tree
Showing 15 changed files with 58 additions and 50 deletions.
15 changes: 8 additions & 7 deletions api/src/main/java/org/asynchttpclient/Request.java
Expand Up @@ -16,16 +16,17 @@
*/
package org.asynchttpclient;

import org.asynchttpclient.cookie.Cookie;
import org.asynchttpclient.multipart.Part;
import org.asynchttpclient.uri.Uri;

import java.io.File;
import java.io.InputStream;
import java.net.InetAddress;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.List;

import org.asynchttpclient.cookie.Cookie;
import org.asynchttpclient.multipart.Part;
import org.asynchttpclient.uri.Uri;

/**
* The Request class can be used to construct HTTP request:
* <blockquote><pre>
Expand Down Expand Up @@ -183,11 +184,11 @@ public interface Request {
long getRangeOffset();

/**
* Return the encoding value used when encoding the request's body.
* Return the charset value used when decoding the request's body.
*
* @return the encoding value used when encoding the request's body.
* @return the charset value used when decoding the request's body.
*/
String getBodyEncoding();
Charset getBodyCharset();

ConnectionPoolPartitioning getConnectionPoolPartitioning();
}
27 changes: 14 additions & 13 deletions api/src/main/java/org/asynchttpclient/RequestBuilderBase.java
Expand Up @@ -17,23 +17,24 @@

import static org.asynchttpclient.util.MiscUtils.isNonEmpty;

import org.asynchttpclient.cookie.Cookie;
import org.asynchttpclient.multipart.Part;
import org.asynchttpclient.uri.Uri;
import org.asynchttpclient.util.AsyncHttpProviderUtils;
import org.asynchttpclient.util.QueryComputer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.InputStream;
import java.net.InetAddress;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.asynchttpclient.cookie.Cookie;
import org.asynchttpclient.multipart.Part;
import org.asynchttpclient.uri.Uri;
import org.asynchttpclient.util.AsyncHttpProviderUtils;
import org.asynchttpclient.util.QueryComputer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Builder for {@link Request}
*
Expand Down Expand Up @@ -66,7 +67,7 @@ private static final class RequestImpl implements Request {
private Boolean followRedirect;
private int requestTimeout;
private long rangeOffset;
public String charset;
public Charset charset;
private ConnectionPoolPartitioning connectionPoolPartitioning = ConnectionPoolPartitioning.PerHostConnectionPoolPartitioning.INSTANCE;
private List<Param> queryParams;

Expand Down Expand Up @@ -96,7 +97,7 @@ public RequestImpl(Request prototype) {
this.followRedirect = prototype.getFollowRedirect();
this.requestTimeout = prototype.getRequestTimeout();
this.rangeOffset = prototype.getRangeOffset();
this.charset = prototype.getBodyEncoding();
this.charset = prototype.getBodyCharset();
this.connectionPoolPartitioning = prototype.getConnectionPoolPartitioning();
}
}
Expand Down Expand Up @@ -212,7 +213,7 @@ public long getRangeOffset() {
}

@Override
public String getBodyEncoding() {
public Charset getBodyCharset() {
return charset;
}

Expand Down Expand Up @@ -552,7 +553,7 @@ public T setMethod(String method) {
return derived.cast(this);
}

public T setBodyEncoding(String charset) {
public T setBodyCharset(Charset charset) {
request.charset = charset;
return derived.cast(this);
}
Expand Down Expand Up @@ -584,7 +585,7 @@ private void computeRequestCharset() {
try {
final String contentType = request.headers.getFirstValue("Content-Type");
if (contentType != null) {
final String charset = AsyncHttpProviderUtils.parseCharset(contentType);
final Charset charset = AsyncHttpProviderUtils.parseCharset(contentType);
if (charset != null) {
// ensure that if charset is provided with the Content-Type header,
// we propagate that down to the charset of the Request object
Expand Down
5 changes: 3 additions & 2 deletions api/src/main/java/org/asynchttpclient/Response.java
Expand Up @@ -22,6 +22,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;

Expand Down Expand Up @@ -78,7 +79,7 @@ public interface Response {
* @return The response body
* @throws java.io.IOException
*/
String getResponseBodyExcerpt(int maxLength, String charset) throws IOException;
String getResponseBodyExcerpt(int maxLength, Charset charset) throws IOException;

/**
* Return the entire response body as a String.
Expand All @@ -88,7 +89,7 @@ public interface Response {
* @return the entire response body as a String.
* @throws IOException
*/
String getResponseBody(String charset) throws IOException;
String getResponseBody(Charset charset) throws IOException;

/**
* Returns the first maxLength bytes of the response body as a string. Note that this does not check whether the content type is actually a textual one, but it will use the
Expand Down
Expand Up @@ -12,36 +12,37 @@
*/
package org.asynchttpclient.consumers;

import static java.nio.charset.StandardCharsets.*;

import org.asynchttpclient.BodyConsumer;
import static java.nio.charset.StandardCharsets.UTF_8;

import java.io.Closeable;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;

import org.asynchttpclient.BodyConsumer;

/**
* An {@link Appendable} customer for {@link ByteBuffer}
*/
public class AppendableBodyConsumer implements BodyConsumer {

private final Appendable appendable;
private final String encoding;
private final Charset charset;

public AppendableBodyConsumer(Appendable appendable, String encoding) {
public AppendableBodyConsumer(Appendable appendable, Charset charset) {
this.appendable = appendable;
this.encoding = encoding;
this.charset = charset;
}

public AppendableBodyConsumer(Appendable appendable) {
this.appendable = appendable;
this.encoding = UTF_8.name();
this.charset = UTF_8;
}

@Override
public void consume(ByteBuffer byteBuffer) throws IOException {
appendable
.append(new String(byteBuffer.array(), byteBuffer.arrayOffset() + byteBuffer.position(), byteBuffer.remaining(), encoding));
.append(new String(byteBuffer.array(), byteBuffer.arrayOffset() + byteBuffer.position(), byteBuffer.remaining(), charset));
}

@Override
Expand Down
Expand Up @@ -30,14 +30,14 @@ protected ResponseBase(HttpResponseStatus status, HttpResponseHeaders headers, L

protected abstract List<Cookie> buildCookies();

protected Charset calculateCharset(String charset) {
protected Charset calculateCharset(Charset charset) {

if (charset == null) {
String contentType = getContentType();
if (contentType != null)
charset = AsyncHttpProviderUtils.parseCharset(contentType); // parseCharset can return null
}
return charset != null ? Charset.forName(charset) : AsyncHttpProviderUtils.DEFAULT_CHARSET;
return charset != null ? charset : AsyncHttpProviderUtils.DEFAULT_CHARSET;
}

@Override
Expand Down
Expand Up @@ -115,7 +115,7 @@ public final static String getNonEmptyPath(Uri uri) {
return isNonEmpty(uri.getPath()) ? uri.getPath() : "/";
}

public static String parseCharset(String contentType) {
public static Charset parseCharset(String contentType) {
for (String part : contentType.split(";")) {
if (part.trim().startsWith("charset=")) {
String[] val = part.split("=");
Expand All @@ -126,7 +126,8 @@ public static String parseCharset(String contentType) {
// not correct, but client should be able to handle
// it (all browsers do, Grizzly strips it by default)
// This is a poor man's trim("\"").trim("'")
return charset.replaceAll("\"", "").replaceAll("'", "");
String charsetName = charset.replaceAll("\"", "").replaceAll("'", "");
return Charset.forName(charsetName);
}
}
}
Expand Down
Expand Up @@ -16,6 +16,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -159,12 +160,12 @@ public InputStream getResponseBodyAsStream() throws IOException {
}

@Override
public String getResponseBodyExcerpt(int maxLength, String charset) throws IOException {
public String getResponseBodyExcerpt(int maxLength, Charset charset) throws IOException {
return wrappedResponse.getResponseBodyExcerpt(maxLength, charset);
}

@Override
public String getResponseBody(String charset) throws IOException {
public String getResponseBody(Charset charset) throws IOException {
return wrappedResponse.getResponseBody(charset);
}

Expand Down
Expand Up @@ -15,6 +15,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.List;

import org.asynchttpclient.FluentCaseInsensitiveStringsMap;
Expand Down Expand Up @@ -61,15 +62,15 @@ public String getResponseBodyExcerpt(int maxLength) throws IOException {
return response.getResponseBodyExcerpt(maxLength);
}

public String getResponseBodyExcerpt(int maxLength, String charset) throws IOException {
public String getResponseBodyExcerpt(int maxLength, Charset charset) throws IOException {
return response.getResponseBodyExcerpt(maxLength, charset);
}

public String getResponseBody() throws IOException {
return response.getResponseBody();
}

public String getResponseBody(String charset) throws IOException {
public String getResponseBody(Charset charset) throws IOException {
return response.getResponseBody(charset);
}

Expand Down
Expand Up @@ -28,8 +28,6 @@
import javax.net.ssl.SSLHandshakeException;
import javax.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.net.ConnectException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
Expand Down
Expand Up @@ -73,11 +73,11 @@ public void testNonAsciiContentLength() throws Exception {

protected void execute(String body) throws IOException, InterruptedException, ExecutionException {
try (AsyncHttpClient client = getAsyncHttpClient(null)) {
BoundRequestBuilder r = client.preparePost(getTargetUrl()).setBody(body).setBodyEncoding(UTF_8.name());
BoundRequestBuilder r = client.preparePost(getTargetUrl()).setBody(body).setBodyCharset(UTF_8);
Future<Response> f = r.execute();
Response resp = f.get();
assertEquals(resp.getStatusCode(), 200);
assertEquals(body, resp.getResponseBody(UTF_8.name()));
assertEquals(body, resp.getResponseBody(UTF_8));
}
}
}
Expand Up @@ -15,6 +15,7 @@
*/
package org.asynchttpclient.async;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.testng.Assert.assertEquals;

import java.io.IOException;
Expand Down Expand Up @@ -117,8 +118,8 @@ public void testPercentageEncodedUserInfo() {
@Test(groups = {"standalone", "default_provider"})
public void testContentTypeCharsetToBodyEncoding() {
final Request req = new RequestBuilder("GET").setHeader("Content-Type", "application/json; charset=utf-8").build();
assertEquals(req.getBodyEncoding(), "utf-8");
assertEquals(req.getBodyCharset(), UTF_8);
final Request req2 = new RequestBuilder("GET").setHeader("Content-Type", "application/json; charset=\"utf-8\"").build();
assertEquals(req2.getBodyEncoding(), "utf-8");
assertEquals(req2.getBodyCharset(), UTF_8);
}
}
Expand Up @@ -209,7 +209,7 @@ private NettyBody body(Request request, HttpMethod method) throws IOException {
NettyBody nettyBody = null;
if (method != HttpMethod.CONNECT) {

Charset bodyCharset = request.getBodyEncoding() == null ? DEFAULT_CHARSET : Charset.forName(request.getBodyEncoding());
Charset bodyCharset = request.getBodyCharset() == null ? DEFAULT_CHARSET : request.getBodyCharset();

if (request.getByteData() != null)
nettyBody = new NettyByteArrayBody(request.getByteData());
Expand Down
Expand Up @@ -18,6 +18,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -57,7 +58,7 @@ public String getResponseBody() throws IOException {
return getResponseBody(null);
}

public String getResponseBody(String charset) throws IOException {
public String getResponseBody(Charset charset) throws IOException {
return getResponseBodyAsChannelBuffer().toString(calculateCharset(charset));
}

Expand Down Expand Up @@ -91,7 +92,7 @@ public String getResponseBodyExcerpt(int maxLength) throws IOException {
return getResponseBodyExcerpt(maxLength, null);
}

public String getResponseBodyExcerpt(int maxLength, String charset) throws IOException {
public String getResponseBodyExcerpt(int maxLength, Charset charset) throws IOException {
String response = getResponseBody(charset);
return response.length() <= maxLength ? response : response.substring(0, maxLength);
}
Expand Down
Expand Up @@ -209,7 +209,7 @@ private NettyBody body(Request request, HttpMethod method) throws IOException {
NettyBody nettyBody = null;
if (method != HttpMethod.CONNECT) {

Charset bodyCharset = request.getBodyEncoding() == null ? DEFAULT_CHARSET : Charset.forName(request.getBodyEncoding());
Charset bodyCharset = request.getBodyCharset() == null ? DEFAULT_CHARSET : request.getBodyCharset();

if (request.getByteData() != null)
nettyBody = new NettyByteArrayBody(request.getByteData());
Expand Down
Expand Up @@ -21,6 +21,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -48,7 +49,7 @@ public String getResponseBodyExcerpt(int maxLength) throws IOException {
return getResponseBodyExcerpt(maxLength, null);
}

public String getResponseBodyExcerpt(int maxLength, String charset) throws IOException {
public String getResponseBodyExcerpt(int maxLength, Charset charset) throws IOException {
byte[] b = contentToBytes(bodyParts, maxLength);
// should be fine; except that it may split multi-byte chars (last char may become '?')
return new String(b, calculateCharset(charset));
Expand Down Expand Up @@ -100,7 +101,7 @@ public String getResponseBody() throws IOException {
}

@Override
public String getResponseBody(String charset) throws IOException {
public String getResponseBody(Charset charset) throws IOException {
return new String(getResponseBodyAsBytes(), calculateCharset(charset));
}

Expand Down

0 comments on commit d35ba38

Please sign in to comment.