lamb/mods/std/http.lamb

147 lines
3.8 KiB
Plaintext

import("std/list").
fst((x, _)) -> x.
-- maybe stuff
is_just(("just", _)) -> true.
is_just(_) -> false.
is_nothing(("nothing",)) -> true.
is_nothing(_) -> false.
unwrap_maybe(("just", x)) -> x.
-- association list
-- insert a pair into a map
map_insert(assoc, key, value) -> (key, value) :: assoc.
-- lookup by key
map_lookup([], _) -> ("nothing",).
map_lookup((k,v)::xs, key) ->
if k == key then ("just", v)
else map_lookup(xs, key).
-- remove a key from a map
map_remove([], key) -> [].
map_remove((k,v)::xs, key) ->
if k == key then xs
else (k,v) :: map_remove(xs, key).
spanS(_, "") -> ("", "").
spanS(p, x::xs) ->
if p(x) then do
(ys, zs) = spanS(p, xs);
(x::ys, zs)
end
else
("", (x::xs)).
parse_uri("http://" :: rest) -> do
(host, request_) = spanS(\x -> x != "/", rest);
(hostname, port_) = spanS(\x -> x != ":", host);
request = if request_ == "" then "/" else request_;
port = if port_ == "" then 80 else do ":"::p = port_; stoi(p) end;
(hostname, port, request)
end.
parse_uri(uri) -> ("err", "invalid schema (URI: " + repr(uri) + ")").
-- print(parse_uri("http://localhost")).
-- print(parse_uri("http://localhost/foo/bar.html")).
-- print(parse_uri("http://localhost:123")).
-- print(parse_uri("http://localhost:123/foo/bar.html")).
-- print(spanS((\x -> x != "/"), "foobar/")).
-- TODO: fix recursive functions inside functions
get_response_body("\r\n\r\n"::body) -> body.
get_response_body(x::xs) -> get_response_body(xs).
concatS([]) -> "".
concatS(x::xs) -> x + concatS(xs).
concatMapS(f, xs) -> concatS(list\map(f, xs)).
initS(_::"") -> "".
initS(c::cs) -> c :: initS(cs).
lengthS("") -> 0.
lengthS(_::cs) -> 1 + lengthS(cs).
-- NOT complete by any means
urlencode("") -> "".
urlencode("&"::xs) -> "%26" + urlencode(xs).
urlencode(" "::xs) -> "+" :: urlencode(xs).
urlencode("\r"::xs) -> "%0D" + urlencode(xs).
urlencode("\n"::xs) -> "%0A" + urlencode(xs).
urlencode(c::xs) -> c :: urlencode(xs).
http_get(uri) -> do
f((hostname, port, request)) -> do
putstrln("hostname: " + repr(hostname) + " port: " + repr(port) + " request: " + repr(request));
sock = sockopen(hostname, port);
fputstr(sock, "GET " + request + " HTTP/1.0\r\n");
fputstr(sock, "Host: " + hostname + "\r\n");
fputstr(sock, "User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) lamb\r\n");
fputstr(sock, "\r\n");
response = freadcontents(sock);
(code, _) = spanS(\x -> x != "\n", response);
putstrln("code: " + code);
resp = get_response_body(response);
("ok", resp)
end;
f(err) -> err;
f(parse_uri(uri))
end.
http_post(uri, data) -> do
f((hostname, port, request)) -> do
putstrln("hostname: " + repr(hostname) + " port: " + repr(port) + " request: " + repr(request));
--fputstr = (\_, s -> putstrln("SEND: " + s));
body_ = concatMapS(\(k,v) -> k + "=" + urlencode(v) + "&", data);
body = initS(body_);
sock = sockopen(hostname, port);
fputstr(sock, "POST " + request + " HTTP/1.0\r\n");
fputstr(sock, "Host: " + hostname + "\r\n");
fputstr(sock, "User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) lamb\r\n");
fputstr(sock, "Content-Type: application/x-www-form-urlencoded\r\n");
fputstr(sock, "Content-Length: " + repr(lengthS(body)) + "\r\n");
fputstr(sock, "\r\n");
fputstr(sock, body);
response = freadcontents(sock);
(code, _) = spanS(\x -> x != "\n", response);
putstrln("code: " + code);
resp = get_response_body(response);
("ok", resp)
end;
f(err) -> err;
f(parse_uri(uri))
end.
-- print(http_get("http://127.0.0.1:123/foo/bar.html")).
-- print(http_get("nope://localhost:123/foo/bar.html")).
-- print(http_get("http://thefuckingweather.com/?where=12345")).
-- print(concatS(["foo", "bar"])).
-- print(http_post("http://127.0.0.1:123/foo/bar.html", [("foo", "bar")])).
-- print(http_post("http://ix.io", [("f:1", "hi from lamb! :D & goodbye!")])).
async_http_get(url, k) -> thread!(\_ -> k(http_get(url))).