summaryrefslogtreecommitdiff
path: root/internal/curl/curl.ha
diff options
context:
space:
mode:
authorJulian Hurst <ark@mansus.space>2024-03-10 02:35:08 +0100
committerJulian Hurst <ark@mansus.space>2024-03-10 02:35:08 +0100
commit89173069e85416539b1256ed1ae1c77e89550ae6 (patch)
treed2f42c63b91306ad1b4693737ab1e35514d746b9 /internal/curl/curl.ha
parent69712258bafda1258454e6336faabf527f207e3b (diff)
downloadhacurl-89173069e85416539b1256ed1ae1c77e89550ae6.tar.gz
Allow retrieving in memory response struct, and cleanup
Diffstat (limited to 'internal/curl/curl.ha')
-rw-r--r--internal/curl/curl.ha74
1 files changed, 74 insertions, 0 deletions
diff --git a/internal/curl/curl.ha b/internal/curl/curl.ha
new file mode 100644
index 0000000..148164a
--- /dev/null
+++ b/internal/curl/curl.ha
@@ -0,0 +1,74 @@
+use types::c;
+use fmt;
+use os;
+use memio;
+use strings;
+use io;
+use internal::curl::ccurl;
+
+export type curlerror = !(setopterr | performerr | getinfoerr);
+
+export type setopterr = !int;
+export type performerr = !int;
+export type getinfoerr = !int;
+
+// A HTTP response
+export type response = struct {
+ // Body
+ data: memio::stream,
+ // HTTP status
+ status: i64,
+ // Size of the body
+ sz: i64,
+};
+
+// Creates a response and returns it. Caller must call [[closeresponse]] to
+// close the underlying stream.
+export fn newresponse() response = {
+ return response {
+ data = memio::dynamic(),
+ status = 0,
+ sz = 0,
+ };
+};
+
+// Closes the stream associated to the response created by [[newresponse]].
+export fn closeresponse(resp: response) (void | io::error) = {
+ io::close(&resp.data)?;
+};
+
+fn cb(ptr: *c::char, sz: c::ssize, nmemb: c::ssize, userdata: *opaque) c::ssize = {
+ let s = c::tostr(ptr)!;
+ //fmt::printfln("FOOKL: {}", s)!;
+ let resp = userdata: *response;
+ let realsize = nmemb * sz;
+ let b = strings::toutf8(s);
+ memio::concat(&resp.data, strings::fromutf8_unsafe(b[..realsize]))!;
+ resp.sz += sz * nmemb;
+ return sz * nmemb;
+};
+
+// Makes a HTTP request to the given url and fills resp with the body, HTTP
+// status and body size.
+export fn get(url: const str, resp: *response) (void | curlerror) = {
+ let c = ccurl::curl_easy_init();
+ defer ccurl::curl_easy_cleanup(c);
+ let c_url = c::fromstr(url);
+ defer free(c_url);
+ let res = ccurl::curl_easy_setopt(c, ccurl::CURLOPT_URL, c_url);
+ if (res != 0) {
+ return res: setopterr;
+ };
+ res = ccurl::curl_easy_setopt_writefunction(c, ccurl::CURLOPT_WRITEFUNCTION, &cb);
+ res = ccurl::curl_easy_setopt_writedata(c, ccurl::CURLOPT_WRITEDATA, resp);
+ res = ccurl::curl_easy_perform(c);
+ if (res != 0) {
+ return res: performerr;
+ };
+ let rc: c::long = 0;
+ res = ccurl::curl_easy_getinfo(c, ccurl::CURLINFO_RESPONSE_CODE, &rc);
+ if (res != 0) {
+ return res: getinfoerr;
+ };
+ resp.status = rc;
+};