From 8e17cb6d88f098071bc2f214ccb5d4073d27deec Mon Sep 17 00:00:00 2001 From: Bruno Dias Date: Mon, 13 Jul 2026 20:51:26 -0300 Subject: [PATCH] Handle timeout and other CURL results to be handled by the user. --- Readme.md | 10 ++++++++-- src/http-get.c | 44 ++++++++++++++++++++++++++++---------------- src/http-get.h | 4 ++++ 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/Readme.md b/Readme.md index 7014586..e4baa0a 100644 --- a/Readme.md +++ b/Readme.md @@ -23,12 +23,18 @@ ok: 1 or 0, status: response status code, data: response text/data, - size: size of data + size: size of data, + code: curl error code } + Requests use a 30 second overall timeout and a 10 second connect timeout by + default. A timeout leaves `ok` at `0` and sets `code` to + `CURLE_OPERATION_TIMEDOUT`. + ### `int http_get_file(const char *url, const char *file)` - Perform an HTTP GET request on `url` and save the response to `file`. Returns `0` on success and `-1` on failures. + Perform an HTTP GET request on `url` and save the response to `file`. Returns + `0` on success, `-2` on timeout, and `-1` on other failures. ### `void http_get_free(http_get_response_t *res)` diff --git a/src/http-get.c b/src/http-get.c index 0aeaaff..bec9505 100644 --- a/src/http-get.c +++ b/src/http-get.c @@ -7,6 +7,7 @@ // #include +#include #include #include #include "http-get.h" @@ -40,27 +41,39 @@ static size_t http_get_cb(void *contents, size_t size, size_t nmemb, void *userp return realsize; } +static void http_get_configure(CURL *req, CURLSH *share) { + if (share) { + curl_easy_setopt(req, CURLOPT_SHARE, share); + } + + curl_easy_setopt(req, CURLOPT_HTTPGET, 1); + curl_easy_setopt(req, CURLOPT_FOLLOWLOCATION, 1); + curl_easy_setopt(req, CURLOPT_NOSIGNAL, 1); + curl_easy_setopt(req, CURLOPT_CONNECTTIMEOUT, HTTP_GET_CONNECT_TIMEOUT); + curl_easy_setopt(req, CURLOPT_TIMEOUT, HTTP_GET_TIMEOUT); +} + http_get_response_t *http_get_shared(const char *url, CURLSH *share) { CURL *req = curl_easy_init(); + if (!req) return NULL; http_get_response_t *res = malloc(sizeof(http_get_response_t)); - memset(res, 0, sizeof(http_get_response_t)); - - if (share) { - curl_easy_setopt(req, CURLOPT_SHARE, share); + if (!res) { + curl_easy_cleanup(req); + return NULL; } + memset(res, 0, sizeof(http_get_response_t)); curl_easy_setopt(req, CURLOPT_URL, url); - curl_easy_setopt(req, CURLOPT_HTTPGET, 1); - curl_easy_setopt(req, CURLOPT_FOLLOWLOCATION, 1); + http_get_configure(req, share); curl_easy_setopt(req, CURLOPT_WRITEFUNCTION, http_get_cb); curl_easy_setopt(req, CURLOPT_WRITEDATA, (void *) res); curl_easy_setopt(req, CURLOPT_USERAGENT, "http-get.c/"HTTP_GET_VERSION); - int c = curl_easy_perform(req); + res->code = curl_easy_perform(req); curl_easy_getinfo(req, CURLINFO_RESPONSE_CODE, &res->status); - res->ok = (200 == res->status && CURLE_ABORTED_BY_CALLBACK != c) ? 1 : 0; + res->ok = (200 == res->status && CURLE_OK == res->code) ? 1 : 0; curl_easy_cleanup(req); return res; @@ -93,18 +106,16 @@ int http_get_file_shared(const char *url, const char *file, CURLSH *share) { if (!req) return -1; FILE *fp = fopen(file, "wb"); - if (!fp) return -1; - - if (share) { - curl_easy_setopt(req, CURLOPT_SHARE, share); + if (!fp) { + curl_easy_cleanup(req); + return -1; } curl_easy_setopt(req, CURLOPT_URL, url); - curl_easy_setopt(req, CURLOPT_HTTPGET, 1); - curl_easy_setopt(req, CURLOPT_FOLLOWLOCATION, 1); + http_get_configure(req, share); curl_easy_setopt(req, CURLOPT_WRITEFUNCTION, http_get_file_cb); curl_easy_setopt(req, CURLOPT_WRITEDATA, fp); - int res = curl_easy_perform(req); + CURLcode res = curl_easy_perform(req); long status; curl_easy_getinfo(req, CURLINFO_RESPONSE_CODE, &status); @@ -112,7 +123,8 @@ int http_get_file_shared(const char *url, const char *file, CURLSH *share) { curl_easy_cleanup(req); fclose(fp); - return (200 == status && CURLE_ABORTED_BY_CALLBACK != res) ? 0 : -1; + if (CURLE_OPERATION_TIMEDOUT == res) return -2; + return (200 == status && CURLE_OK == res) ? 0 : -1; } int http_get_file(const char *url, const char *file) { diff --git a/src/http-get.h b/src/http-get.h index d584086..a89073c 100644 --- a/src/http-get.h +++ b/src/http-get.h @@ -11,14 +11,18 @@ #define HTTP_GET_H 1 #include +#include #define HTTP_GET_VERSION "0.4.0" +#define HTTP_GET_TIMEOUT 30L +#define HTTP_GET_CONNECT_TIMEOUT 10L typedef struct { char *data; size_t size; long status; int ok; + CURLcode code; } http_get_response_t; http_get_response_t *http_get(const char *);