From 63b09b59276e7f5d469df8085e85b0ee79c9d680 Mon Sep 17 00:00:00 2001 From: =?utf8?q?David=20=E2=80=98Bombe=E2=80=99=20Roden?= Date: Mon, 2 Nov 2015 21:55:29 +0100 Subject: [PATCH] Follow redirects in ClientGet --- .../fcp/quelaton/ClientGetCommand.java | 2 ++ .../fcp/quelaton/ClientGetCommandImpl.java | 25 ++++++++++++---- .../net/pterodactylus/fcp/quelaton/FcpDialog.java | 4 +++ .../fcp/quelaton/DefaultFcpClientTest.java | 34 ++++++++++++++++++++++ 4 files changed, 60 insertions(+), 5 deletions(-) diff --git a/src/main/java/net/pterodactylus/fcp/quelaton/ClientGetCommand.java b/src/main/java/net/pterodactylus/fcp/quelaton/ClientGetCommand.java index 01f88e9..385506f 100644 --- a/src/main/java/net/pterodactylus/fcp/quelaton/ClientGetCommand.java +++ b/src/main/java/net/pterodactylus/fcp/quelaton/ClientGetCommand.java @@ -2,6 +2,7 @@ package net.pterodactylus.fcp.quelaton; import java.io.InputStream; import java.util.Optional; +import java.util.function.Consumer; import net.pterodactylus.fcp.Priority; @@ -12,6 +13,7 @@ import net.pterodactylus.fcp.Priority; */ public interface ClientGetCommand { + ClientGetCommand onRedirect(Consumer onRedirect); ClientGetCommand ignoreDataStore(); ClientGetCommand dataStoreOnly(); ClientGetCommand maxSize(long maxSize); diff --git a/src/main/java/net/pterodactylus/fcp/quelaton/ClientGetCommandImpl.java b/src/main/java/net/pterodactylus/fcp/quelaton/ClientGetCommandImpl.java index 7908f5c..e60fed7 100644 --- a/src/main/java/net/pterodactylus/fcp/quelaton/ClientGetCommandImpl.java +++ b/src/main/java/net/pterodactylus/fcp/quelaton/ClientGetCommandImpl.java @@ -2,9 +2,12 @@ package net.pterodactylus.fcp.quelaton; import java.io.IOException; import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; +import java.util.function.Consumer; import java.util.function.Supplier; import net.pterodactylus.fcp.AllData; @@ -27,6 +30,7 @@ class ClientGetCommandImpl implements ClientGetCommand { private final ListeningExecutorService threadPool; private final ConnectionSupplier connectionSupplier; private final Supplier identifierGenerator; + private final List> onRedirects = new ArrayList<>(); private boolean ignoreDataStore; private boolean dataStoreOnly; @@ -42,6 +46,12 @@ class ClientGetCommandImpl implements ClientGetCommand { } @Override + public ClientGetCommand onRedirect(Consumer onRedirect) { + onRedirects.add(onRedirect); + return this; + } + + @Override public ClientGetCommand ignoreDataStore() { ignoreDataStore = true; return this; @@ -83,14 +93,13 @@ class ClientGetCommandImpl implements ClientGetCommand { } private Optional execute(String uri) throws InterruptedException, ExecutionException, IOException { - ClientGet clientGet = createClientGetCommand(uri); + ClientGet clientGet = createClientGetCommand(identifierGenerator.get(), uri); try (ClientGetDialog clientGetDialog = new ClientGetDialog()) { return clientGetDialog.send(clientGet).get(); } } - private ClientGet createClientGetCommand(String uri) { - String identifier = identifierGenerator.get(); + private ClientGet createClientGetCommand(String identifier, String uri) { ClientGet clientGet = new ClientGet(uri, identifier, ReturnType.direct); if (ignoreDataStore) { clientGet.setIgnoreDataStore(true); @@ -116,7 +125,8 @@ class ClientGetCommandImpl implements ClientGetCommand { private class ClientGetDialog extends FcpDialog> { public ClientGetDialog() throws IOException { - super(ClientGetCommandImpl.this.threadPool, ClientGetCommandImpl.this.connectionSupplier.get(), Optional.empty()); + super(ClientGetCommandImpl.this.threadPool, ClientGetCommandImpl.this.connectionSupplier.get(), + Optional.empty()); } @Override @@ -155,7 +165,12 @@ class ClientGetCommandImpl implements ClientGetCommand { @Override protected void consumeGetFailed(GetFailed getFailed) { - finish(); + if (getFailed.getCode() == 27) { + onRedirects.forEach(onRedirect -> onRedirect.accept(getFailed.getRedirectURI())); + sendMessage(createClientGetCommand(getIdentifier(), getFailed.getRedirectURI())); + } else { + finish(); + } } } diff --git a/src/main/java/net/pterodactylus/fcp/quelaton/FcpDialog.java b/src/main/java/net/pterodactylus/fcp/quelaton/FcpDialog.java index 5b030bd..f2b71fd 100644 --- a/src/main/java/net/pterodactylus/fcp/quelaton/FcpDialog.java +++ b/src/main/java/net/pterodactylus/fcp/quelaton/FcpDialog.java @@ -85,6 +85,10 @@ public abstract class FcpDialog implements AutoCloseable, FcpListener { this.identifier.set(identifier); } + protected String getIdentifier() { + return identifier.get(); + } + public final boolean isFinished() { return finished.get(); } diff --git a/src/test/java/net/pterodactylus/fcp/quelaton/DefaultFcpClientTest.java b/src/test/java/net/pterodactylus/fcp/quelaton/DefaultFcpClientTest.java index 0a39451..61a7d0a 100644 --- a/src/test/java/net/pterodactylus/fcp/quelaton/DefaultFcpClientTest.java +++ b/src/test/java/net/pterodactylus/fcp/quelaton/DefaultFcpClientTest.java @@ -1299,6 +1299,30 @@ public class DefaultFcpClientTest { connectAndAssert(() -> matchesFcpMessage("ClientGet", "URI=KSK@foo.txt", "Global=true")); } + @Test + public void clientGetFollowsRedirect() throws InterruptedException, ExecutionException, IOException { + Future> data = fcpClient.clientGet().uri("USK@foo/bar").execute(); + connectAndAssert(() -> matchesFcpMessage("ClientGet", "URI=USK@foo/bar")); + replyWithRedirect("USK@foo/baz"); + readMessage(() -> matchesFcpMessage("ClientGet", "URI=USK@foo/baz")); + replyWithAllData(identifier, "Hello", "text/plain;charset=utf-8"); + verifyData(data.get()); + } + + @Test + public void clientGetNotifiesListenersOnRedirect() throws IOException, ExecutionException, InterruptedException { + List redirects = new ArrayList<>(); + Future> data = fcpClient.clientGet().onRedirect(redirects::add).uri("USK@foo/bar").execute(); + connectAndAssert(() -> matchesFcpMessage("ClientGet", "URI=USK@foo/bar")); + replyWithRedirect("USK@foo/baz"); + readMessage(() -> matchesFcpMessage("ClientGet", "URI=USK@foo/baz")); + replyWithRedirect("USK@foo/quux"); + readMessage(() -> matchesFcpMessage("ClientGet", "URI=USK@foo/quux")); + replyWithAllData(identifier, "Hello", "text/plain;charset=utf-8"); + verifyData(data.get()); + assertThat(redirects, contains("USK@foo/baz", "USK@foo/quux")); + } + private void replyWithGetFailed(String identifier) throws IOException { fcpServer.writeLine( "GetFailed", @@ -1308,6 +1332,16 @@ public class DefaultFcpClientTest { ); } + private void replyWithRedirect(String newUri) throws IOException { + fcpServer.writeLine( + "GetFailed", + "Identifier=" + identifier, + "Code=27", + "RedirectURI=" + newUri, + "EndMessage" + ); + } + private void replyWithAllData(String identifier, String text, String contentType) throws IOException { fcpServer.writeLine( "AllData", -- 2.7.4