Skip to content

Commit e929cd2

Browse files
glandiumgitster
authored andcommitted
http.c: new functions for the http API
The new functions added are: - http_request() (internal function) - http_get_strbuf() - http_get_file() - http_error() http_get_strbuf and http_get_file allow respectively to retrieve contents of an URL to a strbuf or an opened file handle. http_error prints out an error message containing the URL and the curl error (in curl_errorstr). Signed-off-by: Mike Hommey <[email protected]> Signed-off-by: Tay Ray Chuan <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 5ace994 commit e929cd2

File tree

2 files changed

+134
-0
lines changed

2 files changed

+134
-0
lines changed

http.c

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,110 @@ static char *quote_ref_url(const char *base, const char *ref)
665665
return strbuf_detach(&buf, NULL);
666666
}
667667

668+
/* http_request() targets */
669+
#define HTTP_REQUEST_STRBUF 0
670+
#define HTTP_REQUEST_FILE 1
671+
672+
static int http_request(const char *url, void *result, int target, int options)
673+
{
674+
struct active_request_slot *slot;
675+
struct slot_results results;
676+
struct curl_slist *headers = NULL;
677+
struct strbuf buf = STRBUF_INIT;
678+
int ret;
679+
680+
slot = get_active_slot();
681+
slot->results = &results;
682+
curl_easy_setopt(slot->curl, CURLOPT_HTTPGET, 1);
683+
684+
if (result == NULL) {
685+
curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 1);
686+
} else {
687+
curl_easy_setopt(slot->curl, CURLOPT_NOBODY, 0);
688+
curl_easy_setopt(slot->curl, CURLOPT_FILE, result);
689+
690+
if (target == HTTP_REQUEST_FILE) {
691+
long posn = ftell(result);
692+
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION,
693+
fwrite);
694+
if (posn > 0) {
695+
strbuf_addf(&buf, "Range: bytes=%ld-", posn);
696+
headers = curl_slist_append(headers, buf.buf);
697+
strbuf_reset(&buf);
698+
}
699+
slot->local = result;
700+
} else
701+
curl_easy_setopt(slot->curl, CURLOPT_WRITEFUNCTION,
702+
fwrite_buffer);
703+
}
704+
705+
strbuf_addstr(&buf, "Pragma:");
706+
if (options & HTTP_NO_CACHE)
707+
strbuf_addstr(&buf, " no-cache");
708+
709+
headers = curl_slist_append(headers, buf.buf);
710+
711+
curl_easy_setopt(slot->curl, CURLOPT_URL, url);
712+
curl_easy_setopt(slot->curl, CURLOPT_HTTPHEADER, headers);
713+
714+
if (start_active_slot(slot)) {
715+
run_active_slot(slot);
716+
if (results.curl_result == CURLE_OK)
717+
ret = HTTP_OK;
718+
else if (missing_target(&results))
719+
ret = HTTP_MISSING_TARGET;
720+
else
721+
ret = HTTP_ERROR;
722+
} else {
723+
error("Unable to start HTTP request for %s", url);
724+
ret = HTTP_START_FAILED;
725+
}
726+
727+
slot->local = NULL;
728+
curl_slist_free_all(headers);
729+
strbuf_release(&buf);
730+
731+
return ret;
732+
}
733+
734+
int http_get_strbuf(const char *url, struct strbuf *result, int options)
735+
{
736+
return http_request(url, result, HTTP_REQUEST_STRBUF, options);
737+
}
738+
739+
int http_get_file(const char *url, const char *filename, int options)
740+
{
741+
int ret;
742+
struct strbuf tmpfile = STRBUF_INIT;
743+
FILE *result;
744+
745+
strbuf_addf(&tmpfile, "%s.temp", filename);
746+
result = fopen(tmpfile.buf, "a");
747+
if (! result) {
748+
error("Unable to open local file %s", tmpfile.buf);
749+
ret = HTTP_ERROR;
750+
goto cleanup;
751+
}
752+
753+
ret = http_request(url, result, HTTP_REQUEST_FILE, options);
754+
fclose(result);
755+
756+
if ((ret == HTTP_OK) && move_temp_to_file(tmpfile.buf, filename))
757+
ret = HTTP_ERROR;
758+
cleanup:
759+
strbuf_release(&tmpfile);
760+
return ret;
761+
}
762+
763+
int http_error(const char *url, int ret)
764+
{
765+
/* http_request has already handled HTTP_START_FAILED. */
766+
if (ret != HTTP_START_FAILED)
767+
error("%s while accessing %s\n", curl_errorstr, url);
768+
769+
return ret;
770+
}
771+
668772
int http_fetch_ref(const char *base, struct ref *ref)
669773
{
670774
char *url;

http.h

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,36 @@ static inline int missing__target(int code, int result)
114114

115115
#define missing_target(a) missing__target((a)->http_code, (a)->curl_result)
116116

117+
/* Options for http_request_*() */
118+
#define HTTP_NO_CACHE 1
119+
120+
/* Return values for http_request_*() */
121+
#define HTTP_OK 0
122+
#define HTTP_MISSING_TARGET 1
123+
#define HTTP_ERROR 2
124+
#define HTTP_START_FAILED 3
125+
126+
/*
127+
* Requests an url and stores the result in a strbuf.
128+
*
129+
* If the result pointer is NULL, a HTTP HEAD request is made instead of GET.
130+
*/
131+
int http_get_strbuf(const char *url, struct strbuf *result, int options);
132+
133+
/*
134+
* Downloads an url and stores the result in the given file.
135+
*
136+
* If a previous interrupted download is detected (i.e. a previous temporary
137+
* file is still around) the download is resumed.
138+
*/
139+
int http_get_file(const char *url, const char *filename, int options);
140+
141+
/*
142+
* Prints an error message using error() containing url and curl_errorstr,
143+
* and returns ret.
144+
*/
145+
int http_error(const char *url, int ret);
146+
117147
extern int http_fetch_ref(const char *base, struct ref *ref);
118148

119149
#endif /* HTTP_H */

0 commit comments

Comments
 (0)