Same as UploadPack, add a custom error handler. Change-Id: I9c708aa5a22e01214c1d997fa6f72f4b8bf814f0 Signed-off-by: Masaya Suzuki <masayasuzuki@google.com>tags/v5.7.0.202001151323-m1
@@ -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<>(); | |||
@@ -189,6 +191,17 @@ public class GitFilter extends MetaFilter { | |||
this.receivePackFactory = f != null ? f : (ReceivePackFactory<HttpServletRequest>)ReceivePackFactory.DISABLED; | |||
} | |||
/** | |||
* 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 | |||
* | |||
@@ -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); |
@@ -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; | |||
} | |||
} |
@@ -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; | |||
} | |||
} | |||