lav

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

http.ha (1814B)


      1 use fmt;
      2 use net;
      3 use io;
      4 use strings;
      5 use strconv;
      6 use encoding::utf8;
      7 
      8 export type invalid = !void;
      9 
     10 export type response = struct {
     11 	status: int,
     12 	attributes: [][]str
     13 };
     14 
     15 export fn get(sock: io::handle, resource: str) (str | io::error | utf8::invalid) = {
     16 	let req = fmt::asprintf("GET {} HTTP/1.1\r\nUser-Agent: curl/8.6.0\r\n\r\n", resource)!;
     17 	defer free(req);
     18 	let utf8 = strings::toutf8(req);
     19 
     20 	match (io::write(sock, utf8)) {
     21 		case let e: io::error => return e;
     22 		case => yield;
     23 	};
     24 
     25 	let res: []u8 = match(io::drain(sock)) {
     26 		case let buf: []u8 => yield buf;
     27 		case let e: io::error => return e;
     28 	};
     29 
     30 	return strings::fromutf8(res);
     31 };
     32 
     33 export fn freeres(res: *response) void = {
     34 	for (let attribute .. res.attributes) {
     35 		strings::freeall(attribute);
     36 	};
     37 };
     38 
     39 export fn parseres(res: str, html: *str) (response | invalid) = {
     40 	let header = strings::index(res, "\r\n\r\n") as size;
     41 	let lines = strings::split(strings::sub(res, 0, header), "\r\n")!;
     42 	defer free(lines);
     43 
     44 	let tok = &strings::tokenize(lines[0], " ");
     45 	match (strings::next_token(tok)) {
     46 		case done => return invalid;
     47 		case => yield;
     48 	};
     49 	let s = match(strings::next_token(tok)) {
     50 		case let s: str => yield match (strconv::stoi(s)) {
     51 			case let i: int => yield i;
     52 			case => return invalid;
     53 		};
     54 	};
     55 
     56 	let response = response {
     57 		status = s,
     58 		attributes = [],
     59 	};
     60 
     61 	let i = 0z;
     62 	for (let line .. lines[1..]) {
     63 		let split = match (strings::splitn(line, ": ", 2)) {
     64 			case let s: []str => yield s;
     65 			case nomem => fmt::fatal("Out of memory!");
     66 		};
     67 		if (len(split) >= 2) {
     68 			split[0] = strings::ltrim(split[0]);
     69 			split[1] = strings::ltrim(split[1]);
     70 			append(response.attributes, strings::dupall(split) as []str)!;
     71 			i += 1;
     72 		};
     73 
     74 		free(split);
     75 	};
     76 
     77 	*html = strings::sub(res, header + 4, strings::end);
     78 	return response;
     79 };