From 6e84caf3d5aed64d02dcd856239e65e6b9f99dcd Mon Sep 17 00:00:00 2001 From: nishant Date: Tue, 28 Apr 2015 21:51:13 +0530 Subject: [PATCH] Proxy Requests from coordinator to overlord Add unit test and support https scheme review comments --- .../server/http/OverlordProxyServlet.java | 67 +++++++++++++++++++ .../server/http/OverlordProxyServletTest.java | 50 ++++++++++++++ .../CoordinatorJettyServerInitializer.java | 2 + 3 files changed, 119 insertions(+) create mode 100644 server/src/main/java/io/druid/server/http/OverlordProxyServlet.java create mode 100644 server/src/test/java/io/druid/server/http/OverlordProxyServletTest.java diff --git a/server/src/main/java/io/druid/server/http/OverlordProxyServlet.java b/server/src/main/java/io/druid/server/http/OverlordProxyServlet.java new file mode 100644 index 00000000000..534154b6bd6 --- /dev/null +++ b/server/src/main/java/io/druid/server/http/OverlordProxyServlet.java @@ -0,0 +1,67 @@ +/* + * Druid - a distributed column store. + * Copyright 2012 - 2015 Metamarkets Group Inc. + * + * Licensed 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. + */ + +package io.druid.server.http; + +import com.google.api.client.repackaged.com.google.common.base.Throwables; +import com.google.inject.Inject; +import com.metamx.common.ISE; +import io.druid.client.indexing.IndexingService; +import io.druid.client.selector.Server; +import io.druid.curator.discovery.ServerDiscoverySelector; +import org.eclipse.jetty.proxy.ProxyServlet; + +import javax.servlet.http.HttpServletRequest; +import java.net.URI; +import java.net.URISyntaxException; + +/** + * A Proxy servlet that proxies requests to the overlord. + */ +public class OverlordProxyServlet extends ProxyServlet +{ + private final ServerDiscoverySelector selector; + + @Inject + OverlordProxyServlet( + @IndexingService ServerDiscoverySelector selector + ) + { + this.selector = selector; + } + + @Override + protected URI rewriteURI(HttpServletRequest request) + { + try { + final Server indexer = selector.pick(); + if (indexer == null) { + throw new ISE("Cannot find instance of indexingService"); + } + return new URI( + request.getScheme(), + indexer.getHost(), + request.getRequestURI(), + request.getQueryString(), + null + ); + } + catch (URISyntaxException e) { + throw Throwables.propagate(e); + } + } +} diff --git a/server/src/test/java/io/druid/server/http/OverlordProxyServletTest.java b/server/src/test/java/io/druid/server/http/OverlordProxyServletTest.java new file mode 100644 index 00000000000..b25842277ff --- /dev/null +++ b/server/src/test/java/io/druid/server/http/OverlordProxyServletTest.java @@ -0,0 +1,50 @@ +/* + * Licensed to Metamarkets Group Inc. (Metamarkets) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. Metamarkets 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. + */ + +package io.druid.server.http; + +import io.druid.client.selector.Server; +import io.druid.curator.discovery.ServerDiscoverySelector; +import junit.framework.Assert; +import org.easymock.EasyMock; +import org.junit.Test; + +import javax.servlet.http.HttpServletRequest; +import java.net.URI; + +public class OverlordProxyServletTest +{ + @Test + public void testRewriteURI() + { + ServerDiscoverySelector selector = EasyMock.createMock(ServerDiscoverySelector.class); + Server server = EasyMock.createMock(Server.class); + EasyMock.expect(server.getHost()).andReturn("overlord:port"); + EasyMock.expect(selector.pick()).andReturn(server).anyTimes(); + HttpServletRequest request = EasyMock.createMock(HttpServletRequest.class); + EasyMock.expect(request.getScheme()).andReturn("https").anyTimes(); + EasyMock.expect(request.getQueryString()).andReturn("param1=test¶m2=test2").anyTimes(); + EasyMock.expect(request.getRequestURI()).andReturn("/druid/overlord/worker").anyTimes(); + EasyMock.replay(server, selector, request); + + URI uri = new OverlordProxyServlet(selector).rewriteURI(request); + Assert.assertEquals("https://overlord:port/druid/overlord/worker?param1=test¶m2=test2", uri.toString()); + } + +} diff --git a/services/src/main/java/io/druid/cli/CoordinatorJettyServerInitializer.java b/services/src/main/java/io/druid/cli/CoordinatorJettyServerInitializer.java index 2059714a657..3ef1fbd80f5 100644 --- a/services/src/main/java/io/druid/cli/CoordinatorJettyServerInitializer.java +++ b/services/src/main/java/io/druid/cli/CoordinatorJettyServerInitializer.java @@ -21,6 +21,7 @@ import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.servlet.GuiceFilter; import io.druid.server.coordinator.DruidCoordinatorConfig; +import io.druid.server.http.OverlordProxyServlet; import io.druid.server.http.RedirectFilter; import io.druid.server.initialization.jetty.JettyServerInitUtils; import io.druid.server.initialization.jetty.JettyServerInitializer; @@ -75,6 +76,7 @@ class CoordinatorJettyServerInitializer implements JettyServerInitializer // this will be removed in the next major release root.addFilter(GuiceFilter.class, "/coordinator/*", null); + root.addServlet(new ServletHolder(injector.getInstance(OverlordProxyServlet.class)), "/druid/indexer/*"); HandlerList handlerList = new HandlerList(); handlerList.setHandlers(new Handler[]{root});