KAFKA-4827: Correctly encode special chars while creating URI objects

Author: Arjun Satish <arjun@confluent.io>

Reviewers: Randall Hauch <rhauch@gmail.com>, Ewen Cheslack-Postava <ewen@confluent.io>

Closes #4273 from wicknicks/KAFKA-4827-0.10.2

(cherry picked from commit 6a0b84aa0f)
Signed-off-by: Ewen Cheslack-Postava <me@ewencp.org>
This commit is contained in:
Arjun Satish 2017-11-29 10:13:25 -08:00 committed by Ewen Cheslack-Postava
parent 48cbb89d3e
commit 2c620ba1f8
2 changed files with 50 additions and 4 deletions

View File

@ -97,7 +97,9 @@ public class ConnectorsResource {
herder.putConnectorConfig(name, configs, false, cb);
Herder.Created<ConnectorInfo> info = completeOrForwardRequest(cb, "/connectors", "POST", createRequest,
new TypeReference<ConnectorInfo>() { }, new CreatedConnectorInfoTranslator(), forward);
return Response.created(URI.create("/connectors/" + name)).entity(info.result()).build();
URI location = UriBuilder.fromUri("/connectors").path(name).build();
return Response.created(location).entity(info.result()).build();
}
@GET
@ -142,10 +144,12 @@ public class ConnectorsResource {
Herder.Created<ConnectorInfo> createdInfo = completeOrForwardRequest(cb, "/connectors/" + connector + "/config",
"PUT", connectorConfig, new TypeReference<ConnectorInfo>() { }, new CreatedConnectorInfoTranslator(), forward);
Response.ResponseBuilder response;
if (createdInfo.created())
response = Response.created(URI.create("/connectors/" + connector));
else
if (createdInfo.created()) {
URI location = UriBuilder.fromUri("/connectors").path(connector).build();
response = Response.created(location);
} else {
response = Response.ok();
}
return response.entity(createdInfo.result()).build();
}

View File

@ -35,6 +35,7 @@ import org.apache.kafka.connect.util.ConnectorTaskId;
import org.easymock.Capture;
import org.easymock.EasyMock;
import org.easymock.IAnswer;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -45,6 +46,7 @@ import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import javax.ws.rs.BadRequestException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@ -65,8 +67,15 @@ public class ConnectorsResourceTest {
// URL construction properly, avoiding //, which will mess up routing in the REST server
private static final String LEADER_URL = "http://leader:8083/";
private static final String CONNECTOR_NAME = "test";
private static final String CONNECTOR_NAME_SPECIAL_CHARS = "t?a=b&c=d\rx=1.1\n>< \t`'\" x%y+z!#$&'()*+,:;=?@[]";
private static final String CONNECTOR2_NAME = "test2";
private static final Boolean FORWARD = true;
private static final Map<String, String> CONNECTOR_CONFIG_SPECIAL_CHARS = new HashMap<>();
static {
CONNECTOR_CONFIG_SPECIAL_CHARS.put("name", CONNECTOR_NAME_SPECIAL_CHARS);
CONNECTOR_CONFIG_SPECIAL_CHARS.put("sample_config", "test_config");
}
private static final Map<String, String> CONNECTOR_CONFIG = new HashMap<>();
static {
CONNECTOR_CONFIG.put("name", CONNECTOR_NAME);
@ -291,6 +300,39 @@ public class ConnectorsResourceTest {
PowerMock.verifyAll();
}
@Test
public void testCreateConnectorWithSpecialCharsInName() throws Throwable {
CreateConnectorRequest body = new CreateConnectorRequest(CONNECTOR_NAME_SPECIAL_CHARS, Collections.singletonMap(ConnectorConfig.NAME_CONFIG, CONNECTOR_NAME_SPECIAL_CHARS));
final Capture<Callback<Herder.Created<ConnectorInfo>>> cb = Capture.newInstance();
herder.putConnectorConfig(EasyMock.eq(CONNECTOR_NAME_SPECIAL_CHARS), EasyMock.eq(body.config()), EasyMock.eq(false), EasyMock.capture(cb));
expectAndCallbackResult(cb, new Herder.Created<>(true, new ConnectorInfo(CONNECTOR_NAME_SPECIAL_CHARS, CONNECTOR_CONFIG, CONNECTOR_TASK_NAMES)));
PowerMock.replayAll();
String rspLocation = connectorsResource.createConnector(FORWARD, body).getLocation().toString();
String decoded = new URI(rspLocation).getPath();
Assert.assertEquals("/connectors/" + CONNECTOR_NAME_SPECIAL_CHARS, decoded);
PowerMock.verifyAll();
}
@Test
public void testPutConnectorConfigWithSpecialCharsInName() throws Throwable {
final Capture<Callback<Herder.Created<ConnectorInfo>>> cb = Capture.newInstance();
herder.putConnectorConfig(EasyMock.eq(CONNECTOR_NAME_SPECIAL_CHARS), EasyMock.eq(CONNECTOR_CONFIG_SPECIAL_CHARS), EasyMock.eq(true), EasyMock.capture(cb));
expectAndCallbackResult(cb, new Herder.Created<>(true, new ConnectorInfo(CONNECTOR_NAME_SPECIAL_CHARS, CONNECTOR_CONFIG_SPECIAL_CHARS, CONNECTOR_TASK_NAMES)));
PowerMock.replayAll();
String rspLocation = connectorsResource.putConnectorConfig(CONNECTOR_NAME_SPECIAL_CHARS, FORWARD, CONNECTOR_CONFIG_SPECIAL_CHARS).getLocation().toString();
String decoded = new URI(rspLocation).getPath();
Assert.assertEquals("/connectors/" + CONNECTOR_NAME_SPECIAL_CHARS, decoded);
PowerMock.verifyAll();
}
@Test(expected = BadRequestException.class)
public void testPutConnectorConfigNameMismatch() throws Throwable {
Map<String, String> connConfig = new HashMap<>(CONNECTOR_CONFIG);