omdb/fetch.c
2025-12-13 00:22:27 -06:00

113 lines
2.6 KiB
C

#include <curl/curl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "fetch.h"
static char curl_errbuf[CURL_ERROR_SIZE] = {'\0'};
struct fetch *fetch_init(void) {
CURLcode res;
CURL *handle;
struct fetch *fh = NULL;
/*
* TODO: Not sure if calling this possibly more than once can cause
* an issue or not.
*/
if ((res = curl_global_init(CURL_GLOBAL_DEFAULT)) != CURLE_OK) {
fprintf(stderr, "Could not initialize curl: %s\n", curl_easy_strerror(res));
exit(EXIT_FAILURE);
}
handle = curl_easy_init();
if ((res = curl_easy_setopt(handle, CURLOPT_ERRORBUFFER, curl_errbuf)) !=
CURLE_OK) {
fprintf(stderr, "Error setting up error buffer: %s\n",
curl_easy_strerror(res));
curl_easy_cleanup(handle);
exit(EXIT_FAILURE);
}
if ((fh = malloc(sizeof *fh)) == NULL) {
fputs("Out of memory.\n", stderr);
exit(EXIT_FAILURE);
}
fh->handle = handle;
return fh;
}
void fetch_cleanup(struct fetch *restrict f) {
/* Don't even dignify this with a response */
if (f == NULL)
return;
curl_easy_cleanup(f->handle);
free(f);
}
size_t fetch_cb(void *ptr, size_t size, size_t nmemb, void *data) {
struct response *resp = (struct response *)data;
size_t real_size = size * nmemb;
if ((resp->data = realloc(resp->data, resp->size + real_size + 1)) == NULL) {
fputs("Out of memory.\n", stderr);
exit(EXIT_FAILURE);
}
printf("Wrote %zd bytes\n", real_size);
memcpy(resp->data + resp->size, ptr, real_size);
resp->size += real_size;
resp->data[resp->size] = '\0';
return real_size;
}
struct response *fetch(struct fetch *restrict f, CURLU *restrict url) {
struct response *resp = NULL;
if (curl_easy_setopt(f->handle, CURLOPT_WRITEFUNCTION, fetch_cb) != CURLE_OK)
goto call_fetch_fail;
if (curl_easy_setopt(f->handle, CURLOPT_CURLU, url) != CURLE_OK)
goto call_fetch_fail;
if ((resp = malloc(sizeof *resp)) == NULL) {
fputs("Out of memory.", stderr);
exit(EXIT_FAILURE);
}
memset(resp, 0, sizeof *resp);
if (curl_easy_setopt(f->handle, CURLOPT_WRITEDATA, (void *)resp) != CURLE_OK)
goto call_fetch_fail;
if (curl_easy_perform(f->handle) != CURLE_OK)
goto call_fetch_fail;
if (curl_easy_getinfo(f->handle, CURLINFO_CONTENT_TYPE,
&resp->content_type) != CURLE_OK)
goto call_fetch_fail;
printf("CONTENT TYPE: %s\n", resp->content_type);
return resp;
call_fetch_fail:
if (resp != NULL)
free(resp);
fputs(curl_errbuf, stderr);
return NULL;
}
void response_cleanup(struct response *resp) {
if (resp != NULL) {
free(resp->data);
free(resp);
}
}