diff options
| author | Julian Hurst <ark@mansus.space> | 2024-03-10 02:35:08 +0100 |
|---|---|---|
| committer | Julian Hurst <ark@mansus.space> | 2024-03-10 02:35:08 +0100 |
| commit | 89173069e85416539b1256ed1ae1c77e89550ae6 (patch) | |
| tree | d2f42c63b91306ad1b4693737ab1e35514d746b9 /internal/curl/curl.ha | |
| parent | 69712258bafda1258454e6336faabf527f207e3b (diff) | |
| download | hacurl-89173069e85416539b1256ed1ae1c77e89550ae6.tar.gz | |
Allow retrieving in memory response struct, and cleanup
Diffstat (limited to 'internal/curl/curl.ha')
| -rw-r--r-- | internal/curl/curl.ha | 74 |
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; +}; |
