http: add HTTP_KEEP_ERROR option

We currently set curl's FAILONERROR option, which means that any http failures are reported as curl errors, and the http body content from the server is thrown away. This patch introduces a new option to http_get_strbuf which specifies that the body content from a failed http response should be placed in the destination strbuf, where it can be accessed by the caller. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Jeff King committed Apr 5, 2013 at 18:14 UTC 6d052d78d74e581dd93dd6328d3c214f469e34d7
2 files changed +38
http.c
+37
@@ -761,6 +761,25 @@ char *get_remote_object_url(const char *url, const char *hex,
761
762 int handle_curl_result(struct slot_results *results)
763 {
764 + /*
765 + * If we see a failing http code with CURLE_OK, we have turned off
766 + * FAILONERROR (to keep the server's custom error response), and should
767 + * translate the code into failure here.
768 + */
769 + if (results->curl_result == CURLE_OK &&
770 + results->http_code >= 400) {
771 + results->curl_result = CURLE_HTTP_RETURNED_ERROR;
772 + /*
773 + * Normally curl will already have put the "reason phrase"
774 + * from the server into curl_errorstr; unfortunately without
775 + * FAILONERROR it is lost, so we can give only the numeric
776 + * status code.
777 + */
778 + snprintf(curl_errorstr, sizeof(curl_errorstr),
779 + "The requested URL returned error: %ld",
780 + results->http_code);
781 + }
782 +
783 if (results->curl_result == CURLE_OK) {
784 credential_approve(&http_auth);
785 return HTTP_OK;
@@ -825,6 +844,8 @@ static int http_request(const char *url, struct strbuf *type,
844 strbuf_addstr(&buf, "Pragma:");
845 if (options & HTTP_NO_CACHE)
846 strbuf_addstr(&buf, " no-cache");
847 + if (options & HTTP_KEEP_ERROR)
848 + curl_easy_setopt(slot->curl, CURLOPT_FAILONERROR, 0);
849
850 headers = curl_slist_append(headers, buf.buf);
851
@@ -862,6 +883,22 @@ static int http_request_reauth(const char *url,
883 int ret = http_request(url, type, result, target, options);
884 if (ret != HTTP_REAUTH)
885 return ret;
886 +
887 + /*
888 + * If we are using KEEP_ERROR, the previous request may have
889 + * put cruft into our output stream; we should clear it out before
890 + * making our next request. We only know how to do this for
891 + * the strbuf case, but that is enough to satisfy current callers.
892 + */
893 + if (options & HTTP_KEEP_ERROR) {
894 + switch (target) {
895 + case HTTP_REQUEST_STRBUF:
896 + strbuf_reset(result);
897 + break;
898 + default:
899 + die("BUG: HTTP_KEEP_ERROR is only supported with strbufs");
900 + }
901 + }
902 return http_request(url, type, result, target, options);
903 }
904
http.h
+1
@@ -118,6 +118,7 @@ extern char *get_remote_object_url(const char *url, const char *hex,
118
119 /* Options for http_request_*() */
120 #define HTTP_NO_CACHE 1
121 +#define HTTP_KEEP_ERROR 2
122
123 /* Return values for http_request_*() */
124 #define HTTP_OK 0