Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ class PrecommitTasks {
if (testForbidden != null) {
testForbidden.configure {
signaturesURLs += getClass().getResource('/forbidden/es-test-signatures.txt')
signaturesURLs += getClass().getResource('/forbidden/http-signatures.txt')
}
}
Task forbiddenApis = project.tasks.findByName('forbiddenApis')
Expand Down
45 changes: 45 additions & 0 deletions buildSrc/src/main/resources/forbidden/http-signatures.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# Licensed to Elasticsearch under one or more contributor
# license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright
# ownership. Elasticsearch licenses this file to you under
# the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on
# an 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
# either express or implied. See the License for the specific
# language governing permissions and limitations under the License.

@defaultMessage Explicitly specify the ContentType of HTTP entities when creating
org.apache.http.entity.StringEntity#<init>(java.lang.String)
org.apache.http.entity.StringEntity#<init>(java.lang.String,java.lang.String)
org.apache.http.entity.StringEntity#<init>(java.lang.String,java.nio.charset.Charset)
org.apache.http.entity.ByteArrayEntity#<init>(byte[])
org.apache.http.entity.ByteArrayEntity#<init>(byte[],int,int)
org.apache.http.entity.FileEntity#<init>(java.io.File)
org.apache.http.entity.InputStreamEntity#<init>(java.io.InputStream)
org.apache.http.entity.InputStreamEntity#<init>(java.io.InputStream,long)
org.apache.http.nio.entity.NByteArrayEntity#<init>(byte[])
org.apache.http.nio.entity.NByteArrayEntity#<init>(byte[],int,int)
org.apache.http.nio.entity.NFileEntity#<init>(java.io.File)
org.apache.http.nio.entity.NStringEntity#<init>(java.lang.String)
org.apache.http.nio.entity.NStringEntity#<init>(java.lang.String,java.lang.String)

@defaultMessage Use non-deprecated constructors
org.apache.http.nio.entity.NFileEntity#<init>(java.io.File,java.lang.String)
org.apache.http.nio.entity.NFileEntity#<init>(java.io.File,java.lang.String,boolean)
org.apache.http.entity.FileEntity#<init>(java.io.File,java.lang.String)
org.apache.http.entity.StringEntity#<init>(java.lang.String,java.lang.String,java.lang.String)

@defaultMessage BasicEntity is easy to mess up and forget to set content type
org.apache.http.entity.BasicHttpEntity#<init>()

@defaultMessage EntityTemplate is easy to mess up and forget to set content type
org.apache.http.entity.EntityTemplate#<init>(org.apache.http.entity.ContentProducer)

@defaultMessage SerializableEntity uses java serialization and makes it easy to forget to set content type
org.apache.http.entity.SerializableEntity#<init>(java.io.Serializable)
8 changes: 8 additions & 0 deletions client/rest-high-level/build.gradle
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import org.elasticsearch.gradle.precommit.PrecommitTasks

/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
Expand Down Expand Up @@ -39,3 +41,9 @@ dependencyLicenses {
it.group.startsWith('org.elasticsearch') == false
}
}

forbiddenApisMain {
// core does not depend on the httpclient for compile so we add the signatures here. We don't add them for test as they are already
// specified
signaturesURLs += [PrecommitTasks.getResource('/forbidden/http-signatures.txt')]
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import org.apache.http.ProtocolVersion;
import org.apache.http.RequestLine;
import org.apache.http.StatusLine;
import org.apache.http.entity.BasicHttpEntity;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
Expand Down Expand Up @@ -144,7 +143,7 @@ public void testParseEntity() throws IOException {
}
{
IllegalStateException ise = expectThrows(IllegalStateException.class,
() -> RestHighLevelClient.parseEntity(new BasicHttpEntity(), null));
() -> RestHighLevelClient.parseEntity(new StringEntity("", (ContentType) null), null));
assertEquals("Elasticsearch didn't return the [Content-Type] header, unable to parse response body", ise.getMessage());
}
{
Expand Down
8 changes: 5 additions & 3 deletions client/rest/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,18 @@ dependencies {
}

forbiddenApisMain {
//client does not depend on core, so only jdk signatures should be checked
signaturesURLs = [PrecommitTasks.getResource('/forbidden/jdk-signatures.txt')]
//client does not depend on core, so only jdk and http signatures should be checked
signaturesURLs = [PrecommitTasks.getResource('/forbidden/jdk-signatures.txt'),
PrecommitTasks.getResource('/forbidden/http-signatures.txt')]
}

forbiddenApisTest {
//we are using jdk-internal instead of jdk-non-portable to allow for com.sun.net.httpserver.* usage
bundledSignatures -= 'jdk-non-portable'
bundledSignatures += 'jdk-internal'
//client does not depend on core, so only jdk signatures should be checked
signaturesURLs = [PrecommitTasks.getResource('/forbidden/jdk-signatures.txt')]
signaturesURLs = [PrecommitTasks.getResource('/forbidden/jdk-signatures.txt'),
PrecommitTasks.getResource('/forbidden/http-signatures.txt')]
}

dependencyLicenses {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package org.elasticsearch.client;

import org.apache.http.ContentTooLongException;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.ProtocolVersion;
import org.apache.http.StatusLine;
Expand All @@ -32,6 +33,8 @@
import org.apache.http.nio.IOControl;
import org.apache.http.protocol.HttpContext;

import java.util.concurrent.atomic.AtomicReference;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
Expand All @@ -56,7 +59,7 @@ public void testResponseProcessing() throws Exception {
ProtocolVersion protocolVersion = new ProtocolVersion("HTTP", 1, 1);
StatusLine statusLine = new BasicStatusLine(protocolVersion, 200, "OK");
HttpResponse httpResponse = new BasicHttpResponse(statusLine);
httpResponse.setEntity(new StringEntity("test"));
httpResponse.setEntity(new StringEntity("test", ContentType.TEXT_PLAIN));

//everything goes well
consumer.responseReceived(httpResponse);
Expand Down Expand Up @@ -99,11 +102,17 @@ private static void bufferLimitTest(HeapBufferedAsyncResponseConsumer consumer,
StatusLine statusLine = new BasicStatusLine(protocolVersion, 200, "OK");
consumer.onResponseReceived(new BasicHttpResponse(statusLine));

BasicHttpEntity entity = new BasicHttpEntity();
entity.setContentLength(randomInt(bufferLimit));
final AtomicReference<Long> contentLength = new AtomicReference<>();
HttpEntity entity = new StringEntity("", ContentType.APPLICATION_JSON) {
@Override
public long getContentLength() {
return contentLength.get();
}
};
contentLength.set(randomLong(bufferLimit));
consumer.onEntityEnclosed(entity, ContentType.APPLICATION_JSON);

entity.setContentLength(randomIntBetween(bufferLimit + 1, MAX_TEST_BUFFER_SIZE));
contentLength.set(randomLongBetween(bufferLimit + 1, MAX_TEST_BUFFER_SIZE));
try {
consumer.onEntityEnclosed(entity, ContentType.APPLICATION_JSON);
} catch(ContentTooLongException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpTrace;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.message.BasicHeader;
Expand Down Expand Up @@ -71,20 +72,21 @@ public void testTraceRequest() throws IOException, URISyntaxException {
HttpEntity entity;
switch(randomIntBetween(0, 4)) {
case 0:
entity = new StringEntity(requestBody, StandardCharsets.UTF_8);
entity = new StringEntity(requestBody, ContentType.APPLICATION_JSON);
break;
case 1:
entity = new InputStreamEntity(new ByteArrayInputStream(requestBody.getBytes(StandardCharsets.UTF_8)));
entity = new InputStreamEntity(new ByteArrayInputStream(requestBody.getBytes(StandardCharsets.UTF_8)),
ContentType.APPLICATION_JSON);
break;
case 2:
entity = new NStringEntity(requestBody, StandardCharsets.UTF_8);
entity = new NStringEntity(requestBody, ContentType.APPLICATION_JSON);
break;
case 3:
entity = new NByteArrayEntity(requestBody.getBytes(StandardCharsets.UTF_8));
entity = new NByteArrayEntity(requestBody.getBytes(StandardCharsets.UTF_8), ContentType.APPLICATION_JSON);
break;
case 4:
// Evil entity without a charset
entity = new StringEntity(requestBody, (Charset) null);
entity = new StringEntity(requestBody, ContentType.create("application/json", (Charset) null));
break;
default:
throw new UnsupportedOperationException();
Expand Down Expand Up @@ -122,15 +124,16 @@ public void testTraceResponse() throws IOException {
HttpEntity entity;
switch(randomIntBetween(0, 2)) {
case 0:
entity = new StringEntity(responseBody, StandardCharsets.UTF_8);
entity = new StringEntity(responseBody, ContentType.APPLICATION_JSON);
break;
case 1:
//test a non repeatable entity
entity = new InputStreamEntity(new ByteArrayInputStream(responseBody.getBytes(StandardCharsets.UTF_8)));
entity = new InputStreamEntity(new ByteArrayInputStream(responseBody.getBytes(StandardCharsets.UTF_8)),
ContentType.APPLICATION_JSON);
break;
case 2:
// Evil entity without a charset
entity = new StringEntity(responseBody, (Charset) null);
entity = new StringEntity(responseBody, ContentType.create("application/json", (Charset) null));
break;
default:
throw new UnsupportedOperationException();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.apache.http.ProtocolVersion;
import org.apache.http.RequestLine;
import org.apache.http.StatusLine;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.entity.StringEntity;
import org.apache.http.message.BasicHttpResponse;
Expand Down Expand Up @@ -52,10 +53,11 @@ public void testResponseException() throws IOException {
if (hasBody) {
HttpEntity entity;
if (getRandom().nextBoolean()) {
entity = new StringEntity(responseBody, StandardCharsets.UTF_8);
entity = new StringEntity(responseBody, ContentType.APPLICATION_JSON);
} else {
//test a non repeatable entity
entity = new InputStreamEntity(new ByteArrayInputStream(responseBody.getBytes(StandardCharsets.UTF_8)));
entity = new InputStreamEntity(new ByteArrayInputStream(responseBody.getBytes(StandardCharsets.UTF_8)),
ContentType.APPLICATION_JSON);
}
httpResponse.setEntity(entity);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
Expand Down Expand Up @@ -249,7 +250,7 @@ private Response bodyTest(final String method) throws IOException {

private Response bodyTest(final RestClient restClient, final String method) throws IOException {
String requestBody = "{ \"field\": \"value\" }";
StringEntity entity = new StringEntity(requestBody);
StringEntity entity = new StringEntity(requestBody, ContentType.APPLICATION_JSON);
int statusCode = randomStatusCode(getRandom());
Response esResponse;
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.concurrent.FutureCallback;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
Expand Down Expand Up @@ -293,7 +294,7 @@ public void testIOExceptions() throws IOException {
*/
public void testBody() throws IOException {
String body = "{ \"field\": \"value\" }";
StringEntity entity = new StringEntity(body);
StringEntity entity = new StringEntity(body, ContentType.APPLICATION_JSON);
for (String method : Arrays.asList("DELETE", "GET", "PATCH", "POST", "PUT")) {
for (int okStatusCode : getOkStatusCodes()) {
Response response = restClient.performRequest(method, "/" + okStatusCode, Collections.<String, String>emptyMap(), entity);
Expand Down Expand Up @@ -431,7 +432,7 @@ private HttpUriRequest performRandomRequest(String method) throws Exception {
HttpEntity entity = null;
boolean hasBody = request instanceof HttpEntityEnclosingRequest && getRandom().nextBoolean();
if (hasBody) {
entity = new StringEntity(randomAsciiOfLengthBetween(10, 100));
entity = new StringEntity(randomAsciiOfLengthBetween(10, 100), ContentType.APPLICATION_JSON);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks for fixing all these.

((HttpEntityEnclosingRequest) request).setEntity(entity);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,19 +139,6 @@ public PutRepositoryRequest settings(Settings.Builder settings) {
return this;
}

/**
* Sets the repository settings.
*
* @param source repository settings in json or yaml format
* @return this request
* @deprecated use {@link #settings(String, XContentType)} to avoid content type auto-detection
*/
@Deprecated
public PutRepositoryRequest settings(String source) {
this.settings = Settings.builder().loadFromSource(source).build();
return this;
}

/**
* Sets the repository settings.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,19 +89,6 @@ public PutRepositoryRequestBuilder setSettings(Settings.Builder settings) {
return this;
}

/**
* Sets the repository settings in Json or Yaml format
*
* @param source repository settings
* @return this builder
* @deprecated use {@link #setSettings(String, XContentType)} instead to avoid content type auto detection
*/
@Deprecated
public PutRepositoryRequestBuilder setSettings(String source) {
request.settings(source);
return this;
}

/**
* Sets the repository settings in Json or Yaml format
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,16 +81,6 @@ public ClusterUpdateSettingsRequest transientSettings(Settings.Builder settings)
return this;
}

/**
* Sets the source containing the transient settings to be updated. They will not survive a full cluster restart
* @deprecated use {@link #transientSettings(String, XContentType)} to avoid content type detection
*/
@Deprecated
public ClusterUpdateSettingsRequest transientSettings(String source) {
this.transientSettings = Settings.builder().loadFromSource(source).build();
return this;
}

/**
* Sets the source containing the transient settings to be updated. They will not survive a full cluster restart
*/
Expand Down Expand Up @@ -130,16 +120,6 @@ public ClusterUpdateSettingsRequest persistentSettings(Settings.Builder settings
return this;
}

/**
* Sets the source containing the persistent settings to be updated. They will get applied cross restarts
* @deprecated use {@link #persistentSettings(String, XContentType)} to avoid content type detection
*/
@Deprecated
public ClusterUpdateSettingsRequest persistentSettings(String source) {
this.persistentSettings = Settings.builder().loadFromSource(source).build();
return this;
}

/**
* Sets the source containing the persistent settings to be updated. They will get applied cross restarts
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,16 +51,6 @@ public ClusterUpdateSettingsRequestBuilder setTransientSettings(Settings.Builder
return this;
}

/**
* Sets the source containing the transient settings to be updated. They will not survive a full cluster restart
* @deprecated use {@link #setTransientSettings(String, XContentType)} to avoid content type detection
*/
@Deprecated
public ClusterUpdateSettingsRequestBuilder setTransientSettings(String settings) {
request.transientSettings(settings);
return this;
}

/**
* Sets the source containing the transient settings to be updated. They will not survive a full cluster restart
*/
Expand Down Expand Up @@ -93,16 +83,6 @@ public ClusterUpdateSettingsRequestBuilder setPersistentSettings(Settings.Builde
return this;
}

/**
* Sets the source containing the persistent settings to be updated. They will get applied cross restarts
* @deprecated use {@link #setPersistentSettings(String, XContentType)} to avoid content type detection
*/
@Deprecated
public ClusterUpdateSettingsRequestBuilder setPersistentSettings(String settings) {
request.persistentSettings(settings);
return this;
}

/**
* Sets the source containing the persistent settings to be updated. They will get applied cross restarts
*/
Expand Down
Loading