summaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit.http.test/tst
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jgit.http.test/tst')
-rw-r--r--org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientSmartServerTest.java21
-rw-r--r--org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerSslTest.java280
-rw-r--r--org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java311
3 files changed, 550 insertions, 62 deletions
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientSmartServerTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientSmartServerTest.java
index 06bfd7988b..727f9bab00 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientSmartServerTest.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/DumbClientSmartServerTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010, Google Inc.
+ * Copyright (C) 2010, 2017 Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
@@ -60,12 +60,9 @@ import java.util.Collection;
import java.util.List;
import java.util.Map;
-import javax.servlet.http.HttpServletRequest;
-
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jgit.errors.NotSupportedException;
-import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.http.server.GitServlet;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.junit.http.AccessEvent;
@@ -84,8 +81,6 @@ import org.eclipse.jgit.transport.URIish;
import org.eclipse.jgit.transport.http.HttpConnectionFactory;
import org.eclipse.jgit.transport.http.JDKHttpConnectionFactory;
import org.eclipse.jgit.transport.http.apache.HttpClientConnectionFactory;
-import org.eclipse.jgit.transport.resolver.RepositoryResolver;
-import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -124,19 +119,7 @@ public class DumbClientSmartServerTest extends HttpTestCase {
ServletContextHandler app = server.addContext("/git");
GitServlet gs = new GitServlet();
- gs.setRepositoryResolver(new RepositoryResolver<HttpServletRequest>() {
- @Override
- public Repository open(HttpServletRequest req, String name)
- throws RepositoryNotFoundException,
- ServiceNotEnabledException {
- if (!name.equals(srcName))
- throw new RepositoryNotFoundException(name);
-
- final Repository db = src.getRepository();
- db.incrementOpen();
- return db;
- }
- });
+ gs.setRepositoryResolver(new TestRepositoryResolver(src, srcName));
app.addServlet(new ServletHolder(gs), "/*");
server.setUp();
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerSslTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerSslTest.java
new file mode 100644
index 0000000000..42064581c9
--- /dev/null
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerSslTest.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright (C) 2017 Thomas Wolf <thomas.wolf@paranor.ch>
+ * 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.test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.List;
+
+import javax.servlet.DispatcherType;
+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.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.servlet.FilterHolder;
+import org.eclipse.jetty.servlet.ServletContextHandler;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jgit.errors.TransportException;
+import org.eclipse.jgit.http.server.GitServlet;
+import org.eclipse.jgit.junit.TestRepository;
+import org.eclipse.jgit.junit.http.AccessEvent;
+import org.eclipse.jgit.junit.http.AppServer;
+import org.eclipse.jgit.junit.http.HttpTestCase;
+import org.eclipse.jgit.lib.ConfigConstants;
+import org.eclipse.jgit.lib.NullProgressMonitor;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevBlob;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.storage.file.FileBasedConfig;
+import org.eclipse.jgit.transport.HttpTransport;
+import org.eclipse.jgit.transport.Transport;
+import org.eclipse.jgit.transport.URIish;
+import org.eclipse.jgit.transport.http.HttpConnectionFactory;
+import org.eclipse.jgit.transport.http.JDKHttpConnectionFactory;
+import org.eclipse.jgit.transport.http.apache.HttpClientConnectionFactory;
+import org.eclipse.jgit.util.FS;
+import org.eclipse.jgit.util.HttpSupport;
+import org.eclipse.jgit.util.SystemReader;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class SmartClientSmartServerSslTest extends HttpTestCase {
+
+ private URIish remoteURI;
+
+ private URIish secureURI;
+
+ private RevBlob A_txt;
+
+ private RevCommit A, B;
+
+ @Parameters
+ public static Collection<Object[]> data() {
+ // run all tests with both connection factories we have
+ return Arrays.asList(new Object[][] {
+ { new JDKHttpConnectionFactory() },
+ { new HttpClientConnectionFactory() } });
+ }
+
+ public SmartClientSmartServerSslTest(HttpConnectionFactory cf) {
+ HttpTransport.setConnectionFactory(cf);
+ }
+
+ @Override
+ protected AppServer createServer() {
+ return new AppServer(0, 0);
+ }
+
+ @Override
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+
+ final TestRepository<Repository> src = createTestRepository();
+ final String srcName = src.getRepository().getDirectory().getName();
+ src.getRepository()
+ .getConfig()
+ .setBoolean(ConfigConstants.CONFIG_CORE_SECTION, null,
+ ConfigConstants.CONFIG_KEY_LOGALLREFUPDATES, true);
+
+ GitServlet gs = new GitServlet();
+
+ ServletContextHandler app = addNormalContext(gs, src, srcName);
+
+ server.setUp();
+
+ remoteURI = toURIish(app, srcName);
+ secureURI = new URIish(rewriteUrl(remoteURI.toString(), "https",
+ server.getSecurePort()));
+
+ A_txt = src.blob("A");
+ A = src.commit().add("A_txt", A_txt).create();
+ B = src.commit().parent(A).add("A_txt", "C").add("B", "B").create();
+ src.update(master, B);
+
+ src.update("refs/garbage/a/very/long/ref/name/to/compress", B);
+
+ FileBasedConfig userConfig = SystemReader.getInstance()
+ .openUserConfig(null, FS.DETECTED);
+ userConfig.setBoolean("http", null, "sslVerify", false);
+ userConfig.save();
+ }
+
+ private ServletContextHandler addNormalContext(GitServlet gs, TestRepository<Repository> src, String srcName) {
+ ServletContextHandler app = server.addContext("/git");
+ app.addFilter(new FilterHolder(new Filter() {
+
+ @Override
+ public void init(FilterConfig filterConfig)
+ throws ServletException {
+ // empty
+ }
+
+ // Redirects http to https for requests containing "/https/".
+ @Override
+ public void doFilter(ServletRequest request,
+ ServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
+ final HttpServletResponse httpServletResponse = (HttpServletResponse) response;
+ final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+ final StringBuffer fullUrl = httpServletRequest.getRequestURL();
+ if (httpServletRequest.getQueryString() != null) {
+ fullUrl.append("?")
+ .append(httpServletRequest.getQueryString());
+ }
+ String urlString = rewriteUrl(fullUrl.toString(), "https",
+ server.getSecurePort());
+ httpServletResponse
+ .setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
+ httpServletResponse.setHeader(HttpSupport.HDR_LOCATION,
+ urlString.replace("/https/", "/"));
+ }
+
+ @Override
+ public void destroy() {
+ // empty
+ }
+ }), "/https/*", EnumSet.of(DispatcherType.REQUEST));
+ app.addFilter(new FilterHolder(new Filter() {
+
+ @Override
+ public void init(FilterConfig filterConfig)
+ throws ServletException {
+ // empty
+ }
+
+ // Redirects https back to http for requests containing "/back/".
+ @Override
+ public void doFilter(ServletRequest request,
+ ServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
+ final HttpServletResponse httpServletResponse = (HttpServletResponse) response;
+ final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+ final StringBuffer fullUrl = httpServletRequest.getRequestURL();
+ if (httpServletRequest.getQueryString() != null) {
+ fullUrl.append("?")
+ .append(httpServletRequest.getQueryString());
+ }
+ String urlString = rewriteUrl(fullUrl.toString(), "http",
+ server.getPort());
+ httpServletResponse
+ .setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
+ httpServletResponse.setHeader(HttpSupport.HDR_LOCATION,
+ urlString.replace("/back/", "/"));
+ }
+
+ @Override
+ public void destroy() {
+ // empty
+ }
+ }), "/back/*", EnumSet.of(DispatcherType.REQUEST));
+ gs.setRepositoryResolver(new TestRepositoryResolver(src, srcName));
+ app.addServlet(new ServletHolder(gs), "/*");
+ return app;
+ }
+
+ @Test
+ public void testInitialClone_ViaHttps() throws Exception {
+ Repository dst = createBareRepository();
+ assertFalse(dst.hasObject(A_txt));
+
+ try (Transport t = Transport.open(dst, secureURI)) {
+ t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
+ }
+ assertTrue(dst.hasObject(A_txt));
+ assertEquals(B, dst.exactRef(master).getObjectId());
+ fsck(dst, B);
+
+ List<AccessEvent> requests = getRequests();
+ assertEquals(2, requests.size());
+ }
+
+ @Test
+ public void testInitialClone_RedirectToHttps() throws Exception {
+ Repository dst = createBareRepository();
+ assertFalse(dst.hasObject(A_txt));
+
+ URIish cloneFrom = extendPath(remoteURI, "/https");
+ try (Transport t = Transport.open(dst, cloneFrom)) {
+ t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
+ }
+ assertTrue(dst.hasObject(A_txt));
+ assertEquals(B, dst.exactRef(master).getObjectId());
+ fsck(dst, B);
+
+ List<AccessEvent> requests = getRequests();
+ assertEquals(3, requests.size());
+ }
+
+ @Test
+ public void testInitialClone_RedirectBackToHttp() throws Exception {
+ Repository dst = createBareRepository();
+ assertFalse(dst.hasObject(A_txt));
+
+ URIish cloneFrom = extendPath(secureURI, "/back");
+ try (Transport t = Transport.open(dst, cloneFrom)) {
+ t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
+ fail("Should have failed (redirect from https to http)");
+ } catch (TransportException e) {
+ assertTrue(e.getMessage().contains("not allowed"));
+ }
+ }
+
+}
diff --git a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java
index ed223c96ef..8cadca5235 100644
--- a/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java
+++ b/org.eclipse.jgit.http.test/tst/org/eclipse/jgit/http/test/SmartClientSmartServerTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010, Google Inc.
+ * Copyright (C) 2010, 2017 Google Inc.
* and other copyright owners as documented in the project's IP log.
*
* This program and the accompanying materials are made available
@@ -57,17 +57,21 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
+import java.text.MessageFormat;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
+import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
@@ -78,7 +82,6 @@ import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jgit.errors.RemoteRepositoryException;
-import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.errors.TransportException;
import org.eclipse.jgit.http.server.GitServlet;
import org.eclipse.jgit.internal.JGitText;
@@ -101,6 +104,7 @@ import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.StoredConfig;
import org.eclipse.jgit.revwalk.RevBlob;
import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.transport.FetchConnection;
import org.eclipse.jgit.transport.HttpTransport;
import org.eclipse.jgit.transport.RemoteRefUpdate;
@@ -110,9 +114,9 @@ import org.eclipse.jgit.transport.URIish;
import org.eclipse.jgit.transport.http.HttpConnectionFactory;
import org.eclipse.jgit.transport.http.JDKHttpConnectionFactory;
import org.eclipse.jgit.transport.http.apache.HttpClientConnectionFactory;
-import org.eclipse.jgit.transport.resolver.RepositoryResolver;
-import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
+import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.HttpSupport;
+import org.eclipse.jgit.util.SystemReader;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -184,7 +188,52 @@ public class SmartClientSmartServerTest extends HttpTestCase {
private ServletContextHandler addNormalContext(GitServlet gs, TestRepository<Repository> src, String srcName) {
ServletContextHandler app = server.addContext("/git");
- gs.setRepositoryResolver(new TestRepoResolver(src, srcName));
+ app.addFilter(new FilterHolder(new Filter() {
+
+ @Override
+ public void init(FilterConfig filterConfig)
+ throws ServletException {
+ // empty
+ }
+
+ // Does an internal forward for GET requests containing "/post/",
+ // and issues a 301 redirect on POST requests for such URLs. Used
+ // in the POST redirect tests.
+ @Override
+ public void doFilter(ServletRequest request,
+ ServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
+ final HttpServletResponse httpServletResponse = (HttpServletResponse) response;
+ final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+ final StringBuffer fullUrl = httpServletRequest.getRequestURL();
+ if (httpServletRequest.getQueryString() != null) {
+ fullUrl.append("?")
+ .append(httpServletRequest.getQueryString());
+ }
+ String urlString = fullUrl.toString();
+ if ("POST".equalsIgnoreCase(httpServletRequest.getMethod())) {
+ httpServletResponse.setStatus(
+ HttpServletResponse.SC_MOVED_PERMANENTLY);
+ httpServletResponse.setHeader(HttpSupport.HDR_LOCATION,
+ urlString.replace("/post/", "/"));
+ } else {
+ String path = httpServletRequest.getPathInfo();
+ path = path.replace("/post/", "/");
+ if (httpServletRequest.getQueryString() != null) {
+ path += '?' + httpServletRequest.getQueryString();
+ }
+ RequestDispatcher dispatcher = httpServletRequest
+ .getRequestDispatcher(path);
+ dispatcher.forward(httpServletRequest, httpServletResponse);
+ }
+ }
+
+ @Override
+ public void destroy() {
+ // empty
+ }
+ }), "/post/*", EnumSet.of(DispatcherType.REQUEST));
+ gs.setRepositoryResolver(new TestRepositoryResolver(src, srcName));
app.addServlet(new ServletHolder(gs), "/*");
return app;
}
@@ -228,6 +277,12 @@ public class SmartClientSmartServerTest extends HttpTestCase {
ServletContextHandler redirect = server.addContext("/redirect");
redirect.addFilter(new FilterHolder(new Filter() {
+ // Enables tests for different codes, and for multiple redirects.
+ // First parameter is the number of redirects, second one is the
+ // redirect status code that should be used
+ private Pattern responsePattern = Pattern
+ .compile("/response/(\\d+)/(30[1237])/");
+
@Override
public void init(FilterConfig filterConfig)
throws ServletException {
@@ -245,10 +300,43 @@ public class SmartClientSmartServerTest extends HttpTestCase {
fullUrl.append("?")
.append(httpServletRequest.getQueryString());
}
- httpServletResponse
- .setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
+ String urlString = fullUrl.toString();
+ if (urlString.contains("/loop/")) {
+ urlString = urlString.replace("/loop/", "/loop/x/");
+ if (urlString.contains("/loop/x/x/x/x/x/x/x/x/")) {
+ // Go back to initial.
+ urlString = urlString.replace("/loop/x/x/x/x/x/x/x/x/",
+ "/loop/");
+ }
+ httpServletResponse.setStatus(
+ HttpServletResponse.SC_MOVED_TEMPORARILY);
+ httpServletResponse.setHeader(HttpSupport.HDR_LOCATION,
+ urlString);
+ return;
+ }
+ int responseCode = HttpServletResponse.SC_MOVED_PERMANENTLY;
+ int nofRedirects = 0;
+ Matcher matcher = responsePattern.matcher(urlString);
+ if (matcher.find()) {
+ nofRedirects = Integer
+ .parseUnsignedInt(matcher.group(1));
+ responseCode = Integer.parseUnsignedInt(matcher.group(2));
+ if (--nofRedirects <= 0) {
+ urlString = fullUrl.substring(0, matcher.start()) + '/'
+ + fullUrl.substring(matcher.end());
+ } else {
+ urlString = fullUrl.substring(0, matcher.start())
+ + "/response/" + nofRedirects + "/"
+ + responseCode + '/'
+ + fullUrl.substring(matcher.end());
+ }
+ }
+ httpServletResponse.setStatus(responseCode);
+ if (nofRedirects <= 0) {
+ urlString = urlString.replace("/redirect", "/git");
+ }
httpServletResponse.setHeader(HttpSupport.HDR_LOCATION,
- fullUrl.toString().replace("/redirect", "/git"));
+ urlString);
}
@Override
@@ -373,12 +461,17 @@ public class SmartClientSmartServerTest extends HttpTestCase {
.getResponseHeader(HDR_CONTENT_TYPE));
}
- @Test
- public void testInitialClone_RedirectSmall() throws Exception {
+ private void initialClone_Redirect(int nofRedirects, int code)
+ throws Exception {
Repository dst = createBareRepository();
assertFalse(dst.hasObject(A_txt));
- try (Transport t = Transport.open(dst, redirectURI)) {
+ URIish cloneFrom = redirectURI;
+ if (code != 301 || nofRedirects > 1) {
+ cloneFrom = extendPath(cloneFrom,
+ "/response/" + nofRedirects + "/" + code);
+ }
+ try (Transport t = Transport.open(dst, cloneFrom)) {
t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
}
@@ -387,12 +480,15 @@ public class SmartClientSmartServerTest extends HttpTestCase {
fsck(dst, B);
List<AccessEvent> requests = getRequests();
- assertEquals(4, requests.size());
+ assertEquals(2 + nofRedirects, requests.size());
- AccessEvent firstRedirect = requests.get(0);
- assertEquals(301, firstRedirect.getStatus());
+ int n = 0;
+ while (n < nofRedirects) {
+ AccessEvent redirect = requests.get(n++);
+ assertEquals(code, redirect.getStatus());
+ }
- AccessEvent info = requests.get(1);
+ AccessEvent info = requests.get(n++);
assertEquals("GET", info.getMethod());
assertEquals(join(remoteURI, "info/refs"), info.getPath());
assertEquals(1, info.getParameters().size());
@@ -402,10 +498,130 @@ public class SmartClientSmartServerTest extends HttpTestCase {
info.getResponseHeader(HDR_CONTENT_TYPE));
assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
- AccessEvent secondRedirect = requests.get(2);
- assertEquals(301, secondRedirect.getStatus());
+ AccessEvent service = requests.get(n++);
+ assertEquals("POST", service.getMethod());
+ assertEquals(join(remoteURI, "git-upload-pack"), service.getPath());
+ assertEquals(0, service.getParameters().size());
+ assertNotNull("has content-length",
+ service.getRequestHeader(HDR_CONTENT_LENGTH));
+ assertNull("not chunked",
+ service.getRequestHeader(HDR_TRANSFER_ENCODING));
+
+ assertEquals(200, service.getStatus());
+ assertEquals("application/x-git-upload-pack-result",
+ service.getResponseHeader(HDR_CONTENT_TYPE));
+ }
+
+ @Test
+ public void testInitialClone_Redirect301Small() throws Exception {
+ initialClone_Redirect(1, 301);
+ }
+
+ @Test
+ public void testInitialClone_Redirect302Small() throws Exception {
+ initialClone_Redirect(1, 302);
+ }
+
+ @Test
+ public void testInitialClone_Redirect303Small() throws Exception {
+ initialClone_Redirect(1, 303);
+ }
+
+ @Test
+ public void testInitialClone_Redirect307Small() throws Exception {
+ initialClone_Redirect(1, 307);
+ }
+
+ @Test
+ public void testInitialClone_RedirectMultiple() throws Exception {
+ initialClone_Redirect(4, 302);
+ }
+
+ @Test
+ public void testInitialClone_RedirectMax() throws Exception {
+ FileBasedConfig userConfig = SystemReader.getInstance()
+ .openUserConfig(null, FS.DETECTED);
+ userConfig.setInt("http", null, "maxRedirects", 4);
+ userConfig.save();
+ initialClone_Redirect(4, 302);
+ }
+
+ @Test
+ public void testInitialClone_RedirectTooOften() throws Exception {
+ FileBasedConfig userConfig = SystemReader.getInstance()
+ .openUserConfig(null, FS.DETECTED);
+ userConfig.setInt("http", null, "maxRedirects", 3);
+ userConfig.save();
+ Repository dst = createBareRepository();
+ assertFalse(dst.hasObject(A_txt));
+
+ URIish cloneFrom = extendPath(redirectURI, "/response/4/302");
+ String remoteUri = cloneFrom.toString();
+ try (Transport t = Transport.open(dst, cloneFrom)) {
+ t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
+ fail("Should have failed (too many redirects)");
+ } catch (TransportException e) {
+ String expectedMessageBegin = MessageFormat.format(
+ JGitText.get().redirectLimitExceeded, remoteUri, "3",
+ remoteUri.replace("/4/", "/1/") + '/', "");
+ String message = e.getMessage();
+ if (message.length() > expectedMessageBegin.length()) {
+ message = message.substring(0, expectedMessageBegin.length());
+ }
+ assertEquals(expectedMessageBegin, message);
+ }
+ }
+
+ @Test
+ public void testInitialClone_RedirectLoop() throws Exception {
+ Repository dst = createBareRepository();
+ assertFalse(dst.hasObject(A_txt));
+
+ URIish cloneFrom = extendPath(redirectURI, "/loop");
+ try (Transport t = Transport.open(dst, cloneFrom)) {
+ t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
+ fail("Should have failed (redirect loop)");
+ } catch (TransportException e) {
+ assertTrue(e.getMessage().contains("redirected more than"));
+ }
+ }
+
+ @Test
+ public void testInitialClone_RedirectOnPostAllowed() throws Exception {
+ FileBasedConfig userConfig = SystemReader.getInstance()
+ .openUserConfig(null, FS.DETECTED);
+ userConfig.setString("http", null, "followRedirects", "true");
+ userConfig.save();
+ Repository dst = createBareRepository();
+ assertFalse(dst.hasObject(A_txt));
+
+ URIish cloneFrom = extendPath(remoteURI, "/post");
+ try (Transport t = Transport.open(dst, cloneFrom)) {
+ t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
+ }
+
+ assertTrue(dst.hasObject(A_txt));
+ assertEquals(B, dst.exactRef(master).getObjectId());
+ fsck(dst, B);
+
+ List<AccessEvent> requests = getRequests();
+ assertEquals(3, requests.size());
+
+ AccessEvent info = requests.get(0);
+ assertEquals("GET", info.getMethod());
+ assertEquals(join(cloneFrom, "info/refs"), info.getPath());
+ assertEquals(1, info.getParameters().size());
+ assertEquals("git-upload-pack", info.getParameter("service"));
+ assertEquals(200, info.getStatus());
+ assertEquals("application/x-git-upload-pack-advertisement",
+ info.getResponseHeader(HDR_CONTENT_TYPE));
+ assertEquals("gzip", info.getResponseHeader(HDR_CONTENT_ENCODING));
+
+ AccessEvent redirect = requests.get(1);
+ assertEquals("POST", redirect.getMethod());
+ assertEquals(301, redirect.getStatus());
- AccessEvent service = requests.get(3);
+ AccessEvent service = requests.get(2);
assertEquals("POST", service.getMethod());
assertEquals(join(remoteURI, "git-upload-pack"), service.getPath());
assertEquals(0, service.getParameters().size());
@@ -420,6 +636,39 @@ public class SmartClientSmartServerTest extends HttpTestCase {
}
@Test
+ public void testInitialClone_RedirectOnPostForbidden() throws Exception {
+ Repository dst = createBareRepository();
+ assertFalse(dst.hasObject(A_txt));
+
+ URIish cloneFrom = extendPath(remoteURI, "/post");
+ try (Transport t = Transport.open(dst, cloneFrom)) {
+ t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
+ fail("Should have failed (redirect on POST)");
+ } catch (TransportException e) {
+ assertTrue(e.getMessage().contains("301"));
+ }
+ }
+
+ @Test
+ public void testInitialClone_RedirectForbidden() throws Exception {
+ FileBasedConfig userConfig = SystemReader.getInstance()
+ .openUserConfig(null, FS.DETECTED);
+ userConfig.setString("http", null, "followRedirects", "false");
+ userConfig.save();
+
+ Repository dst = createBareRepository();
+ assertFalse(dst.hasObject(A_txt));
+
+ try (Transport t = Transport.open(dst, redirectURI)) {
+ t.fetch(NullProgressMonitor.INSTANCE, mirror(master));
+ fail("Should have failed (redirects forbidden)");
+ } catch (TransportException e) {
+ assertTrue(
+ e.getMessage().contains("http.followRedirects is false"));
+ }
+ }
+
+ @Test
public void testFetch_FewLocalCommits() throws Exception {
// Bootstrap by doing the clone.
//
@@ -619,7 +868,7 @@ public class SmartClientSmartServerTest extends HttpTestCase {
ServletContextHandler app = noRefServer.addContext("/git");
GitServlet gs = new GitServlet();
- gs.setRepositoryResolver(new TestRepoResolver(repo, repoName));
+ gs.setRepositoryResolver(new TestRepositoryResolver(repo, repoName));
app.addServlet(new ServletHolder(gs), "/*");
noRefServer.setUp();
@@ -822,28 +1071,4 @@ public class SmartClientSmartServerTest extends HttpTestCase {
cfg.save();
}
- private final class TestRepoResolver
- implements RepositoryResolver<HttpServletRequest> {
-
- private final TestRepository<Repository> repo;
-
- private final String repoName;
-
- private TestRepoResolver(TestRepository<Repository> repo,
- String repoName) {
- this.repo = repo;
- this.repoName = repoName;
- }
-
- @Override
- public Repository open(HttpServletRequest req, String name)
- throws RepositoryNotFoundException, ServiceNotEnabledException {
- if (!name.equals(repoName))
- throw new RepositoryNotFoundException(name);
-
- Repository db = repo.getRepository();
- db.incrementOpen();
- return db;
- }
- }
}