diff --git a/integration-tests/src/test/java/org/apache/druid/tests/security/AbstractAuthConfigurationTest.java b/integration-tests/src/test/java/org/apache/druid/tests/security/AbstractAuthConfigurationTest.java index e97c35375c3..42556ad2531 100644 --- a/integration-tests/src/test/java/org/apache/druid/tests/security/AbstractAuthConfigurationTest.java +++ b/integration-tests/src/test/java/org/apache/druid/tests/security/AbstractAuthConfigurationTest.java @@ -445,12 +445,14 @@ public abstract class AbstractAuthConfigurationTest public void test_avaticaQuery_broker() { testAvaticaQuery(getBrokerAvacticaUrl()); + testAvaticaQuery(StringUtils.maybeRemoveTrailingSlash(getBrokerAvacticaUrl())); } @Test public void test_avaticaQuery_router() { testAvaticaQuery(getRouterAvacticaUrl()); + testAvaticaQuery(StringUtils.maybeRemoveTrailingSlash(getRouterAvacticaUrl())); } @Test diff --git a/services/src/main/java/org/apache/druid/cli/RouterJettyServerInitializer.java b/services/src/main/java/org/apache/druid/cli/RouterJettyServerInitializer.java index 1850de588a5..a959f91e3bc 100644 --- a/services/src/main/java/org/apache/druid/cli/RouterJettyServerInitializer.java +++ b/services/src/main/java/org/apache/druid/cli/RouterJettyServerInitializer.java @@ -59,7 +59,9 @@ public class RouterJettyServerInitializer implements JettyServerInitializer // The router will keep the connection context in the forwarded message, and the broker is responsible for // performing the auth checks. DruidAvaticaJsonHandler.AVATICA_PATH, - DruidAvaticaProtobufHandler.AVATICA_PATH + DruidAvaticaJsonHandler.AVATICA_PATH_NO_TRAILING_SLASH, + DruidAvaticaProtobufHandler.AVATICA_PATH, + DruidAvaticaProtobufHandler.AVATICA_PATH_NO_TRAILING_SLASH ); private final DruidHttpClientConfig routerHttpClientConfig; diff --git a/sql/src/main/java/org/apache/druid/sql/avatica/DruidAvaticaJsonHandler.java b/sql/src/main/java/org/apache/druid/sql/avatica/DruidAvaticaJsonHandler.java index ffb1107bacf..e2d223d1266 100644 --- a/sql/src/main/java/org/apache/druid/sql/avatica/DruidAvaticaJsonHandler.java +++ b/sql/src/main/java/org/apache/druid/sql/avatica/DruidAvaticaJsonHandler.java @@ -24,6 +24,7 @@ import org.apache.calcite.avatica.remote.LocalService; import org.apache.calcite.avatica.remote.Service; import org.apache.calcite.avatica.server.AvaticaJsonHandler; import org.apache.druid.guice.annotations.Self; +import org.apache.druid.java.util.common.StringUtils; import org.apache.druid.server.DruidNode; import org.eclipse.jetty.server.Request; @@ -35,6 +36,7 @@ import java.io.IOException; public class DruidAvaticaJsonHandler extends AvaticaJsonHandler { public static final String AVATICA_PATH = "/druid/v2/sql/avatica/"; + public static final String AVATICA_PATH_NO_TRAILING_SLASH = "/druid/v2/sql/avatica"; @Inject public DruidAvaticaJsonHandler( @@ -55,7 +57,7 @@ public class DruidAvaticaJsonHandler extends AvaticaJsonHandler final HttpServletResponse response ) throws IOException, ServletException { - if (request.getRequestURI().equals(AVATICA_PATH)) { + if (AVATICA_PATH_NO_TRAILING_SLASH.equals(StringUtils.maybeRemoveTrailingSlash(request.getRequestURI()))) { super.handle(target, baseRequest, request, response); } } diff --git a/sql/src/main/java/org/apache/druid/sql/avatica/DruidAvaticaProtobufHandler.java b/sql/src/main/java/org/apache/druid/sql/avatica/DruidAvaticaProtobufHandler.java index 8bc9f33d9f9..50c54ad27ac 100644 --- a/sql/src/main/java/org/apache/druid/sql/avatica/DruidAvaticaProtobufHandler.java +++ b/sql/src/main/java/org/apache/druid/sql/avatica/DruidAvaticaProtobufHandler.java @@ -24,6 +24,7 @@ import org.apache.calcite.avatica.remote.LocalService; import org.apache.calcite.avatica.remote.Service; import org.apache.calcite.avatica.server.AvaticaProtobufHandler; import org.apache.druid.guice.annotations.Self; +import org.apache.druid.java.util.common.StringUtils; import org.apache.druid.server.DruidNode; import org.eclipse.jetty.server.Request; @@ -35,6 +36,7 @@ import java.io.IOException; public class DruidAvaticaProtobufHandler extends AvaticaProtobufHandler { public static final String AVATICA_PATH = "/druid/v2/sql/avatica-protobuf/"; + public static final String AVATICA_PATH_NO_TRAILING_SLASH = "/druid/v2/sql/avatica-protobuf"; @Inject public DruidAvaticaProtobufHandler( @@ -55,7 +57,7 @@ public class DruidAvaticaProtobufHandler extends AvaticaProtobufHandler final HttpServletResponse response ) throws IOException, ServletException { - if (request.getRequestURI().equals(AVATICA_PATH)) { + if (AVATICA_PATH_NO_TRAILING_SLASH.equals(StringUtils.maybeRemoveTrailingSlash(request.getRequestURI()))) { super.handle(target, baseRequest, request, response); } } diff --git a/sql/src/test/java/org/apache/druid/sql/avatica/DruidAvaticaHandlerTest.java b/sql/src/test/java/org/apache/druid/sql/avatica/DruidAvaticaHandlerTest.java index 3934665da48..91d83fa86cb 100644 --- a/sql/src/test/java/org/apache/druid/sql/avatica/DruidAvaticaHandlerTest.java +++ b/sql/src/test/java/org/apache/druid/sql/avatica/DruidAvaticaHandlerTest.java @@ -115,7 +115,7 @@ public abstract class DruidAvaticaHandlerTest extends CalciteTestBase public int getMaxConnections() { // This must match the number of Connection objects created in setUp() - return 3; + return 4; } @Override @@ -156,6 +156,7 @@ public abstract class DruidAvaticaHandlerTest extends CalciteTestBase private SpecificSegmentsQuerySegmentWalker walker; private Server server; private Connection client; + private Connection clientNoTrailingSlash; private Connection superuserClient; private Connection clientLosAngeles; private DruidMeta druidMeta; @@ -221,6 +222,7 @@ public abstract class DruidAvaticaHandlerTest extends CalciteTestBase url = this.getJdbcConnectionString(port); client = DriverManager.getConnection(url, "regularUser", "druid"); superuserClient = DriverManager.getConnection(url, CalciteTests.TEST_SUPERUSER_NAME, "druid"); + clientNoTrailingSlash = DriverManager.getConnection(StringUtils.maybeRemoveTrailingSlash(url), CalciteTests.TEST_SUPERUSER_NAME, "druid"); final Properties propertiesLosAngeles = new Properties(); propertiesLosAngeles.setProperty("sqlTimeZone", "America/Los_Angeles"); @@ -234,11 +236,13 @@ public abstract class DruidAvaticaHandlerTest extends CalciteTestBase { client.close(); clientLosAngeles.close(); + clientNoTrailingSlash.close(); server.stop(); walker.close(); walker = null; client = null; clientLosAngeles = null; + clientNoTrailingSlash = null; server = null; } @@ -255,6 +259,19 @@ public abstract class DruidAvaticaHandlerTest extends CalciteTestBase ); } + @Test + public void testSelectCountNoTrailingSlash() throws Exception + { + final ResultSet resultSet = clientNoTrailingSlash.createStatement().executeQuery("SELECT COUNT(*) AS cnt FROM druid.foo"); + final List> rows = getRows(resultSet); + Assert.assertEquals( + ImmutableList.of( + ImmutableMap.of("cnt", 6L) + ), + rows + ); + } + @Test public void testSelectCountAlternateStyle() throws Exception { @@ -811,19 +828,15 @@ public abstract class DruidAvaticaHandlerTest extends CalciteTestBase @Test public void testTooManyConnections() throws Exception { - final Connection connection1 = DriverManager.getConnection(url); - final Statement statement1 = connection1.createStatement(); - - final Connection connection2 = DriverManager.getConnection(url); - final Statement statement2 = connection2.createStatement(); - - final Connection connection3 = DriverManager.getConnection(url); - final Statement statement3 = connection3.createStatement(); + client.createStatement(); + clientLosAngeles.createStatement(); + superuserClient.createStatement(); + clientNoTrailingSlash.createStatement(); expectedException.expect(AvaticaClientRuntimeException.class); - expectedException.expectMessage("Too many connections, limit is[3]"); + expectedException.expectMessage("Too many connections, limit is[4]"); - final Connection connection4 = DriverManager.getConnection(url); + final Connection connection5 = DriverManager.getConnection(url); } @Test