mirror of
https://github.com/cryptomator/cryptomator.git
synced 2026-05-22 04:31:27 +00:00
Added delay for requests on invalid vault ids. Issue #319
This commit is contained in:
@@ -11,6 +11,8 @@ package org.cryptomator.frontend.webdav;
|
||||
import java.io.IOException;
|
||||
import java.util.EnumSet;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
@@ -21,12 +23,24 @@ import org.cryptomator.frontend.webdav.filters.LoopbackFilter;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
|
||||
/**
|
||||
* The server needs to respond to requests to the root resource, because Windows is stupid.
|
||||
*/
|
||||
public class WindowsCompatibilityServlet extends HttpServlet {
|
||||
@Singleton
|
||||
class DefaultServlet extends HttpServlet {
|
||||
|
||||
private static final String ROOT_PATH = "/";
|
||||
private static final String WILDCARD = "/*";
|
||||
|
||||
private final Tarpit tarpit;
|
||||
|
||||
@Inject
|
||||
public DefaultServlet(Tarpit tarpit) {
|
||||
this.tarpit = tarpit;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
tarpit.handle(req);
|
||||
super.service(req, resp);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
@@ -36,11 +50,11 @@ public class WindowsCompatibilityServlet extends HttpServlet {
|
||||
resp.setStatus(HttpServletResponse.SC_NO_CONTENT);
|
||||
}
|
||||
|
||||
public static ServletContextHandler createServletContextHandler() {
|
||||
public ServletContextHandler createServletContextHandler() {
|
||||
final ServletContextHandler servletContext = new ServletContextHandler(null, ROOT_PATH, ServletContextHandler.NO_SESSIONS);
|
||||
final ServletHolder servletHolder = new ServletHolder(ROOT_PATH, WindowsCompatibilityServlet.class);
|
||||
final ServletHolder servletHolder = new ServletHolder(ROOT_PATH, this);
|
||||
servletContext.addServlet(servletHolder, ROOT_PATH);
|
||||
servletContext.addFilter(LoopbackFilter.class, ROOT_PATH, EnumSet.of(DispatcherType.REQUEST));
|
||||
servletContext.addFilter(LoopbackFilter.class, WILDCARD, EnumSet.of(DispatcherType.REQUEST));
|
||||
return servletContext;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Markus Kreusch
|
||||
* This file is licensed under the terms of the MIT license.
|
||||
* See the LICENSE.txt file for more info.
|
||||
*******************************************************************************/
|
||||
package org.cryptomator.frontend.webdav;
|
||||
|
||||
import static java.lang.Math.max;
|
||||
import static java.lang.System.currentTimeMillis;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
@Singleton
|
||||
class Tarpit {
|
||||
|
||||
private static final long DELAY_MS = 10000;
|
||||
|
||||
@Inject
|
||||
public Tarpit() {}
|
||||
|
||||
public void handle(HttpServletRequest req) {
|
||||
if (isRequestWithVaultId(req)) {
|
||||
delayExecutionUninterruptibly();
|
||||
}
|
||||
}
|
||||
|
||||
private void delayExecutionUninterruptibly() {
|
||||
long expected = currentTimeMillis() + DELAY_MS;
|
||||
long sleepTime = DELAY_MS;
|
||||
while (expected > currentTimeMillis()) {
|
||||
try {
|
||||
Thread.sleep(sleepTime);
|
||||
} catch (InterruptedException e) {
|
||||
sleepTime = max(0, currentTimeMillis() - expected + 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isRequestWithVaultId(HttpServletRequest req) {
|
||||
String path = req.getServletPath();
|
||||
return path.matches("^/[a-zA-Z0-9_-]{12}/.*$");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -47,7 +47,7 @@ public class WebDavServer implements FrontendFactory {
|
||||
private final WebDavMounterProvider webdavMounterProvider;
|
||||
|
||||
@Inject
|
||||
WebDavServer(WebDavServletContextFactory servletContextFactory, WebDavMounterProvider webdavMounterProvider) {
|
||||
WebDavServer(WebDavServletContextFactory servletContextFactory, WebDavMounterProvider webdavMounterProvider, DefaultServlet defaultServlet) {
|
||||
final BlockingQueue<Runnable> queue = new LinkedBlockingQueue<>(MAX_PENDING_REQUESTS);
|
||||
final ThreadPool tp = new QueuedThreadPool(MAX_THREADS, MIN_THREADS, THREAD_IDLE_SECONDS, queue);
|
||||
this.server = new Server(tp);
|
||||
@@ -56,7 +56,7 @@ public class WebDavServer implements FrontendFactory {
|
||||
this.servletContextFactory = servletContextFactory;
|
||||
this.webdavMounterProvider = webdavMounterProvider;
|
||||
|
||||
servletCollection.addHandler(WindowsCompatibilityServlet.createServletContextHandler());
|
||||
servletCollection.addHandler(defaultServlet.createServletContextHandler());
|
||||
server.setConnectors(new Connector[] {localConnector});
|
||||
server.setHandler(servletCollection);
|
||||
}
|
||||
|
||||
@@ -35,10 +35,9 @@ import org.eclipse.jetty.servlet.ServletHolder;
|
||||
class WebDavServletContextFactory {
|
||||
|
||||
private static final String WILDCARD = "/*";
|
||||
|
||||
|
||||
@Inject
|
||||
public WebDavServletContextFactory() {
|
||||
}
|
||||
public WebDavServletContextFactory() {}
|
||||
|
||||
/**
|
||||
* Creates a new Jetty ServletContextHandler, that can be be added to a servletCollection as follows:
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
*******************************************************************************/
|
||||
package org.cryptomator.frontend.webdav;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
@@ -21,21 +23,26 @@ import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
|
||||
public class WindowsCompatibilityServletTest {
|
||||
public class DefaultServletTest {
|
||||
|
||||
private Tarpit tarpit = mock(Tarpit.class);
|
||||
|
||||
private DefaultServlet inTest = new DefaultServlet(tarpit);
|
||||
|
||||
@Test
|
||||
public void testFactory() throws ServletException {
|
||||
ServletHolder[] holders = WindowsCompatibilityServlet.createServletContextHandler().getServletHandler().getServlets();
|
||||
|
||||
ServletHolder[] holders = inTest.createServletContextHandler().getServletHandler().getServlets();
|
||||
Assert.assertEquals(1, holders.length);
|
||||
ServletHolder holder = holders[0];
|
||||
|
||||
Servlet servlet = holder.getServlet();
|
||||
Assert.assertTrue(servlet instanceof WindowsCompatibilityServlet);
|
||||
Assert.assertTrue(servlet instanceof DefaultServlet);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResponse() throws IOException, ServletException {
|
||||
final WindowsCompatibilityServlet servlet = new WindowsCompatibilityServlet();
|
||||
final DefaultServlet servlet = inTest;
|
||||
final HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
|
||||
final HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
|
||||
|
||||
Reference in New Issue
Block a user