Merge branch 'jk/http-walker-status-fix'

dumb-http walker has been updated to share more error recovery
strategy with the normal codepath.

* jk/http-walker-status-fix:
  http: use normalize_curl_result() instead of manual conversion
  http: normalize curl results for dumb loose and alternates fetches
  http: factor out curl result code normalization
This commit is contained in:
Junio C Hamano 2019-04-16 19:28:11 +09:00
commit 3151a5fc45
4 changed files with 47 additions and 17 deletions

View file

@ -98,6 +98,11 @@ static void process_object_response(void *callback_data)
process_http_object_request(obj_req->req);
obj_req->state = COMPLETE;
normalize_curl_result(&obj_req->req->curl_result,
obj_req->req->http_code,
obj_req->req->errorstr,
sizeof(obj_req->req->errorstr));
/* Use alternates if necessary */
if (missing_target(obj_req->req)) {
fetch_alternates(walker, alt->base);
@ -208,6 +213,9 @@ static void process_alternates_response(void *callback_data)
char *data;
int i = 0;
normalize_curl_result(&slot->curl_result, slot->http_code,
curl_errorstr, sizeof(curl_errorstr));
if (alt_req->http_specific) {
if (slot->curl_result != CURLE_OK ||
!alt_req->buffer->len) {
@ -518,17 +526,8 @@ static int fetch_object(struct walker *walker, unsigned char *sha1)
req->localfile = -1;
}
/*
* we turned off CURLOPT_FAILONERROR to avoid losing a
* persistent connection and got CURLE_OK.
*/
if (req->http_code >= 300 && req->curl_result == CURLE_OK &&
(starts_with(req->url, "http://") ||
starts_with(req->url, "https://"))) {
req->curl_result = CURLE_HTTP_RETURNED_ERROR;
xsnprintf(req->errorstr, sizeof(req->errorstr),
"HTTP request failed");
}
normalize_curl_result(&req->curl_result, req->http_code,
req->errorstr, sizeof(req->errorstr));
if (obj_req->state == ABORTED) {
ret = error("Request for %s aborted", hex);

18
http.c
View file

@ -1544,7 +1544,8 @@ char *get_remote_object_url(const char *url, const char *hex,
return strbuf_detach(&buf, NULL);
}
static int handle_curl_result(struct slot_results *results)
void normalize_curl_result(CURLcode *result, long http_code,
char *errorstr, size_t errorlen)
{
/*
* If we see a failing http code with CURLE_OK, we have turned off
@ -1554,19 +1555,24 @@ static int handle_curl_result(struct slot_results *results)
* Likewise, if we see a redirect (30x code), that means we turned off
* redirect-following, and we should treat the result as an error.
*/
if (results->curl_result == CURLE_OK &&
results->http_code >= 300) {
results->curl_result = CURLE_HTTP_RETURNED_ERROR;
if (*result == CURLE_OK && http_code >= 300) {
*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.
*/
xsnprintf(curl_errorstr, sizeof(curl_errorstr),
xsnprintf(errorstr, errorlen,
"The requested URL returned error: %ld",
results->http_code);
http_code);
}
}
static int handle_curl_result(struct slot_results *results)
{
normalize_curl_result(&results->curl_result, results->http_code,
curl_errorstr, sizeof(curl_errorstr));
if (results->curl_result == CURLE_OK) {
credential_approve(&http_auth);

9
http.h
View file

@ -136,6 +136,15 @@ static inline int missing__target(int code, int result)
#define missing_target(a) missing__target((a)->http_code, (a)->curl_result)
/*
* Normalize curl results to handle CURL_FAILONERROR (or lack thereof). Failing
* http codes have their "result" converted to CURLE_HTTP_RETURNED_ERROR, and
* an appropriate string placed in the errorstr buffer (pass curl_errorstr if
* you don't have a custom buffer).
*/
void normalize_curl_result(CURLcode *result, long http_code, char *errorstr,
size_t errorlen);
/* Helpers for modifying and creating URLs */
extern void append_remote_object_url(struct strbuf *buf, const char *url,
const char *hex,

View file

@ -408,5 +408,21 @@ test_expect_success 'print HTTP error when any intermediate redirect throws erro
test_i18ngrep "unable to access.*/redir-to/502" stderr
'
test_expect_success 'fetching via http alternates works' '
parent=$HTTPD_DOCUMENT_ROOT_PATH/alt-parent.git &&
git init --bare "$parent" &&
git -C "$parent" --work-tree=. commit --allow-empty -m foo &&
git -C "$parent" update-server-info &&
commit=$(git -C "$parent" rev-parse HEAD) &&
child=$HTTPD_DOCUMENT_ROOT_PATH/alt-child.git &&
git init --bare "$child" &&
echo "../../alt-parent.git/objects" >"$child/objects/info/alternates" &&
git -C "$child" update-ref HEAD $commit &&
git -C "$child" update-server-info &&
git -c http.followredirects=true clone "$HTTPD_URL/dumb/alt-child.git"
'
stop_httpd
test_done