From: Junio C Hamano Date: Mon, 15 Jul 2013 17:36:01 +0000 (-0700) Subject: Merge branch 'bc/http-keep-memory-given-to-curl' into maint X-Git-Tag: v1.8.3.3~2 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/29b2f0565a1e3fdd6ef40d6e12e211757071ef56?ds=inline;hp=-c Merge branch 'bc/http-keep-memory-given-to-curl' into maint Older cURL wanted piece of memory we call it with to be stable, but we updated the auth material after handing it to a call. * bc/http-keep-memory-given-to-curl: http.c: don't rewrite the user:passwd string multiple times --- 29b2f0565a1e3fdd6ef40d6e12e211757071ef56 diff --combined http.c index 92aba59082,c02246a78b..2d086aedfa --- a/http.c +++ b/http.c @@@ -5,7 -5,6 +5,7 @@@ #include "url.h" #include "credential.h" #include "version.h" +#include "pkt-line.h" int active_requests; int http_is_verbose; @@@ -31,7 -30,6 +31,7 @@@ static CURL *curl_default char curl_errorstr[CURL_ERROR_SIZE]; static int curl_ssl_verify = -1; +static int curl_ssl_try; static const char *ssl_cert; #if LIBCURL_VERSION_NUM >= 0x070903 static const char *ssl_key; @@@ -164,10 -162,6 +164,10 @@@ static int http_options(const char *var ssl_cert_password_required = 1; return 0; } + if (!strcmp("http.ssltry", var)) { + curl_ssl_try = git_config_bool(var, value); + return 0; + } if (!strcmp("http.minsessions", var)) { min_curl_sessions = git_config_int(var, value); #ifndef USE_CURL_MULTI @@@ -228,9 -222,15 +228,15 @@@ static void init_curl_http_auth(CURL *r #else { static struct strbuf up = STRBUF_INIT; - strbuf_reset(&up); - strbuf_addf(&up, "%s:%s", - http_auth.username, http_auth.password); + /* + * Note that we assume we only ever have a single set of + * credentials in a given program run, so we do not have + * to worry about updating this buffer, only setting its + * initial value. + */ + if (!up.len) + strbuf_addf(&up, "%s:%s", + http_auth.username, http_auth.password); curl_easy_setopt(result, CURLOPT_USERPWD, up.buf); } #endif @@@ -287,6 -287,7 +293,6 @@@ static CURL *get_curl_handle(void #endif if (ssl_cainfo != NULL) curl_easy_setopt(result, CURLOPT_CAINFO, ssl_cainfo); - curl_easy_setopt(result, CURLOPT_FAILONERROR, 1); if (curl_low_speed_limit > 0 && curl_low_speed_time > 0) { curl_easy_setopt(result, CURLOPT_LOW_SPEED_LIMIT, @@@ -311,11 -312,6 +317,11 @@@ if (curl_ftp_no_epsv) curl_easy_setopt(result, CURLOPT_FTP_USE_EPSV, 0); +#ifdef CURLOPT_USE_SSL + if (curl_ssl_try) + curl_easy_setopt(result, CURLOPT_USE_SSL, CURLUSESSL_TRY); +#endif + if (curl_http_proxy) { curl_easy_setopt(result, CURLOPT_PROXY, curl_http_proxy); curl_easy_setopt(result, CURLOPT_PROXYAUTH, CURLAUTH_ANY); @@@ -515,7 -511,6 +521,7 @@@ struct active_request_slot *get_active_ curl_easy_setopt(slot->curl, CURLOPT_POSTFIELDS, NULL); curl_easy_setopt(slot->curl, CURLOPT_UPLOAD, 0); curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1); + curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 1); if (http_auth.password) init_curl_http_auth(slot->curl); @@@ -771,25 -766,6 +777,25 @@@ char *get_remote_object_url(const char int handle_curl_result(struct slot_results *results) { + /* + * If we see a failing http code with CURLE_OK, we have turned off + * FAILONERROR (to keep the server's custom error response), and should + * translate the code into failure here. + */ + if (results->curl_result == CURLE_OK && + results->http_code >= 400) { + results->curl_result = CURLE_HTTP_RETURNED_ERROR; + /* + * Normally curl will already have put the "reason phrase" + * from the server into curl_errorstr; unfortunately without + * FAILONERROR it is lost, so we can give only the numeric + * status code. + */ + snprintf(curl_errorstr, sizeof(curl_errorstr), + "The requested URL returned error: %ld", + results->http_code); + } + if (results->curl_result == CURLE_OK) { credential_approve(&http_auth); return HTTP_OK; @@@ -854,8 -830,6 +860,8 @@@ static int http_request(const char *url strbuf_addstr(&buf, "Pragma:"); if (options & HTTP_NO_CACHE) strbuf_addstr(&buf, " no-cache"); + if (options & HTTP_KEEP_ERROR) + curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 0); headers = curl_slist_append(headers, buf.buf); @@@ -867,8 -841,7 +873,8 @@@ run_active_slot(slot); ret = handle_curl_result(&results); } else { - error("Unable to start HTTP request for %s", url); + snprintf(curl_errorstr, sizeof(curl_errorstr), + "failed to start HTTP request"); ret = HTTP_START_FAILED; } @@@ -894,22 -867,6 +900,22 @@@ static int http_request_reauth(const ch int ret = http_request(url, type, result, target, options); if (ret != HTTP_REAUTH) return ret; + + /* + * If we are using KEEP_ERROR, the previous request may have + * put cruft into our output stream; we should clear it out before + * making our next request. We only know how to do this for + * the strbuf case, but that is enough to satisfy current callers. + */ + if (options & HTTP_KEEP_ERROR) { + switch (target) { + case HTTP_REQUEST_STRBUF: + strbuf_reset(result); + break; + default: + die("BUG: HTTP_KEEP_ERROR is only supported with strbufs"); + } + } return http_request(url, type, result, target, options); } @@@ -951,6 -908,15 +957,6 @@@ cleanup return ret; } -int http_error(const char *url, int ret) -{ - /* http_request has already handled HTTP_START_FAILED. */ - if (ret != HTTP_START_FAILED) - error("%s while accessing %s", curl_errorstr, url); - - return ret; -} - int http_fetch_ref(const char *base, struct ref *ref) { char *url;