Download
111 lines 3.4 KiBTomoModified 2025-11-29 raw
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
# A simple HTTP library built using CURL

use -lcurl
use <curl/curl.h>

struct HTTPResponse(code:Int, body:Text)

enum _Method(GET, POST, PUT, PATCH, DELETE)

func _send(method:_Method, url:Text, data:Text?, headers:[Text]=[] -> HTTPResponse)
    chunks : @[Text]
    save_chunk := func(chunk:CString, size:Int64, n:Int64)
        chunks.insert(C_code:Text`Text$from_strn(@chunk, @size*@n)`)
        return n*size

    C_code `
        CURL *curl = curl_easy_init();
        struct curl_slist *chunk = NULL;
        curl_easy_setopt(curl, CURLOPT_URL, @(CString(url)));
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, @save_chunk.fn);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, @save_chunk.userdata);
    `

    defer
        C_code `
            if (chunk)
                curl_slist_free_all(chunk);
            curl_easy_cleanup(curl);
        `

    when method is POST
        C_code `
            curl_easy_setopt(curl, CURLOPT_POST, 1L);
        `
        if posting := data
            C_code `
                curl_easy_setopt(curl, CURLOPT_POSTFIELDS, @(CString(posting)));
            `
    is PUT
        C_code `
            curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
        `
        if putting := data
            C_code `
                curl_easy_setopt(curl, CURLOPT_POSTFIELDS, @(CString(putting)));
            `
    is PATCH
        C_code `
            curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PATCH");
        `
        if patching := data
            C_code `
                curl_easy_setopt(curl, CURLOPT_POSTFIELDS, @(CString(patching)));
            `
    is DELETE
        C_code `
            curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
        `
    else
        pass

    for header in headers
        C_code `
            chunk = curl_slist_append(chunk, @(CString(header)));
        `

    C_code `
        if (chunk)
            curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
    `

    code := Int64(0)
    C_code `
        CURLcode res = curl_easy_perform(curl);
        if (res != CURLE_OK)
            fprintf(stderr, "curl_easy_perform() failed: %s\\n", curl_easy_strerror(res));

        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &@code);
    `
    return HTTPResponse(Int(code), "".join(chunks))

func get(url:Text, headers:[Text]=[] -> HTTPResponse)
    return _send(GET, url, none, headers)

func post(url:Text, data="", headers=["Content-Type: application/json", "Accept: application/json"] -> HTTPResponse)
    return _send(POST, url, data, headers)

func put(url:Text, data="", headers=["Content-Type: application/json", "Accept: application/json"] -> HTTPResponse)
    return _send(PUT, url, data, headers)

func patch(url:Text, data="", headers=["Content-Type: application/json", "Accept: application/json"] -> HTTPResponse)
    return _send(PATCH, url, data, headers)

func delete(url:Text, data:Text?=none, headers=["Content-Type: application/json", "Accept: application/json"] -> HTTPResponse)
    return _send(DELETE, url, data, headers)

func main()
    say("GET:")
    say(get("https://httpbin.org/get").body)
    say("Waiting 1sec...")
    sleep(1)
    say("POST:")
    say(post("https://httpbin.org/post", `{"key": "value"}`).body)
    say("Waiting 1sec...")
    sleep(1)
    say("PUT:")
    say(put("https://httpbin.org/put", `{"key": "value"}`).body)
    say("Waiting 1sec...")
    sleep(1)
    say("DELETE:")
    say(delete("https://httpbin.org/delete").body)