Merge pull request #1778 from gianm/redirect-fixes

Redirect fixes
This commit is contained in:
Xavier Léauté 2015-09-25 09:54:48 -07:00
commit 25bbc0b923
5 changed files with 109 additions and 10 deletions

View File

@ -40,6 +40,7 @@ import io.druid.server.initialization.IndexerZkConfig;
import org.apache.curator.framework.CuratorFramework; import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.leader.LeaderSelector; import org.apache.curator.framework.recipes.leader.LeaderSelector;
import org.apache.curator.framework.recipes.leader.LeaderSelectorListener; import org.apache.curator.framework.recipes.leader.LeaderSelectorListener;
import org.apache.curator.framework.recipes.leader.Participant;
import org.apache.curator.framework.state.ConnectionState; import org.apache.curator.framework.state.ConnectionState;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
@ -243,7 +244,12 @@ public class TaskMaster
public String getLeader() public String getLeader()
{ {
try { try {
return leaderSelector.getLeader().getId(); final Participant leader = leaderSelector.getLeader();
if (leader != null && leader.isLeader()) {
return leader.getId();
} else {
return null;
}
} }
catch (Exception e) { catch (Exception e) {
throw Throwables.propagate(e); throw Throwables.propagate(e);

View File

@ -19,9 +19,11 @@ package io.druid.indexing.overlord.http;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.google.inject.Inject; import com.google.inject.Inject;
import com.metamx.common.IAE;
import io.druid.indexing.overlord.TaskMaster; import io.druid.indexing.overlord.TaskMaster;
import io.druid.server.http.RedirectInfo; import io.druid.server.http.RedirectInfo;
import java.net.URI;
import java.net.URL; import java.net.URL;
/** /**
@ -46,7 +48,12 @@ public class OverlordRedirectInfo implements RedirectInfo
public URL getRedirectURL(String queryString, String requestURI) public URL getRedirectURL(String queryString, String requestURI)
{ {
try { try {
return new URL(String.format("http://%s%s", taskMaster.getLeader(), requestURI)); final String leader = taskMaster.getLeader();
if (leader == null || leader.isEmpty()) {
return null;
} else {
return new URI("http", leader, requestURI, queryString, null).toURL();
}
} }
catch (Exception e) { catch (Exception e) {
throw Throwables.propagate(e); throw Throwables.propagate(e);

View File

@ -0,0 +1,83 @@
/*
* 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.indexing.overlord.http;
import io.druid.indexing.overlord.TaskMaster;
import org.easymock.EasyMock;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.net.URL;
public class OverlordRedirectInfoTest
{
private TaskMaster taskMaster;
private OverlordRedirectInfo redirectInfo;
@Before
public void setUp()
{
taskMaster = EasyMock.createMock(TaskMaster.class);
redirectInfo = new OverlordRedirectInfo(taskMaster);
}
@Test
public void testDoLocal()
{
EasyMock.expect(taskMaster.isLeading()).andReturn(true).anyTimes();
EasyMock.replay(taskMaster);
Assert.assertTrue(redirectInfo.doLocal());
EasyMock.verify(taskMaster);
}
@Test
public void testGetRedirectURLNull()
{
EasyMock.expect(taskMaster.getLeader()).andReturn(null).anyTimes();
EasyMock.replay(taskMaster);
URL url = redirectInfo.getRedirectURL("query", "/request");
Assert.assertNull(url);
EasyMock.verify(taskMaster);
}
@Test
public void testGetRedirectURLEmpty()
{
EasyMock.expect(taskMaster.getLeader()).andReturn("").anyTimes();
EasyMock.replay(taskMaster);
URL url = redirectInfo.getRedirectURL("query", "/request");
Assert.assertNull(url);
EasyMock.verify(taskMaster);
}
@Test
public void testGetRedirectURL()
{
String host = "localhost";
String query = "foo=bar&x=y";
String request = "/request";
EasyMock.expect(taskMaster.getLeader()).andReturn(host).anyTimes();
EasyMock.replay(taskMaster);
URL url = redirectInfo.getRedirectURL(query, request);
Assert.assertEquals("http://localhost/request?foo=bar&x=y", url.toString());
EasyMock.verify(taskMaster);
}
}

View File

@ -72,12 +72,12 @@ public class RedirectFilter implements Filter
log.debug("Forwarding request to [%s]", url); log.debug("Forwarding request to [%s]", url);
if (url == null) { if (url == null) {
// We apparently have no coordinator, so let's do a Service Unavailable // We apparently have nothing to redirect to, so let's do a Service Unavailable
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE); response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
return; return;
} }
response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); response.setStatus(HttpServletResponse.SC_TEMPORARY_REDIRECT);
response.setHeader("Location", url.toString()); response.setHeader("Location", url.toString());
} }
} }

View File

@ -53,18 +53,21 @@ public class CoordinatorRedirectInfoTest
{ {
EasyMock.expect(druidCoordinator.getCurrentLeader()).andReturn(null).anyTimes(); EasyMock.expect(druidCoordinator.getCurrentLeader()).andReturn(null).anyTimes();
EasyMock.replay(druidCoordinator); EasyMock.replay(druidCoordinator);
URL url = coordinatorRedirectInfo.getRedirectURL("query", "request"); URL url = coordinatorRedirectInfo.getRedirectURL("query", "/request");
Assert.assertNull(url); Assert.assertNull(url);
EasyMock.verify(druidCoordinator);
} }
@Test @Test
public void testGetRedirectURL() public void testGetRedirectURL()
{ {
String host = "localhost"; String host = "localhost";
String query = "query"; String query = "foo=bar&x=y";
String request = "request"; String request = "/request";
EasyMock.expect(druidCoordinator.getCurrentLeader()).andReturn(host).anyTimes(); EasyMock.expect(druidCoordinator.getCurrentLeader()).andReturn(host).anyTimes();
EasyMock.replay(druidCoordinator); EasyMock.replay(druidCoordinator);
URL url = coordinatorRedirectInfo.getRedirectURL(query, request); URL url = coordinatorRedirectInfo.getRedirectURL(query, request);
Assert.assertTrue(url.toString().contains(host+request+"?"+query)); Assert.assertEquals("http://localhost/request?foo=bar&x=y", url.toString());
EasyMock.verify(druidCoordinator);
} }
} }