summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitFilter.java15
-rw-r--r--org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ReceivePackErrorHandler.java60
-rw-r--r--org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ReceivePackServlet.java70
3 files changed, 117 insertions, 28 deletions
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitFilter.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitFilter.java
index e9462eeb4c..06970a7693 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitFilter.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitFilter.java
@@ -96,6 +96,8 @@ public class GitFilter extends MetaFilter {
private ReceivePackFactory<HttpServletRequest> receivePackFactory = new DefaultReceivePackFactory();
+ private ReceivePackErrorHandler receivePackErrorHandler;
+
private final List<Filter> uploadPackFilters = new LinkedList<>();
private final List<Filter> receivePackFilters = new LinkedList<>();
@@ -190,6 +192,17 @@ public class GitFilter extends MetaFilter {
}
/**
+ * Set a custom error handler for git-receive-pack.
+ *
+ * @param h
+ * A custom error handler for git-receive-pack.
+ */
+ public void setReceivePackErrorHandler(ReceivePackErrorHandler h) {
+ assertNotInitialized();
+ this.receivePackErrorHandler = h;
+ }
+
+ /**
* Add receive-pack filter
*
* @param filter
@@ -233,7 +246,7 @@ public class GitFilter extends MetaFilter {
b = b.through(new ReceivePackServlet.Factory(receivePackFactory));
for (Filter f : receivePackFilters)
b = b.through(f);
- b.with(new ReceivePackServlet());
+ b.with(new ReceivePackServlet(receivePackErrorHandler));
}
ServletBinder refs = serve("*/" + Constants.INFO_REFS);
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ReceivePackErrorHandler.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ReceivePackErrorHandler.java
new file mode 100644
index 0000000000..ee66cb102f
--- /dev/null
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ReceivePackErrorHandler.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2019, Google LLC and others
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Distribution License v. 1.0 which is available at
+ * http://www.eclipse.org/org/documents/edl-v10.php.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+package org.eclipse.jgit.http.server;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jgit.transport.ReceivePack;
+import org.eclipse.jgit.transport.ServiceMayNotContinueException;
+
+/**
+ * Handle git-receive-pack errors.
+ *
+ * <p>
+ * This is an entry point for customizing an error handler for git-receive-pack.
+ * Right before calling {@link ReceivePack#receiveWithExceptionPropagation},
+ * JGit will call this handler if specified through {@link GitFilter}. The
+ * implementation of this handler is responsible for calling
+ * {@link ReceivePackRunnable} and handling exceptions for clients.
+ *
+ * <p>
+ * If a custom handler is not specified, JGit will use the default error
+ * handler.
+ *
+ * @since 5.6
+ */
+public interface ReceivePackErrorHandler {
+ /**
+ * @param req
+ * The HTTP request
+ * @param rsp
+ * The HTTP response
+ * @param r
+ * A continuation that handles a git-receive-pack request.
+ * @throws IOException
+ */
+ void receive(HttpServletRequest req, HttpServletResponse rsp,
+ ReceivePackRunnable r) throws IOException;
+
+ /** Process a git-receive-pack request. */
+ public interface ReceivePackRunnable {
+ /**
+ * See {@link ReceivePack#receiveWithExceptionPropagation}.
+ *
+ * @throws ServiceMayNotContinueException
+ * @throws IOException
+ */
+ void receive() throws ServiceMayNotContinueException, IOException;
+ }
+
+}
diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ReceivePackServlet.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ReceivePackServlet.java
index aed36560a8..eb130d0a28 100644
--- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ReceivePackServlet.java
+++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/ReceivePackServlet.java
@@ -71,6 +71,7 @@ import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.errors.CorruptObjectException;
import org.eclipse.jgit.errors.PackProtocolException;
import org.eclipse.jgit.errors.UnpackException;
@@ -161,6 +162,13 @@ class ReceivePackServlet extends HttpServlet {
}
}
+ @Nullable
+ private final ReceivePackErrorHandler handler;
+
+ ReceivePackServlet(@Nullable ReceivePackErrorHandler handler) {
+ this.handler = handler;
+ }
+
/** {@inheritDoc} */
@Override
public void doPost(final HttpServletRequest req,
@@ -178,34 +186,42 @@ class ReceivePackServlet extends HttpServlet {
};
ReceivePack rp = (ReceivePack) req.getAttribute(ATTRIBUTE_HANDLER);
- try {
- rp.setBiDirectionalPipe(false);
- rsp.setContentType(RECEIVE_PACK_RESULT_TYPE);
-
- rp.receive(getInputStream(req), out, null);
- out.close();
- } catch (CorruptObjectException e ) {
- // This should be already reported to the client.
- getServletContext().log(MessageFormat.format(
- HttpServerText.get().receivedCorruptObject,
- e.getMessage(),
- ServletUtils.identify(rp.getRepository())));
- consumeRequestBody(req);
- out.close();
-
- } catch (UnpackException | PackProtocolException e) {
- // This should be already reported to the client.
- log(rp.getRepository(), e.getCause());
- consumeRequestBody(req);
- out.close();
-
- } catch (Throwable e) {
- log(rp.getRepository(), e);
- if (!rsp.isCommitted()) {
- rsp.reset();
- sendError(req, rsp, SC_INTERNAL_SERVER_ERROR);
+ rp.setBiDirectionalPipe(false);
+ rsp.setContentType(RECEIVE_PACK_RESULT_TYPE);
+
+ if (handler != null) {
+ handler.receive(req, rsp, () -> {
+ rp.receiveWithExceptionPropagation(getInputStream(req), out,
+ null);
+ out.close();
+ });
+ } else {
+ try {
+ rp.receive(getInputStream(req), out, null);
+ out.close();
+ } catch (CorruptObjectException e ) {
+ // This should be already reported to the client.
+ getServletContext().log(MessageFormat.format(
+ HttpServerText.get().receivedCorruptObject,
+ e.getMessage(),
+ ServletUtils.identify(rp.getRepository())));
+ consumeRequestBody(req);
+ out.close();
+
+ } catch (UnpackException | PackProtocolException e) {
+ // This should be already reported to the client.
+ log(rp.getRepository(), e.getCause());
+ consumeRequestBody(req);
+ out.close();
+
+ } catch (Throwable e) {
+ log(rp.getRepository(), e);
+ if (!rsp.isCommitted()) {
+ rsp.reset();
+ sendError(req, rsp, SC_INTERNAL_SERVER_ERROR);
+ }
+ return;
}
- return;
}
}