diff options
Diffstat (limited to 'org.eclipse.jgit.http.server/src')
7 files changed, 354 insertions, 96 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 7b88ae346a..980d246d2d 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 @@ -196,7 +196,7 @@ public class GitFilter extends MetaFilter { initialized = true; if (uploadPackFactory != UploadPackFactory.DISABLED) { - ServletBinder b = serve("*/git-upload-pack"); + ServletBinder b = serve("*/" + GitSmartHttpTools.UPLOAD_PACK); b = b.through(new UploadPackServlet.Factory(uploadPackFactory)); for (Filter f : uploadPackFilters) b = b.through(f); @@ -204,7 +204,7 @@ public class GitFilter extends MetaFilter { } if (receivePackFactory != ReceivePackFactory.DISABLED) { - ServletBinder b = serve("*/git-receive-pack"); + ServletBinder b = serve("*/" + GitSmartHttpTools.RECEIVE_PACK); b = b.through(new ReceivePackServlet.Factory(receivePackFactory)); for (Filter f : receivePackFilters) b = b.through(f); diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitSmartHttpTools.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitSmartHttpTools.java new file mode 100644 index 0000000000..3d2aff174d --- /dev/null +++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/GitSmartHttpTools.java @@ -0,0 +1,309 @@ +/* + * Copyright (C) 2011, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.http.server; + +import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN; +import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; +import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.transport.PacketLineOut; + +/** + * Utility functions for handling the Git-over-HTTP protocol. + */ +public class GitSmartHttpTools { + private static final String INFO_REFS = Constants.INFO_REFS; + + /** Name of the git-upload-pack service. */ + public static final String UPLOAD_PACK = "git-upload-pack"; + + /** Name of the git-receive-pack service. */ + public static final String RECEIVE_PACK = "git-receive-pack"; + + /** Content type supplied by the client to the /git-upload-pack handler. */ + public static final String UPLOAD_PACK_REQUEST_TYPE = + "application/x-git-upload-pack-request"; + + /** Content type returned from the /git-upload-pack handler. */ + public static final String UPLOAD_PACK_RESULT_TYPE = + "application/x-git-upload-pack-result"; + + /** Content type supplied by the client to the /git-receive-pack handler. */ + public static final String RECEIVE_PACK_REQUEST_TYPE = + "application/x-git-receive-pack-request"; + + /** Content type returned from the /git-receive-pack handler. */ + public static final String RECEIVE_PACK_RESULT_TYPE = + "application/x-git-receive-pack-result"; + + /** Git service names accepted by the /info/refs?service= handler. */ + public static final List<String> VALID_SERVICES = + Collections.unmodifiableList(Arrays.asList(new String[] { + UPLOAD_PACK, RECEIVE_PACK })); + + private static final String INFO_REFS_PATH = "/" + INFO_REFS; + private static final String UPLOAD_PACK_PATH = "/" + UPLOAD_PACK; + private static final String RECEIVE_PACK_PATH = "/" + RECEIVE_PACK; + + private static final List<String> SERVICE_SUFFIXES = + Collections.unmodifiableList(Arrays.asList(new String[] { + INFO_REFS_PATH, UPLOAD_PACK_PATH, RECEIVE_PACK_PATH })); + + /** + * Check a request for Git-over-HTTP indicators. + * + * @param req + * the current HTTP request that may have been made by Git. + * @return true if the request is likely made by a Git client program. + */ + public static boolean isGitClient(HttpServletRequest req) { + return isInfoRefs(req) || isUploadPack(req) || isReceivePack(req); + } + + /** + * Send an error to the Git client or browser. + * <p> + * Server implementors may use this method to send customized error messages + * to a Git protocol client using an HTTP 200 OK response with the error + * embedded in the payload. If the request was not issued by a Git client, + * an HTTP response code is returned instead. + * + * @param req + * current request. + * @param res + * current response. + * @param httpStatus + * HTTP status code to set if the client is not a Git client. + * @throws IOException + * the response cannot be sent. + */ + public static void sendError(HttpServletRequest req, + HttpServletResponse res, int httpStatus) throws IOException { + sendError(req, res, httpStatus, null); + } + + /** + * Send an error to the Git client or browser. + * <p> + * Server implementors may use this method to send customized error messages + * to a Git protocol client using an HTTP 200 OK response with the error + * embedded in the payload. If the request was not issued by a Git client, + * an HTTP response code is returned instead. + * + * @param req + * current request. + * @param res + * current response. + * @param httpStatus + * HTTP status code to set if the client is not a Git client. + * @param textForGit + * plain text message to display on the user's console. This is + * shown only if the client is likely to be a Git client. If null + * or the empty string a default text is chosen based on the HTTP + * response code. + * @throws IOException + * the response cannot be sent. + */ + public static void sendError(HttpServletRequest req, + HttpServletResponse res, int httpStatus, String textForGit) + throws IOException { + if (textForGit == null || textForGit.length() == 0) { + switch (httpStatus) { + case SC_FORBIDDEN: + textForGit = HttpServerText.get().repositoryAccessForbidden; + break; + case SC_NOT_FOUND: + textForGit = HttpServerText.get().repositoryNotFound; + break; + case SC_INTERNAL_SERVER_ERROR: + textForGit = HttpServerText.get().internalServerError; + break; + default: + textForGit = "HTTP " + httpStatus; + break; + } + } + + ByteArrayOutputStream buf = new ByteArrayOutputStream(128); + PacketLineOut pck = new PacketLineOut(buf); + + if (isInfoRefs(req)) { + String svc = req.getParameter("service"); + pck.writeString("# service=" + svc + "\n"); + pck.end(); + pck.writeString("ERR " + textForGit); + send(res, infoRefsResultType(svc), buf.toByteArray()); + } else if (isUploadPack(req)) { + pck.writeString("ERR " + textForGit); + send(res, UPLOAD_PACK_RESULT_TYPE, buf.toByteArray()); + } else if (isReceivePack(req)) { + pck.writeString("ERR " + textForGit); + send(res, RECEIVE_PACK_RESULT_TYPE, buf.toByteArray()); + } else { + res.sendError(httpStatus); + } + } + + private static void send(HttpServletResponse res, String type, byte[] buf) + throws IOException { + res.setStatus(HttpServletResponse.SC_OK); + res.setContentType(type); + res.setContentLength(buf.length); + ServletOutputStream os = res.getOutputStream(); + try { + os.write(buf); + } finally { + os.close(); + } + } + + /** + * Get the response Content-Type a client expects for the request. + * <p> + * This method should only be invoked if + * {@link #isGitClient(HttpServletRequest)} is true. + * + * @param req + * current request. + * @return the Content-Type the client expects. + * @throws IllegalArgumentException + * the request is not a Git client request. See + * {@link #isGitClient(HttpServletRequest)}. + */ + public static String getResponseContentType(HttpServletRequest req) { + if (isInfoRefs(req)) + return infoRefsResultType(req.getParameter("service")); + else if (isUploadPack(req)) + return UPLOAD_PACK_RESULT_TYPE; + else if (isReceivePack(req)) + return RECEIVE_PACK_RESULT_TYPE; + else + throw new IllegalArgumentException(); + } + + static String infoRefsResultType(String svc) { + return "application/x-" + svc + "-advertisement"; + } + + /** + * Strip the Git service suffix from a request path. + * + * Generally the suffix is stripped by the {@code SuffixPipeline} handling + * the request, so this method is rarely needed. + * + * @param path + * the path of the request. + * @return the path up to the last path component before the service suffix; + * the path as-is if it contains no service suffix. + */ + public static String stripServiceSuffix(String path) { + for (String suffix : SERVICE_SUFFIXES) { + if (path.endsWith(suffix)) + return path.substring(0, path.length() - suffix.length()); + } + return path; + } + + /** + * Check if the HTTP request was for the /info/refs?service= Git handler. + * + * @param req + * current request. + * @return true if the request is for the /info/refs service. + */ + public static boolean isInfoRefs(HttpServletRequest req) { + return req.getRequestURI().endsWith(INFO_REFS_PATH) + && VALID_SERVICES.contains(req.getParameter("service")); + } + + /** + * Check if the HTTP request path ends with the /git-upload-pack handler. + * + * @param pathOrUri + * path or URI of the request. + * @return true if the request is for the /git-upload-pack handler. + */ + public static boolean isUploadPack(String pathOrUri) { + return pathOrUri != null && pathOrUri.endsWith(UPLOAD_PACK_PATH); + } + + /** + * Check if the HTTP request was for the /git-upload-pack Git handler. + * + * @param req + * current request. + * @return true if the request is for the /git-upload-pack handler. + */ + public static boolean isUploadPack(HttpServletRequest req) { + return isUploadPack(req.getRequestURI()) + && UPLOAD_PACK_REQUEST_TYPE.equals(req.getContentType()); + } + + /** + * Check if the HTTP request was for the /git-receive-pack Git handler. + * + * @param req + * current request. + * @return true if the request is for the /git-receive-pack handler. + */ + public static boolean isReceivePack(HttpServletRequest req) { + String uri = req.getRequestURI(); + return uri != null && uri.endsWith(RECEIVE_PACK_PATH) + && RECEIVE_PACK_REQUEST_TYPE.equals(req.getContentType()); + } + + private GitSmartHttpTools() { + } +} diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/HttpServerText.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/HttpServerText.java index 18743989ba..2342fea3ca 100644 --- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/HttpServerText.java +++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/HttpServerText.java @@ -65,6 +65,7 @@ public class HttpServerText extends TranslationBundle { /***/ public String filterMustNotBeNull; /***/ public String internalErrorDuringReceivePack; /***/ public String internalErrorDuringUploadPack; + /***/ public String internalServerError; /***/ public String internalServerErrorRequestAttributeWasAlreadySet; /***/ public String invalidBoolean; /***/ public String invalidIndex; 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 0c856d4aa5..6af28ba0d3 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 @@ -47,6 +47,10 @@ import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN; import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED; import static javax.servlet.http.HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE; +import static org.eclipse.jgit.http.server.GitSmartHttpTools.RECEIVE_PACK; +import static org.eclipse.jgit.http.server.GitSmartHttpTools.RECEIVE_PACK_REQUEST_TYPE; +import static org.eclipse.jgit.http.server.GitSmartHttpTools.RECEIVE_PACK_RESULT_TYPE; +import static org.eclipse.jgit.http.server.GitSmartHttpTools.sendError; import static org.eclipse.jgit.http.server.ServletUtils.ATTRIBUTE_HANDLER; import static org.eclipse.jgit.http.server.ServletUtils.getInputStream; import static org.eclipse.jgit.http.server.ServletUtils.getRepository; @@ -74,10 +78,6 @@ import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException; /** Server side implementation of smart push over HTTP. */ class ReceivePackServlet extends HttpServlet { - private static final String REQ_TYPE = "application/x-git-receive-pack-request"; - - private static final String RSP_TYPE = "application/x-git-receive-pack-result"; - private static final long serialVersionUID = 1L; static class InfoRefs extends SmartServiceInfoRefs { @@ -85,7 +85,7 @@ class ReceivePackServlet extends HttpServlet { InfoRefs(ReceivePackFactory<HttpServletRequest> receivePackFactory, List<Filter> filters) { - super("git-receive-pack", filters); + super(RECEIVE_PACK, filters); this.receivePackFactory = receivePackFactory; } @@ -129,7 +129,7 @@ class ReceivePackServlet extends HttpServlet { return; } catch (ServiceNotEnabledException e) { - RepositoryFilter.sendError(SC_FORBIDDEN, req, rsp); + sendError(req, rsp, SC_FORBIDDEN); return; } @@ -153,7 +153,7 @@ class ReceivePackServlet extends HttpServlet { @Override public void doPost(final HttpServletRequest req, final HttpServletResponse rsp) throws IOException { - if (!REQ_TYPE.equals(req.getContentType())) { + if (!RECEIVE_PACK_REQUEST_TYPE.equals(req.getContentType())) { rsp.sendError(SC_UNSUPPORTED_MEDIA_TYPE); return; } @@ -161,7 +161,7 @@ class ReceivePackServlet extends HttpServlet { ReceivePack rp = (ReceivePack) req.getAttribute(ATTRIBUTE_HANDLER); try { rp.setBiDirectionalPipe(false); - rsp.setContentType(RSP_TYPE); + rsp.setContentType(RECEIVE_PACK_RESULT_TYPE); final SmartOutputStream out = new SmartOutputStream(req, rsp) { @Override @@ -181,7 +181,7 @@ class ReceivePackServlet extends HttpServlet { getServletContext().log(HttpServerText.get().internalErrorDuringReceivePack, e); if (!rsp.isCommitted()) { rsp.reset(); - rsp.sendError(SC_INTERNAL_SERVER_ERROR); + sendError(req, rsp, SC_INTERNAL_SERVER_ERROR); } return; } diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/RepositoryFilter.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/RepositoryFilter.java index d1bd9024e9..571183682f 100644 --- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/RepositoryFilter.java +++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/RepositoryFilter.java @@ -47,8 +47,8 @@ import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN; import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND; import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED; +import static org.eclipse.jgit.http.server.GitSmartHttpTools.sendError; import static org.eclipse.jgit.http.server.ServletUtils.ATTRIBUTE_REPOSITORY; -import static org.eclipse.jgit.util.HttpSupport.HDR_ACCEPT; import java.io.IOException; import java.text.MessageFormat; @@ -65,7 +65,6 @@ import javax.servlet.http.HttpServletResponse; import org.eclipse.jgit.errors.RepositoryNotFoundException; import org.eclipse.jgit.lib.Repository; -import org.eclipse.jgit.transport.PacketLineOut; import org.eclipse.jgit.transport.resolver.RepositoryResolver; import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException; import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException; @@ -109,23 +108,24 @@ public class RepositoryFilter implements Filter { } public void doFilter(final ServletRequest request, - final ServletResponse rsp, final FilterChain chain) + final ServletResponse response, final FilterChain chain) throws IOException, ServletException { + HttpServletRequest req = (HttpServletRequest) request; + HttpServletResponse res = (HttpServletResponse) response; + if (request.getAttribute(ATTRIBUTE_REPOSITORY) != null) { context.log(MessageFormat.format(HttpServerText.get().internalServerErrorRequestAttributeWasAlreadySet , ATTRIBUTE_REPOSITORY , getClass().getName())); - ((HttpServletResponse) rsp).sendError(SC_INTERNAL_SERVER_ERROR); + sendError(req, res, SC_INTERNAL_SERVER_ERROR); return; } - final HttpServletRequest req = (HttpServletRequest) request; - String name = req.getPathInfo(); while (name != null && 0 < name.length() && name.charAt(0) == '/') name = name.substring(1); if (name == null || name.length() == 0) { - ((HttpServletResponse) rsp).sendError(SC_NOT_FOUND); + sendError(req, res, SC_NOT_FOUND); return; } @@ -133,74 +133,21 @@ public class RepositoryFilter implements Filter { try { db = resolver.open(req, name); } catch (RepositoryNotFoundException e) { - sendError(SC_NOT_FOUND, req, (HttpServletResponse) rsp); + sendError(req, res, SC_NOT_FOUND); return; } catch (ServiceNotEnabledException e) { - sendError(SC_FORBIDDEN, req, (HttpServletResponse) rsp); + sendError(req, res, SC_FORBIDDEN); return; } catch (ServiceNotAuthorizedException e) { - ((HttpServletResponse) rsp).sendError(SC_UNAUTHORIZED); + res.sendError(SC_UNAUTHORIZED); return; } try { request.setAttribute(ATTRIBUTE_REPOSITORY, db); - chain.doFilter(request, rsp); + chain.doFilter(request, response); } finally { request.removeAttribute(ATTRIBUTE_REPOSITORY); db.close(); } } - - static void sendError(int statusCode, HttpServletRequest req, - HttpServletResponse rsp) throws IOException { - String svc = req.getParameter("service"); - - if (req.getRequestURI().endsWith("/info/refs") && isService(svc)) { - // Smart HTTP service request, use an ERR response. - rsp.setContentType("application/x-" + svc + "-advertisement"); - - SmartOutputStream buf = new SmartOutputStream(req, rsp); - PacketLineOut out = new PacketLineOut(buf); - out.writeString("# service=" + svc + "\n"); - out.end(); - out.writeString("ERR " + translate(statusCode)); - buf.close(); - return; - } - - String accept = req.getHeader(HDR_ACCEPT); - if (accept != null && accept.contains(UploadPackServlet.RSP_TYPE)) { - // An upload-pack wants ACK or NAK, return ERR - // and the client will print this instead. - rsp.setContentType(UploadPackServlet.RSP_TYPE); - SmartOutputStream buf = new SmartOutputStream(req, rsp); - PacketLineOut out = new PacketLineOut(buf); - out.writeString("ERR " + translate(statusCode)); - buf.close(); - return; - } - - // Otherwise fail with an HTTP error code instead of an - // application level message. This may not be as pretty - // of a result for the user, but its better than nothing. - // - rsp.sendError(statusCode); - } - - private static boolean isService(String svc) { - return "git-upload-pack".equals(svc) || "git-receive-pack".equals(svc); - } - - private static String translate(int statusCode) { - switch (statusCode) { - case SC_NOT_FOUND: - return HttpServerText.get().repositoryNotFound; - - case SC_FORBIDDEN: - return HttpServerText.get().repositoryAccessForbidden; - - default: - return String.valueOf(statusCode); - } - } } diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/SmartServiceInfoRefs.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/SmartServiceInfoRefs.java index 935867cef3..c0f1f6335b 100644 --- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/SmartServiceInfoRefs.java +++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/SmartServiceInfoRefs.java @@ -44,8 +44,9 @@ package org.eclipse.jgit.http.server; import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN; -import static javax.servlet.http.HttpServletResponse.SC_SERVICE_UNAVAILABLE; import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED; +import static org.eclipse.jgit.http.server.GitSmartHttpTools.infoRefsResultType; +import static org.eclipse.jgit.http.server.GitSmartHttpTools.sendError; import static org.eclipse.jgit.http.server.ServletUtils.ATTRIBUTE_HANDLER; import static org.eclipse.jgit.http.server.ServletUtils.getRepository; @@ -90,17 +91,17 @@ abstract class SmartServiceInfoRefs implements Filter { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { final HttpServletRequest req = (HttpServletRequest) request; - final HttpServletResponse rsp = (HttpServletResponse) response; + final HttpServletResponse res = (HttpServletResponse) response; if (svc.equals(req.getParameter("service"))) { final Repository db = getRepository(req); try { begin(req, db); } catch (ServiceNotAuthorizedException e) { - rsp.sendError(SC_UNAUTHORIZED); + res.sendError(SC_UNAUTHORIZED); return; } catch (ServiceNotEnabledException e) { - rsp.sendError(SC_FORBIDDEN); + sendError(req, res, SC_FORBIDDEN); return; } @@ -120,10 +121,10 @@ abstract class SmartServiceInfoRefs implements Filter { private void service(ServletRequest request, ServletResponse response) throws IOException { final HttpServletRequest req = (HttpServletRequest) request; - final HttpServletResponse rsp = (HttpServletResponse) response; - final SmartOutputStream buf = new SmartOutputStream(req, rsp); + final HttpServletResponse res = (HttpServletResponse) response; + final SmartOutputStream buf = new SmartOutputStream(req, res); try { - rsp.setContentType("application/x-" + svc + "-advertisement"); + res.setContentType(infoRefsResultType(svc)); final PacketLineOut out = new PacketLineOut(buf); out.writeString("# service=" + svc + "\n"); @@ -131,16 +132,16 @@ abstract class SmartServiceInfoRefs implements Filter { advertise(req, new PacketLineOutRefAdvertiser(out)); buf.close(); } catch (ServiceNotAuthorizedException e) { - rsp.sendError(SC_UNAUTHORIZED); + res.sendError(SC_UNAUTHORIZED); } catch (ServiceNotEnabledException e) { - rsp.sendError(SC_FORBIDDEN); + sendError(req, res, SC_FORBIDDEN); } catch (UploadPackMayNotContinueException e) { if (e.isOutput()) buf.close(); else - rsp.sendError(SC_SERVICE_UNAVAILABLE); + sendError(req, res, SC_FORBIDDEN, e.getMessage()); } } diff --git a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/UploadPackServlet.java b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/UploadPackServlet.java index 178473c401..c7891dfc77 100644 --- a/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/UploadPackServlet.java +++ b/org.eclipse.jgit.http.server/src/org/eclipse/jgit/http/server/UploadPackServlet.java @@ -45,9 +45,12 @@ package org.eclipse.jgit.http.server; import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN; import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; -import static javax.servlet.http.HttpServletResponse.SC_SERVICE_UNAVAILABLE; import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED; import static javax.servlet.http.HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE; +import static org.eclipse.jgit.http.server.GitSmartHttpTools.UPLOAD_PACK; +import static org.eclipse.jgit.http.server.GitSmartHttpTools.UPLOAD_PACK_REQUEST_TYPE; +import static org.eclipse.jgit.http.server.GitSmartHttpTools.UPLOAD_PACK_RESULT_TYPE; +import static org.eclipse.jgit.http.server.GitSmartHttpTools.sendError; import static org.eclipse.jgit.http.server.ServletUtils.ATTRIBUTE_HANDLER; import static org.eclipse.jgit.http.server.ServletUtils.getInputStream; import static org.eclipse.jgit.http.server.ServletUtils.getRepository; @@ -76,10 +79,6 @@ import org.eclipse.jgit.transport.resolver.UploadPackFactory; /** Server side implementation of smart fetch over HTTP. */ class UploadPackServlet extends HttpServlet { - private static final String REQ_TYPE = "application/x-git-upload-pack-request"; - - static final String RSP_TYPE = "application/x-git-upload-pack-result"; - private static final long serialVersionUID = 1L; static class InfoRefs extends SmartServiceInfoRefs { @@ -87,7 +86,7 @@ class UploadPackServlet extends HttpServlet { InfoRefs(UploadPackFactory<HttpServletRequest> uploadPackFactory, List<Filter> filters) { - super("git-upload-pack", filters); + super(UPLOAD_PACK, filters); this.uploadPackFactory = uploadPackFactory; } @@ -132,7 +131,7 @@ class UploadPackServlet extends HttpServlet { return; } catch (ServiceNotEnabledException e) { - RepositoryFilter.sendError(SC_FORBIDDEN, req, rsp); + sendError(req, rsp, SC_FORBIDDEN); return; } @@ -156,7 +155,7 @@ class UploadPackServlet extends HttpServlet { @Override public void doPost(final HttpServletRequest req, final HttpServletResponse rsp) throws IOException { - if (!REQ_TYPE.equals(req.getContentType())) { + if (!UPLOAD_PACK_REQUEST_TYPE.equals(req.getContentType())) { rsp.sendError(SC_UNSUPPORTED_MEDIA_TYPE); return; } @@ -164,7 +163,7 @@ class UploadPackServlet extends HttpServlet { UploadPack up = (UploadPack) req.getAttribute(ATTRIBUTE_HANDLER); try { up.setBiDirectionalPipe(false); - rsp.setContentType(RSP_TYPE); + rsp.setContentType(UPLOAD_PACK_RESULT_TYPE); final SmartOutputStream out = new SmartOutputStream(req, rsp) { @Override @@ -178,11 +177,12 @@ class UploadPackServlet extends HttpServlet { } catch (UploadPackMayNotContinueException e) { if (!e.isOutput() && !rsp.isCommitted()) { rsp.reset(); - rsp.sendError(SC_SERVICE_UNAVAILABLE); + sendError(req, rsp, SC_FORBIDDEN, e.getMessage()); } return; } catch (UploadPackInternalServerErrorException e) { + // Special case exception, error message was sent to client. getServletContext().log( HttpServerText.get().internalErrorDuringUploadPack, e.getCause()); @@ -191,7 +191,7 @@ class UploadPackServlet extends HttpServlet { getServletContext().log(HttpServerText.get().internalErrorDuringUploadPack, e); if (!rsp.isCommitted()) { rsp.reset(); - rsp.sendError(SC_INTERNAL_SERVER_ERROR); + sendError(req, rsp, SC_INTERNAL_SERVER_ERROR); } return; } |