Commit 41a6de289fecbec426d2d977c4d02da5456701ac

Ben Straub 2013-10-02T14:45:57

HTTP: handle "relative" redirects

diff --git a/src/netops.c b/src/netops.c
index 3257e77..7a61ef8 100644
--- a/src/netops.c
+++ b/src/netops.c
@@ -609,6 +609,9 @@ int gitno_connection_data_from_url(
 		data->use_ssl = true;
 	}
 
+	if (url[0] == '/')
+		default_port = data->use_ssl ? "443" : "80";
+
 	if (!default_port) {
 		giterr_set(GITERR_NET, "Unrecognized URL prefix");
 		goto cleanup;
@@ -618,6 +621,13 @@ int gitno_connection_data_from_url(
 		&data->host, &data->port, &data->user, &data->pass,
 		url, default_port);
 
+	if (url[0] == '/') {
+		/* Relative redirect; reuse original host name and port */
+		git__free(data->host);
+		data->host = original_host;
+		original_host = NULL;
+	}
+
 	if (!error) {
 		const char *path = strchr(url, '/');
 		size_t pathlen = strlen(path);
diff --git a/tests-clar/network/urlparse.c b/tests-clar/network/urlparse.c
index 8892781..274d7e9 100644
--- a/tests-clar/network/urlparse.c
+++ b/tests-clar/network/urlparse.c
@@ -125,6 +125,34 @@ void test_network_urlparse__connection_data_http_downgrade(void)
 			-1);
 }
 
+void test_network_urlparse__connection_data_relative_redirect(void)
+{
+	cl_git_pass(gitno_connection_data_from_url(&conndata,
+				"http://foo.com/bar/baz/biff", NULL));
+	cl_git_pass(gitno_connection_data_from_url(&conndata,
+				"/zap/baz/biff?bam", NULL));
+	cl_assert_equal_s(conndata.host, "foo.com");
+	cl_assert_equal_s(conndata.port, "80");
+	cl_assert_equal_s(conndata.path, "/zap/baz/biff?bam");
+	cl_assert_equal_p(conndata.user, NULL);
+	cl_assert_equal_p(conndata.pass, NULL);
+	cl_assert_equal_i(conndata.use_ssl, false);
+}
+
+void test_network_urlparse__connection_data_relative_redirect_ssl(void)
+{
+	cl_git_pass(gitno_connection_data_from_url(&conndata,
+				"https://foo.com/bar/baz/biff", NULL));
+	cl_git_pass(gitno_connection_data_from_url(&conndata,
+				"/zap/baz/biff?bam", NULL));
+	cl_assert_equal_s(conndata.host, "foo.com");
+	cl_assert_equal_s(conndata.port, "443");
+	cl_assert_equal_s(conndata.path, "/zap/baz/biff?bam");
+	cl_assert_equal_p(conndata.user, NULL);
+	cl_assert_equal_p(conndata.pass, NULL);
+	cl_assert_equal_i(conndata.use_ssl, true);
+}
+
 /* Run this under valgrind */
 void test_network_urlparse__connection_data_cleanup(void)
 {