From 9bb42177d8ed5c4a3a05f08cfecd52f46f128854 Mon Sep 17 00:00:00 2001 From: Dimitri Lozeve Date: Sun, 1 Oct 2023 17:01:26 +0200 Subject: [PATCH] Initial commit: GET requests --- config.bqn | 1 + curl.bqn | 74 ++++++++++++++++++++++++++++++++++++++ ffi.bqn | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++ test.bqn | 7 ++++ utils.bqn | 7 ++++ 5 files changed, 193 insertions(+) create mode 100644 config.bqn create mode 100644 curl.bqn create mode 100644 ffi.bqn create mode 100644 test.bqn create mode 100644 utils.bqn diff --git a/config.bqn b/config.bqn new file mode 100644 index 0000000..7fa79e3 --- /dev/null +++ b/config.bqn @@ -0,0 +1 @@ +libcurlPath⇐"/usr/lib/x86_64-linux-gnu/libcurl.so" diff --git a/curl.bqn b/curl.bqn new file mode 100644 index 0000000..60b1037 --- /dev/null +++ b/curl.bqn @@ -0,0 +1,74 @@ +⟨Get⟩⇐ + +⟨ + easyInit, + easyCleanup, + easySetoptStr, + easySetoptPtr, + easySetoptLong, + easyPerform, + easyGetinfoStr, + easyGetinfoLong, + easyGetinfoDouble, + slistAppend, + slistFreeAll, + fopen, + fclose, + options, + info +⟩←•Import"ffi.bqn" +⟨RandID⟩←•Import"utils.bqn" + +Get←{ +𝕊 url: ⟨⟩ 𝕊 url ; +headers 𝕊 url: + id←RandID 32 + filename←"/tmp/bqncurl."∾id + filePtr←Fopen⟨filename∾@,"w+"⟩ + headerFilename←"/tmp/bqncurl.header."∾id + headerFilePtr←Fopen⟨headerFilename∾@,"w+"⟩ + + session←EasyInit⟨⟩ + + ruseragent←EasySetoptStr⟨session,options.useragent,"curl/bqn"∾@⟩ + ("Error setting user agent: "∾•Fmt ruseragent)!ruseragent=0 + rurl←EasySetoptStr⟨session,options.url,url∾@⟩ + ("Error setting URL: "∾•Fmt rurl)!rurl=0 + rfile←EasySetoptPtr⟨session,options.writedata,filePtr⟩ + ("Error setting file target: "∾•Fmt rfile)!rfile=0 + rheaderfile←EasySetoptPtr⟨session,options.headerdata,headerFilePtr⟩ + ("Error setting header file target: "∾•Fmt rheaderfile)!rheaderfile=0 + rredirect←EasySetoptLong⟨session,options.followlocation,1⟩ + ("Error setting redirect option: "∾•Fmt rredirect)!rredirect=0 + # EasySetoptLong⟨session,options.header,1⟩ + # EasySetoptLong⟨session,options.verbose,1⟩ + + slist←(8↑0){SlistAppend⟨𝕩,𝕨∾@⟩}´headers + rheaders←EasySetoptPtr⟨session,options.httpHeader,slist⟩ + ("Error setting headers: "∾•Fmt rheaders)!rheaders=0 + + rperform←EasyPerform⟨session⟩ + ("Error performing request: "∾•Fmt rperform)!rperform=0 + + SlistFreeAll slist + + rcode‿⟨code⟩←EasyGetinfoLong⟨session,info.responseCode,⟨0⟩⟩ + ("Error retrieving response code: "∾•Fmt rcode)!rcode=0 + # ("Request failed with status code "∾•Fmt code)!2=⌊code÷100 + rtime‿⟨time⟩←EasyGetinfoDouble⟨session,info.totalTime,⟨0.0⟩⟩ + ("Error retrieving request time: "∾•Fmt rtime)!rtime=0 + + Fclose filePtr + Fclose headerFilePtr + content←•file.Bytes filename + responseHeaders←•file.Chars headerFilename + + •file.Remove filename + EasyCleanup session + { + code⇐code, + time⇐time, + headers⇐responseHeaders, + content⇐content, + } +} diff --git a/ffi.bqn b/ffi.bqn new file mode 100644 index 0000000..35a333d --- /dev/null +++ b/ffi.bqn @@ -0,0 +1,104 @@ +⟨ + easyInit, + easyCleanup, + easySetoptStr, + easySetoptPtr, + easySetoptLong, + easyPerform, + easyGetinfoStr, + easyGetinfoLong, + easyGetinfoDouble, + slistAppend, + slistFreeAll, + fopen, + fclose, + options, + info +⟩⇐ + +⟨Hex2Num⟩←•Import"utils.bqn" + +⟨libcurlPath⟩←•Import"config.bqn" + +CurlFFI←libcurlPath⊸•FFI + +curlPtr←"*:i8" +curlOption←"i32" +curlCode←"i32" + +easyInit←CurlFFI curlPtr‿"curl_easy_init" +easyCleanup←CurlFFI ""‿"curl_easy_cleanup"‿(">"∾curlPtr) + +easySetoptStr←CurlFFI curlCode‿"curl_easy_setopt"‿curlPtr‿curlOption‿"*u8:c8" +easySetoptPtr←CurlFFI curlCode‿"curl_easy_setopt"‿curlPtr‿curlOption‿"*:i8" +easySetoptLong←CurlFFI curlCode‿"curl_easy_setopt"‿curlPtr‿curlOption‿"i32" + +easyPerform←CurlFFI curlCode‿"curl_easy_perform"‿curlPtr + +easyGetinfoStr←CurlFFI curlCode‿"curl_easy_getinfo"‿curlPtr‿curlOption‿"&u8:c8" +easyGetinfoLong←CurlFFI curlCode‿"curl_easy_getinfo"‿curlPtr‿curlOption‿"&i32" +easyGetinfoDouble←CurlFFI curlCode‿"curl_easy_getinfo"‿curlPtr‿curlOption‿"&f64" + +slistAppend←CurlFFI "*:i8"‿"curl_slist_append"‿"*:i8"‿"*u8:c8" +slistFreeAll←CurlFFI ""‿"curl_slist_free_all"‿">*:i8" + +fopen←@•FFI "*:i8"‿"fopen"‿"*u8:c8"‿"*u8:c8" +fclose←@•FFI ""‿"fclose"‿">*:i8" + +options←{ + strOffset←10000 + slistOffset←10000 + ptrOffset←10000 + + # boolean options + verbose⇐41 + header⇐42 + noprogress⇐43 + post⇐47 + followlocation⇐52 + httpget⇐80 + + # long integer options + timeout⇐78 # timeout in seconds + timeoutms⇐155 # timeout in milliseconds + + # string options, null-terminated + url⇐strOffset+2 + userpwd⇐strOffset+5 # user:password + useragent⇐strOffset+18 + + # pointer options + writedata⇐ptrOffset+1 + headerdata⇐ptrOffset+29 + + # linked list options + httpHeader⇐slistOffset+23 +} + + +info←{ + strOffset←Hex2Num"100000" + longOffset←Hex2Num"200000" + doubleOffset←Hex2Num"300000" + slistOffset←Hex2Num"400000" + ptrOffset←Hex2Num"400000" + + # long integer info + responseCode⇐longOffset+2 + headerSize⇐longOffset+11 # in bytes + requestSize⇐longOffset+12 # in bytes + redirectCount⇐longOffset+20 + httpVersion⇐longOffset+46 + + # double info + totalTime⇐doubleOffset+3 # in seconds + nameLookupTime⇐doubleOffset+4 # in seconds + connectTime⇐doubleOffset+5 # in seconds + + # string info + effectiveUrl⇐strOffset+1 + contentType⇐strOffset+18 + primaryIP⇐strOffset+32 + httpScheme⇐strOffset+49 + effectiveMethod⇐strOffset+58 +} diff --git a/test.bqn b/test.bqn new file mode 100644 index 0000000..ac11318 --- /dev/null +++ b/test.bqn @@ -0,0 +1,7 @@ +⟨Get⟩←•Import"curl.bqn" + +r←⟨"Hello: World","Blabla: Blublu"⟩Get"http://httpbin.org/get?key=value" +r.code +r.headers +r.content +r.time diff --git a/utils.bqn b/utils.bqn new file mode 100644 index 0000000..9af859d --- /dev/null +++ b/utils.bqn @@ -0,0 +1,7 @@ +⟨Hex2Num,RandID⟩⇐ + +# Parse hexadecimal number +Hex2Num←{16⊸×⊸+˜´⌽(∾"0A"+⟜↕¨10‿6)⊐𝕩} + +# random alphanumeric ID of 𝕩 characters +RandId←{(𝕩•rand.Range 62)⊏∾"0aA"+¨↕¨10‿26‿26}