http.um
struct Progress
type Progress* = struct {
// total data to download
dltotal: int
// amount of downloaded data
dlnow: int
// total data to upload
ultotal: int
// amount of uploaded data
ulnow: int
}
struct Response
type Response* = struct {
status: int
headers: map[str]str
body: []char
complete: bool
progress: Progress
}
enum Method
type Method* = enum {
get
post
}
struct Request
type Request* = struct {
method: Method
url: str
headers: map[str]str
body: []char
}
fn requestAsync
Make an asynchronous request and return a RequestHandle. The handle can be polled for the response.
fn requestAsync*(r: Request): RequestHandle {
fn RequestHandle.poll
Poll the handle for a response or an error. If the request is ongoing, the
response has completed
set to false
. The progress
field can be used to
see progress of the request.
fn (rh: ^RequestHandle) poll*(): (Response, std::Err) {
fn request
Make a request and return the response.
fn request*(r: Request): (Response, std::Err) {
Example
fn main() {
rh := requestAsync({
url: "https://httpbin.org/get"
})
for true {
if resp, err := rh.poll(); resp.complete {
std::exitif(err)
printf("status: %d\n", resp.status)
for k, v in resp.headers {
printf("%s: %s\n", k, v)
}
printf("body: %v\n", str(resp.body))
break
} else {
if resp.progress.dltotal > 0 {
printf("Progress: %.1f%% (%d/%d)\n", real(resp.progress.dlnow) / resp.progress.dltotal * 100, resp.progress.dlnow, resp.progress.dltotal)
} else {
printf("Progress: unknown\n")
}
for i:=0; i < 1999999; i++ {}
}
}
resp, err := request({
method: .post,
url: "https://httpbin.org/post",
headers: { "Content-Type": "application/json" },
body: []char("[ 1, 2, 3 ]")
})
std::exitif(err)
printf("status: %d\n", resp.status)
for k, v in resp.headers {
printf("%s: %s\n", k, v)
}
printf("body: %v\n", str(resp.body))
}
import (
"std.um"
"umbox/strings/strings.um"
)
//~~struct Progress
type Progress* = struct {
// total data to download
dltotal: int
// amount of downloaded data
dlnow: int
// total data to upload
ultotal: int
// amount of uploaded data
ulnow: int
}
//~~
//~~struct Response
type Response* = struct {
status: int
headers: map[str]str
body: []char
complete: bool
progress: Progress
}
//~~
type cResponse* = struct {
status: int
headers: str
body: []char
progress: Progress
}
//~~enum Method
type Method* = enum {
get
post
}
//~~
//~~struct Request
type Request* = struct {
method: Method
url: str
headers: map[str]str
body: []char
}
//~~
type cRequest* = struct {
method: Method
url: str
headers: []str
body: []char
}
type RequestHandle* = struct{ _: ^struct{} }
fn umc__request(cr: ^cRequest): ^struct{}
fn umc__poll(rh: ^struct{}, cresp: ^cResponse, typeptr: ^void): int
fn umc__strerror(code: int): str
fn errFromCode(code: int): std::Err {
return std::error(code, umc__strerror(code), "http.um")
}
//~~fn requestAsync
// Make an asynchronous request and return a RequestHandle. The handle can be
// polled for the response.
fn requestAsync*(r: Request): RequestHandle {
//~~
cr := cRequest {
method: r.method,
url: r.url,
headers: {},
body: r.body
}
for k,v in r.headers {
cr.headers = append(cr.headers, sprintf("%s: %s", k, v))
}
return { umc__request(&cr) }
}
//~~fn RequestHandle.poll
// Poll the handle for a response or an error. If the request is ongoing, the
// response has `completed` set to `false`. The `progress` field can be used to
// see progress of the request.
fn (rh: ^RequestHandle) poll*(): (Response, std::Err) {
//~~
cresp := cResponse{}
err := umc__poll(rh._, &cresp, typeptr([]char))
if err != 0 {
return { progress: cresp.progress }, errFromCode(err)
}
headersList := strings::split(cresp.headers, "\n")
headers := map[str]str{}
for i,h in headersList {
sp := strings::split(h, ": ")
if len(sp) != 2 { continue }
headers[sp[0]] = sp[1]
}
return {
status: cresp.status,
body: cresp.body,
headers: headers,
complete: true,
progress: cresp.progress
}, {}
}
//~~fn request
// Make a request and return the response.
fn request*(r: Request): (Response, std::Err) {
//~~
rh := requestAsync(r)
for true {
if resp, err := rh.poll(); resp.complete {
return resp, err
}
}
return {}, {}
}
//~~Example
fn main() {
rh := requestAsync({
url: "https://httpbin.org/get"
})
for true {
if resp, err := rh.poll(); resp.complete {
std::exitif(err)
printf("status: %d\n", resp.status)
for k, v in resp.headers {
printf("%s: %s\n", k, v)
}
printf("body: %v\n", str(resp.body))
break
} else {
if resp.progress.dltotal > 0 {
printf("Progress: %.1f%% (%d/%d)\n", real(resp.progress.dlnow) / resp.progress.dltotal * 100, resp.progress.dlnow, resp.progress.dltotal)
} else {
printf("Progress: unknown\n")
}
for i:=0; i < 1999999; i++ {}
}
}
resp, err := request({
method: .post,
url: "https://httpbin.org/post",
headers: { "Content-Type": "application/json" },
body: []char("[ 1, 2, 3 ]")
})
std::exitif(err)
printf("status: %d\n", resp.status)
for k, v in resp.headers {
printf("%s: %s\n", k, v)
}
printf("body: %v\n", str(resp.body))
}
//~~