http: add http.savecookies option to write out HTTP cookies
authorDave Borowitz <dborowitz@google.com>
Tue, 23 Jul 2013 22:40:17 +0000 (15:40 -0700)
committerJunio C Hamano <gitster@pobox.com>
Tue, 30 Jul 2013 16:19:04 +0000 (09:19 -0700)
HTTP servers may send Set-Cookie headers in a response and expect them
to be set on subsequent requests. By default, libcurl behavior is to
store such cookies in memory and reuse them across requests within a
single session. However, it may also make sense, depending on the
server and the cookies, to store them across sessions. Provide users
an option to enable this behavior, writing cookies out to the same
file specified in http.cookiefile.

Signed-off-by: Dave Borowitz <dborowitz@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Documentation/config.txt
http.c
t/lib-httpd/apache.conf
t/t5551-http-fetch.sh
index e0b923f428094f1303084778bee7ab9e502709a4..e935447d9448de3102c8e909d1b3b7511a190778 100644 (file)
@@ -1456,7 +1456,11 @@ http.cookiefile::
        of the file to read cookies from should be plain HTTP headers or
        the Netscape/Mozilla cookie file format (see linkgit:curl[1]).
        NOTE that the file specified with http.cookiefile is only used as
-       input. No cookies will be stored in the file.
+       input unless http.saveCookies is set.
+
+http.savecookies::
+       If set, store cookies received during requests to the file specified by
+       http.cookiefile. Has no effect if http.cookiefile is unset.
 
 http.sslVerify::
        Whether to verify the SSL certificate when fetching or pushing
diff --git a/http.c b/http.c
index 2d086aedfac9a8ea384c53f3b1963149b880ed31..2fbf986231d0e23b1d2c15c8d9121f1129139097 100644 (file)
--- a/http.c
+++ b/http.c
@@ -45,6 +45,7 @@ static long curl_low_speed_time = -1;
 static int curl_ftp_no_epsv;
 static const char *curl_http_proxy;
 static const char *curl_cookie_file;
+static int curl_save_cookies;
 static struct credential http_auth = CREDENTIAL_INIT;
 static int http_proactive_auth;
 static const char *user_agent;
@@ -200,6 +201,10 @@ static int http_options(const char *var, const char *value, void *cb)
 
        if (!strcmp("http.cookiefile", var))
                return git_config_string(&curl_cookie_file, var, value);
+       if (!strcmp("http.savecookies", var)) {
+               curl_save_cookies = git_config_bool(var, value);
+               return 0;
+       }
 
        if (!strcmp("http.postbuffer", var)) {
                http_post_buffer = git_config_int(var, value);
@@ -513,6 +518,8 @@ struct active_request_slot *get_active_slot(void)
        slot->callback_data = NULL;
        slot->callback_func = NULL;
        curl_easy_setopt(slot->curl, CURLOPT_COOKIEFILE, curl_cookie_file);
+       if (curl_save_cookies)
+               curl_easy_setopt(slot->curl, CURLOPT_COOKIEJAR, curl_cookie_file);
        curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, pragma_header);
        curl_easy_setopt(slot->curl, CURLOPT_ERRORBUFFER, curl_errorstr);
        curl_easy_setopt(slot->curl, CURLOPT_CUSTOMREQUEST, NULL);
index dd17e3a09d728a08c8038c5ce8187ea63112cdf3..397c4804010c7566a4f969822c413e46fe817e53 100644 (file)
@@ -22,6 +22,9 @@ ErrorLog error.log
 <IfModule !mod_version.c>
        LoadModule version_module modules/mod_version.so
 </IfModule>
+<IfModule !mod_headers.c>
+       LoadModule headers_module modules/mod_headers.so
+</IfModule>
 
 <IfVersion < 2.4>
 LockFile accept.lock
@@ -87,6 +90,11 @@ Alias /auth/dumb/ www/auth/dumb/
        SetEnv GIT_HTTP_EXPORT_ALL
        SetEnv GIT_NAMESPACE ns
 </LocationMatch>
+<LocationMatch /smart_cookies/>
+       SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH}
+       SetEnv GIT_HTTP_EXPORT_ALL
+       Header set Set-Cookie name=value
+</LocationMatch>
 ScriptAliasMatch /smart_*[^/]*/(.*) ${GIT_EXEC_PATH}/git-http-backend/$1
 ScriptAlias /broken_smart/ broken-smart-http.sh/
 <Directory ${GIT_EXEC_PATH}>
index 55a866af803452e164e2c11c421b1e63f62d2e1e..287d22b510babfcff7b46f7a0b422a209f9d2cb5 100755 (executable)
@@ -187,6 +187,24 @@ test_expect_success 'dumb clone via http-backend respects namespace' '
        test_cmp expect actual
 '
 
+cat >cookies.txt <<EOF
+127.0.0.1      FALSE   /smart_cookies/ FALSE   0       othername       othervalue
+EOF
+cat >expect_cookies.txt <<EOF
+# Netscape HTTP Cookie File
+# http://curl.haxx.se/docs/http-cookies.html
+# This file was generated by libcurl! Edit at your own risk.
+
+127.0.0.1      FALSE   /smart_cookies/ FALSE   0       othername       othervalue
+127.0.0.1      FALSE   /smart_cookies/repo.git/info/   FALSE   0       name    value
+EOF
+test_expect_success 'cookies stored in http.cookiefile when http.savecookies set' '
+       git config http.cookiefile cookies.txt &&
+       git config http.savecookies true &&
+       git ls-remote $HTTPD_URL/smart_cookies/repo.git master &&
+       test_cmp expect_cookies.txt cookies.txt
+'
+
 test -n "$GIT_TEST_LONG" && test_set_prereq EXPENSIVE
 
 test_expect_success EXPENSIVE 'create 50,000 tags in the repo' '