Watcher: Fix encoding of UTF8 data in HttpClient (elastic/x-pack-elasticsearch#3398)
The HttpClient uses an Apache HTTP client class named StringEntity to encode a HTTP request body. This one however assumes ISO-8859-1 as its charset when encoding the string based body to bytes. This commit switches to a byte array based body, then sets the content type header and falls back to the old text/plain content type if no content type header is specified. relates elastic/x-pack-elasticsearch#3397 Original commit: elastic/x-pack-elasticsearch@d5a6e7f0c7
This commit is contained in:
parent
2eb3f02e40
commit
6f2fddc5f6
|
@ -23,7 +23,8 @@ import org.apache.http.client.utils.URLEncodedUtils;
|
||||||
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
|
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
|
||||||
import org.apache.http.conn.ssl.NoopHostnameVerifier;
|
import org.apache.http.conn.ssl.NoopHostnameVerifier;
|
||||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||||
import org.apache.http.entity.StringEntity;
|
import org.apache.http.entity.ByteArrayEntity;
|
||||||
|
import org.apache.http.entity.ContentType;
|
||||||
import org.apache.http.impl.auth.BasicScheme;
|
import org.apache.http.impl.auth.BasicScheme;
|
||||||
import org.apache.http.impl.client.BasicAuthCache;
|
import org.apache.http.impl.client.BasicAuthCache;
|
||||||
import org.apache.http.impl.client.BasicCredentialsProvider;
|
import org.apache.http.impl.client.BasicCredentialsProvider;
|
||||||
|
@ -38,10 +39,10 @@ import org.elasticsearch.common.unit.ByteSizeValue;
|
||||||
import org.elasticsearch.common.unit.TimeValue;
|
import org.elasticsearch.common.unit.TimeValue;
|
||||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||||
import org.elasticsearch.common.xcontent.XContentType;
|
import org.elasticsearch.common.xcontent.XContentType;
|
||||||
import org.elasticsearch.xpack.watcher.common.http.auth.ApplicableHttpAuth;
|
|
||||||
import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuthRegistry;
|
|
||||||
import org.elasticsearch.xpack.common.socket.SocketAccess;
|
import org.elasticsearch.xpack.common.socket.SocketAccess;
|
||||||
import org.elasticsearch.xpack.ssl.SSLService;
|
import org.elasticsearch.xpack.ssl.SSLService;
|
||||||
|
import org.elasticsearch.xpack.watcher.common.http.auth.ApplicableHttpAuth;
|
||||||
|
import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuthRegistry;
|
||||||
|
|
||||||
import javax.net.ssl.HostnameVerifier;
|
import javax.net.ssl.HostnameVerifier;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
@ -104,8 +105,15 @@ public class HttpClient extends AbstractComponent {
|
||||||
internalRequest = new HttpHead(uri);
|
internalRequest = new HttpHead(uri);
|
||||||
} else {
|
} else {
|
||||||
HttpMethodWithEntity methodWithEntity = new HttpMethodWithEntity(uri, request.method.name());
|
HttpMethodWithEntity methodWithEntity = new HttpMethodWithEntity(uri, request.method.name());
|
||||||
if (request.body != null) {
|
if (request.hasBody()) {
|
||||||
methodWithEntity.setEntity(new StringEntity(request.body));
|
ByteArrayEntity entity = new ByteArrayEntity(request.body.getBytes(StandardCharsets.UTF_8));
|
||||||
|
String contentType = request.headers().get(HttpHeaders.CONTENT_TYPE);
|
||||||
|
if (Strings.hasLength(contentType)) {
|
||||||
|
entity.setContentType(contentType);
|
||||||
|
} else {
|
||||||
|
entity.setContentType(ContentType.TEXT_PLAIN.toString());
|
||||||
|
}
|
||||||
|
methodWithEntity.setEntity(entity);
|
||||||
}
|
}
|
||||||
internalRequest = methodWithEntity;
|
internalRequest = methodWithEntity;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
package org.elasticsearch.xpack.watcher.common.http;
|
package org.elasticsearch.xpack.watcher.common.http;
|
||||||
|
|
||||||
import com.carrotsearch.randomizedtesting.generators.RandomStrings;
|
import com.carrotsearch.randomizedtesting.generators.RandomStrings;
|
||||||
|
import org.apache.http.HttpHeaders;
|
||||||
import org.apache.http.client.ClientProtocolException;
|
import org.apache.http.client.ClientProtocolException;
|
||||||
import org.apache.logging.log4j.message.ParameterizedMessage;
|
import org.apache.logging.log4j.message.ParameterizedMessage;
|
||||||
import org.apache.logging.log4j.util.Supplier;
|
import org.apache.logging.log4j.util.Supplier;
|
||||||
|
@ -14,6 +15,7 @@ import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.common.unit.ByteSizeUnit;
|
import org.elasticsearch.common.unit.ByteSizeUnit;
|
||||||
import org.elasticsearch.common.unit.ByteSizeValue;
|
import org.elasticsearch.common.unit.ByteSizeValue;
|
||||||
import org.elasticsearch.common.unit.TimeValue;
|
import org.elasticsearch.common.unit.TimeValue;
|
||||||
|
import org.elasticsearch.common.xcontent.XContentType;
|
||||||
import org.elasticsearch.env.Environment;
|
import org.elasticsearch.env.Environment;
|
||||||
import org.elasticsearch.env.TestEnvironment;
|
import org.elasticsearch.env.TestEnvironment;
|
||||||
import org.elasticsearch.mocksocket.MockServerSocket;
|
import org.elasticsearch.mocksocket.MockServerSocket;
|
||||||
|
@ -21,12 +23,12 @@ import org.elasticsearch.test.ESTestCase;
|
||||||
import org.elasticsearch.test.http.MockResponse;
|
import org.elasticsearch.test.http.MockResponse;
|
||||||
import org.elasticsearch.test.http.MockWebServer;
|
import org.elasticsearch.test.http.MockWebServer;
|
||||||
import org.elasticsearch.test.junit.annotations.Network;
|
import org.elasticsearch.test.junit.annotations.Network;
|
||||||
import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuthRegistry;
|
|
||||||
import org.elasticsearch.xpack.watcher.common.http.auth.basic.BasicAuth;
|
|
||||||
import org.elasticsearch.xpack.watcher.common.http.auth.basic.BasicAuthFactory;
|
|
||||||
import org.elasticsearch.xpack.ssl.SSLService;
|
import org.elasticsearch.xpack.ssl.SSLService;
|
||||||
import org.elasticsearch.xpack.ssl.TestsSSLService;
|
import org.elasticsearch.xpack.ssl.TestsSSLService;
|
||||||
import org.elasticsearch.xpack.ssl.VerificationMode;
|
import org.elasticsearch.xpack.ssl.VerificationMode;
|
||||||
|
import org.elasticsearch.xpack.watcher.common.http.auth.HttpAuthRegistry;
|
||||||
|
import org.elasticsearch.xpack.watcher.common.http.auth.basic.BasicAuth;
|
||||||
|
import org.elasticsearch.xpack.watcher.common.http.auth.basic.BasicAuthFactory;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
|
||||||
|
@ -494,4 +496,21 @@ public class HttpClientTests extends ESTestCase {
|
||||||
assertThat(response.body(), is(nullValue()));
|
assertThat(response.body(), is(nullValue()));
|
||||||
assertThat(webServer.requests(), hasSize(1));
|
assertThat(webServer.requests(), hasSize(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testThatBodyWithUTF8Content() throws Exception {
|
||||||
|
String body = "title あいうえお";
|
||||||
|
webServer.enqueue(new MockResponse().setResponseCode(200).setBody(body));
|
||||||
|
|
||||||
|
HttpRequest request = HttpRequest.builder("localhost", webServer.getPort())
|
||||||
|
.path("/")
|
||||||
|
.setHeader(HttpHeaders.CONTENT_TYPE, XContentType.JSON.mediaType())
|
||||||
|
.body(body)
|
||||||
|
.build();
|
||||||
|
HttpResponse response = httpClient.execute(request);
|
||||||
|
assertThat(response.body().utf8ToString(), is(body));
|
||||||
|
|
||||||
|
assertThat(webServer.requests(), hasSize(1));
|
||||||
|
assertThat(webServer.requests().get(0).getHeader(HttpHeaders.CONTENT_TYPE), is(XContentType.JSON.mediaType()));
|
||||||
|
assertThat(webServer.requests().get(0).getBody(), is(body));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,7 +56,7 @@ public class SlackServiceTests extends AbstractWatcherIntegrationTestCase {
|
||||||
SlackService service = getInstanceFromMaster(SlackService.class);
|
SlackService service = getInstanceFromMaster(SlackService.class);
|
||||||
Attachment[] attachments = new Attachment[] {
|
Attachment[] attachments = new Attachment[] {
|
||||||
new Attachment("fallback", randomFrom("good", "warning", "danger"), "pretext `code` *bold*", "author_name", null, null,
|
new Attachment("fallback", randomFrom("good", "warning", "danger"), "pretext `code` *bold*", "author_name", null, null,
|
||||||
"title", null, "_text `code` *bold*", null, null, null, new String[] { "text", "pretext" })
|
"title あいうえお", null, "_text `code` *bold*", null, null, null, new String[] { "text", "pretext" })
|
||||||
};
|
};
|
||||||
SlackMessage message = new SlackMessage(
|
SlackMessage message = new SlackMessage(
|
||||||
"SlackServiceTests",
|
"SlackServiceTests",
|
||||||
|
|
Loading…
Reference in New Issue