Inherited from v1.0.0

request module

Axios-style HTTP client. Every verb returns a Future — pair with wait for straight-line code. An optional config map per call carries headers/params/timeout/etc. JSON and form bodies auto-encode. Connection pooling, before/after interceptors, file upload/download.

import "request" as r;

function main() {
    var resp = wait r.get("https://api.example.com/users/1");
    print(resp.status, resp.body);

    var created = wait r.post(
        "https://api.example.com/users",
        { name: "Alice" },                              // auto-JSON
        { headers: { "X-Trace": "abc" }, timeout: 5000 }
    );
    print("created id:", created.data.id);
}
main().fail(function (e) { print("err:", e); });

Verb shortcuts

Every verb accepts an optional config map for headers, params (query), timeout, etc. The verb's URL, method, and body always win over config — config is purely additive.

FunctionDescription
r.get(url, config?)Returns Future<resp>.
r.head(url, config?)
r.delete(url, config?)
r.post(url, data, config?)data can be a string (raw body) or a map (auto-JSON).
r.put(url, data, config?)
r.patch(url, data, config?)
r.post_form(url, fields, config?)URL-encoded form body.
r.request(config)Full-options form: {url, method, headers, body, json, form, params, timeout, ...}.

Config keys

KeyDescription
headersMap of header name → value. Merged with instance defaults.
paramsMap serialized as query string and appended to the URL.
timeoutMilliseconds. Rejected with a timeout error if exceeded.
jsonMap sent as JSON body (sets Content-Type: application/json).
formMap sent as application/x-www-form-urlencoded.
bodyRaw string body. You set Content-Type yourself.
dataSmart: map → JSON, string → text/plain.
pooltrue to use keep-alive pool for this request.
tlsTLS options (e.g. { verify: false } for self-signed).
base_url(instance only) prepended to relative URLs.

Instances

var api = r.create({
    base_url: "https://api.example.com",
    headers:  { "Authorization": "Bearer " + token }
});

var users = wait api.get("/users", { params: { limit: 10 } });
FunctionDescription
r.create(defaults) → instanceBind a base URL, default headers/timeout/etc. Instance has the same verb shape as the module.
r.before(fn) / api.before(fn)Hook before(cfg) → cfg — modify config before send.
r.after(fn) / api.after(fn)Hook after(resp) → resp — modify response before return.

File transfer

FunctionDescription
r.download(url, dest, config?) → FutureStream url to file dest. Resolves with {status, headers, dest, bytes_written, ok}.
r.upload(url, file, config?) → FuturePOST file as multipart. file is a path string or a spec map {path, name, filename, content_type}. Extra fields via config.fields.
var dl = wait r.download("https://example.com/big.zip", "./big.zip");
print("downloaded", dl.bytes_written, "bytes to", dl.dest);

var up = wait r.upload(
    "https://example.com/upload",
    { path: "./report.pdf", name: "report", content_type: "application/pdf" },
    { fields: { user: "alice" }, headers: { "X-Trace": "abc" } }
);

Connection pool

request keeps a keep-alive pool per scheme://host:port. Enable per-request via config.pool: true or default via r.create({...pool: true}). Call r.shutdown() at process end to drain it cleanly.

Response object

resp exposes:

  • status — HTTP status code.
  • headers — map with lowercased keys.
  • body — raw response body string.
  • data — parsed body when content-type is JSON; otherwise same as body.
  • oktrue if status is 2xx.
  • json() — re-parse body as JSON on demand.

A 4xx/5xx response fulfills the Future (you get a resp with ok=false). The Future only rejects on transport-level errors (DNS, TCP, TLS, timeout, malformed response).

try {
    var resp = wait r.get(url, { timeout: 3000 });
    if (resp.ok) { print("got:", resp.body); }
    else        { print("server said:", resp.status); }
} catch (e) {
    print("transport error:", e);
}

See also

  • Future — what the verbs return.
  • web — the server side.
  • multipart — what upload builds under the hood.