- /*
- * Copyright (C) 2009-2010, Google Inc. 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
- * https://www.eclipse.org/org/documents/edl-v10.php.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
- 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_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.consumeRequestBody;
- import static org.eclipse.jgit.http.server.ServletUtils.getInputStream;
- import static org.eclipse.jgit.http.server.ServletUtils.getRepository;
- import static org.eclipse.jgit.util.HttpSupport.HDR_USER_AGENT;
-
- import java.io.IOException;
- import java.text.MessageFormat;
- import java.util.List;
-
- import javax.servlet.Filter;
- import javax.servlet.FilterChain;
- import javax.servlet.FilterConfig;
- import javax.servlet.ServletException;
- import javax.servlet.ServletRequest;
- import javax.servlet.ServletResponse;
- 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;
- import org.eclipse.jgit.lib.Repository;
- import org.eclipse.jgit.transport.InternalHttpServerGlue;
- import org.eclipse.jgit.transport.ReceivePack;
- import org.eclipse.jgit.transport.RefAdvertiser.PacketLineOutRefAdvertiser;
- import org.eclipse.jgit.transport.resolver.ReceivePackFactory;
- import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
- import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
-
- /** Server side implementation of smart push over HTTP. */
- class ReceivePackServlet extends HttpServlet {
- private static final long serialVersionUID = 1L;
-
- static class InfoRefs extends SmartServiceInfoRefs {
- private final ReceivePackFactory<HttpServletRequest> receivePackFactory;
-
- InfoRefs(ReceivePackFactory<HttpServletRequest> receivePackFactory,
- List<Filter> filters) {
- super(RECEIVE_PACK, filters);
- this.receivePackFactory = receivePackFactory;
- }
-
- @Override
- protected void begin(HttpServletRequest req, Repository db)
- throws IOException, ServiceNotEnabledException,
- ServiceNotAuthorizedException {
- ReceivePack rp = receivePackFactory.create(req, db);
- InternalHttpServerGlue.setPeerUserAgent(
- rp,
- req.getHeader(HDR_USER_AGENT));
- req.setAttribute(ATTRIBUTE_HANDLER, rp);
- }
-
- @Override
- protected void advertise(HttpServletRequest req,
- PacketLineOutRefAdvertiser pck) throws IOException,
- ServiceNotEnabledException, ServiceNotAuthorizedException {
- ReceivePack rp = (ReceivePack) req.getAttribute(ATTRIBUTE_HANDLER);
- try {
- rp.sendAdvertisedRefs(pck);
- } finally {
- rp.getRevWalk().close();
- }
- }
- }
-
- static class Factory implements Filter {
- private final ReceivePackFactory<HttpServletRequest> receivePackFactory;
-
- Factory(ReceivePackFactory<HttpServletRequest> receivePackFactory) {
- this.receivePackFactory = receivePackFactory;
- }
-
- @Override
- public void doFilter(ServletRequest request, ServletResponse response,
- FilterChain chain) throws IOException, ServletException {
- HttpServletRequest req = (HttpServletRequest) request;
- HttpServletResponse rsp = (HttpServletResponse) response;
- ReceivePack rp;
- try {
- rp = receivePackFactory.create(req, getRepository(req));
- } catch (ServiceNotAuthorizedException e) {
- rsp.sendError(SC_UNAUTHORIZED, e.getMessage());
- return;
- } catch (ServiceNotEnabledException e) {
- sendError(req, rsp, SC_FORBIDDEN, e.getMessage());
- return;
- }
-
- try {
- req.setAttribute(ATTRIBUTE_HANDLER, rp);
- chain.doFilter(req, rsp);
- } finally {
- req.removeAttribute(ATTRIBUTE_HANDLER);
- }
- }
-
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
- // Nothing.
- }
-
- @Override
- public void destroy() {
- // Nothing.
- }
- }
-
- @Nullable
- private final ReceivePackErrorHandler handler;
-
- ReceivePackServlet(@Nullable ReceivePackErrorHandler handler) {
- this.handler = handler;
- }
-
- /** {@inheritDoc} */
- @Override
- public void doPost(final HttpServletRequest req,
- final HttpServletResponse rsp) throws IOException {
- if (!RECEIVE_PACK_REQUEST_TYPE.equals(req.getContentType())) {
- rsp.sendError(SC_UNSUPPORTED_MEDIA_TYPE);
- return;
- }
-
- SmartOutputStream out = new SmartOutputStream(req, rsp, false) {
- @Override
- public void flush() throws IOException {
- doFlush();
- }
- };
-
- ReceivePack rp = (ReceivePack) req.getAttribute(ATTRIBUTE_HANDLER);
- 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;
- }
- }
- }
-
- private void log(Repository git, Throwable e) {
- getServletContext().log(MessageFormat.format(
- HttpServerText.get().internalErrorDuringReceivePack,
- ServletUtils.identify(git)), e);
- }
- }
|