From Newsgroup: comp.lang.forth
okflo@teletyp.ist writes:
hi forthers,
I am trying to do a (very simple and naive) http-request
with gforth (current from git):
[...]
Hi,
following up to my own post, I did nearly a year ago:
Some days ago I came back to forth and finally grasped the ffi of
gforth. Great stuff - especially the simple way to make c-callbacks!
Gforth's documentation doesn't include any example, so - perhaps my implementation, see below, helps someone else. See also at
https://teletyp.ist/blog/entries/Doing-http-requests-with-gforth-and-libcurl.html
for web-reference.
Let me also address some questions to the experienced forthers:
- I use global variables (in the dictionary) for curl-data and
response-code. What would be the right way to do this locally in
http-request? The usual locals are on a stack IMHO - so I would need
to allocate cells?
- What is the best way, to convert an sstring to a cstring? I was
wondering, that there is a cstring>sstring in gforth, but not the
other way sstring>cstring?
- Please raise any other detail, I did wrong! ;)
best regards & many thanks for any hints in advance - okflo
#+begin_src forth
\ http-request bindings to libcurl for gforth (>= 0.7.9)
c-library curl
s" curl-gnutls" add-lib
\c #include <curl/curl.h>
\c #include <curl/easy.h>
c-value curl-global-all CURL_GLOBAL_ALL -- n
c-value curle-ok CURLE_OK -- n
c-value curlopt-url CURLOPT_URL -- n
c-value curlopt-customrequest CURLOPT_CUSTOMREQUEST -- n
c-value curlopt-writefunction CURLOPT_WRITEFUNCTION -- n
c-value curlopt-writedata CURLOPT_WRITEDATA -- n
c-value curlopt-useragent CURLOPT_USERAGENT -- n
c-value curlinfo-response-code CURLINFO_RESPONSE_CODE -- n
c-function curl-global-init curl_global_init n -- void
c-function curl-easy-init curl_easy_init void -- a
c-function curl-easy-setopt curl_easy_setopt a n a -- void
c-function curl-easy-perform curl_easy_perform a -- a
c-function curl-easy-getinfo curl_easy_getinfo a n a -- void
c-function curl-easy-cleanup curl_easy_cleanup a -- void
c-callback make-receive-request a n n a -- n
end-c-library
: receive-request ( data chunksize nmemb usrptr )
-rot * swap over >r $+! r> ;
' receive-request make-receive-request constant recv
: >cstring ( addr u -- c-string-addr )
[ s\" \0" ] 2literal s+ drop ;
s" GET" >cstring constant method-get
s" POST" >cstring constant method-post
s" PUT" >cstring constant method-put
s" DELETE" >cstring constant method-delete
s" PATCH" >cstring constant method-patch
variable curl-data
variable response-code
: http-request ( method url-addr url-len -- status content-addr content-len )
curl-data $init
curl-global-all curl-global-init
curl-easy-init { curl }
curl 0= if ." CURL initialization failed..." quit then
>cstring curl curlopt-url rot curl-easy-setopt
curl curlopt-customrequest rot curl-easy-setopt
curl curlopt-writefunction recv curl-easy-setopt
curl curlopt-writedata curl-data curl-easy-setopt
curl curl-easy-perform
curle-ok <> if ." CURL perform failed..." quit then
curl curlinfo-response-code response-code curl-easy-getinfo
curl curl-easy-cleanup
response-code @
curl-data $@
save-mem
curl-data $free ; \ you'll have to make sure, to free memory on your own!
: my-example ( -- )
method-get s"
https://example.com" http-request
2dup type
drop free ;
#+end_src
--- Synchronet 3.21a-Linux NewsLink 1.2