summaryrefslogtreecommitdiff
path: root/internal/curl/curl.ha
blob: 148164ae868ea7c1630882e6ed9077742201fb32 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
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;
};