Repository: kafka Updated Branches: refs/heads/0.10.0 c7f725dbb -> 2ed41cec9
KAFKA-4827: Correctly encode special chars while creating URI objects Author: Arjun Satish <ar...@confluent.io> Reviewers: Randall Hauch <rha...@gmail.com>, Ewen Cheslack-Postava <e...@confluent.io> Closes #4273 from wicknicks/KAFKA-4827-0.10.2 (cherry picked from commit 6a0b84aa0f2bf43eff7293fb285043e9584f32c3) Signed-off-by: Ewen Cheslack-Postava <m...@ewencp.org> Project: http://git-wip-us.apache.org/repos/asf/kafka/repo Commit: http://git-wip-us.apache.org/repos/asf/kafka/commit/2ed41cec Tree: http://git-wip-us.apache.org/repos/asf/kafka/tree/2ed41cec Diff: http://git-wip-us.apache.org/repos/asf/kafka/diff/2ed41cec Branch: refs/heads/0.10.0 Commit: 2ed41cec9c6aa9f8549bb0692efd86fd4911a897 Parents: c7f725d Author: Arjun Satish <ar...@confluent.io> Authored: Wed Nov 29 10:13:25 2017 -0800 Committer: Ewen Cheslack-Postava <m...@ewencp.org> Committed: Wed Nov 29 10:14:12 2017 -0800 ---------------------------------------------------------------------- .../rest/resources/ConnectorsResource.java | 12 ++++-- .../rest/resources/ConnectorsResourceTest.java | 42 ++++++++++++++++++++ 2 files changed, 50 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/kafka/blob/2ed41cec/connect/runtime/src/main/java/org/apache/kafka/connect/runtime/rest/resources/ConnectorsResource.java ---------------------------------------------------------------------- diff --git a/connect/runtime/src/main/java/org/apache/kafka/connect/runtime/rest/resources/ConnectorsResource.java b/connect/runtime/src/main/java/org/apache/kafka/connect/runtime/rest/resources/ConnectorsResource.java index 2ec35f4..4c2fdd9 100644 --- a/connect/runtime/src/main/java/org/apache/kafka/connect/runtime/rest/resources/ConnectorsResource.java +++ b/connect/runtime/src/main/java/org/apache/kafka/connect/runtime/rest/resources/ConnectorsResource.java @@ -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(); } http://git-wip-us.apache.org/repos/asf/kafka/blob/2ed41cec/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/resources/ConnectorsResourceTest.java ---------------------------------------------------------------------- diff --git a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/resources/ConnectorsResourceTest.java b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/resources/ConnectorsResourceTest.java index aa1b9a7..5e13b2e 100644 --- a/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/resources/ConnectorsResourceTest.java +++ b/connect/runtime/src/test/java/org/apache/kafka/connect/runtime/rest/resources/ConnectorsResourceTest.java @@ -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);