Free and easy-to-use client-side URL transfer library supporting almost every protocol.
Website: https://curl.se/libcurl/
Platforms supported: Windows (32-bit and 64-bit), Linux, macOS, FreeBSD, Haiku
Headers to include: curl.bi
Header version: 7.85.0
Examples: in examples/network/curl/
Haiku R1 beta 6 amd64: `examples/manual/libraries/curl.bas` compiled and ran
with FreeBASIC 1.20.4-3 against HaikuPorts libcurl 8.22.0, fetching and
checking the exact response from a local loopback HTTP fixture.
The declarations describe libcurl 7.85.0. The Windows qualification uses the installed 32-bit and 64-bit libcurl 8.21.0 SDKs and compares stable C types and form-list layouts with the native C headers. This does not add newer APIs to
curl.bi. The HTTP fixtures test loopback transfers; they do not establish HTTPS certificate or public-server interoperability.
The example accepts a URL as its first command-line argument. It prints the exact callback bytes, including embedded zeros, without adding a newline for each callback. It checks option and transfer errors, returns a failing process status for HTTP and transport errors, and balances global initialization and easy-handle cleanup. Its connection deadline is five seconds and its complete transfer deadline is fifteen seconds.
CURLOPT_* options which take C
long must receive a
Clong argument in varargs on 64-bit Windows.
The
CHttp examples build a static library from
CHttp.bas,
CHttpStream.bas and
CHttpForm.bas before linking
test.bas. Each connection owns its easy handle and header list. A stream with a supplied connection borrows it, so that connection must outlive the stream. These owning example objects are used synchronously on one thread and must not be copied.
CHttpStream.read(TRUE) returns exactly the response body, without the internal C terminator; a text read stops at the first zero.
send() uploads the caller's bytes synchronously using
CURLOPT_UPLOAD (PUT for HTTP), including an empty body. It keeps response storage separate from the borrowed upload buffer and supplies a seek callback so a redirected upload can be rewound. It removes stack-backed read and seek userdata before returning.
read() can retrieve the upload response. Transfer failures clear partial response data. The wrapper treats HTTP status policy as a caller option; the standalone manual example enables
CURLOPT_FAILONERROR.
CHttpForm retains the original
curl_formadd multipart interface, which libcurl has deprecated in favor of the MIME API. It remains an example of that original binding, and should be linked against a libcurl build which still exposes it.
See the libcurl
write callback,
upload,
seek callback, and
global initialization references for the underlying API contracts.
Example
'' FreeBASIC manual examples
'' File: curl.bas
'' Purpose: Fetch a URL with libcurl's easy interface.
'' Responsibilities: Preserve callback bytes, report errors, and release curl state.
'' This file contains no redirects, retries or asynchronous transfers.
'' See Also: https://www.freebasic.net/wiki/wikka.php?wakka=ExtLibcurl
#include Once "curl.bi"
#include Once "crt/string.bi"
'' libcurl supplies a byte count, not a terminated string. A FreeBASIC STRING
'' preserves embedded zeros; the semicolon avoids adding callback-dependent
'' newlines. The temporary chunk belongs to this synchronous callback only.
Private Function write_callback cdecl ( ByVal buffer As Byte Ptr, _
ByVal size As size_t, _
ByVal nitems As size_t, _
ByVal userdata As Any Ptr ) As size_t
Dim maximum As size_t = Cast( size_t, -1 )
If( size <> 0 AndAlso nitems > maximum \ size ) Then Return 0
Dim bytes As size_t = size * nitems
If( bytes > (maximum Shr 1) ) Then Return 0
If( bytes <> 0 AndAlso buffer = NULL ) Then Return 0
Dim chunk As String = Space( bytes )
If( Len( chunk ) <> bytes ) Then Return 0
If( bytes <> 0 ) Then memcpy( StrPtr( chunk ), buffer, bytes )
Print chunk;
Return bytes
End Function
Function main() As Integer
Dim url As String = Command(1)
If( Len( url ) = 0 ) Then url = "https://freebasic.net/"
If( curl_global_init( CURL_GLOBAL_ALL ) <> CURLE_OK ) Then Return 1
Dim handle As CURL Ptr = curl_easy_init( )
If( handle = NULL ) Then
curl_global_cleanup( )
Return 1
End If
'' Long options use C long in varargs, including on 64-bit Windows.
'' Bound the wait to five seconds for connection and fifteen in total.
Dim As clong connect_timeout = 5000, total_timeout = 15000, fail_http = 1
Dim result As CURLcode = CURLE_FAILED_INIT
Do
If( curl_easy_setopt( handle, CURLOPT_URL, StrPtr( url ) ) <> CURLE_OK ) Then Exit Do
If( curl_easy_setopt( handle, CURLOPT_WRITEFUNCTION, @write_callback ) <> CURLE_OK ) Then Exit Do
If( curl_easy_setopt( handle, CURLOPT_CONNECTTIMEOUT_MS, connect_timeout ) <> CURLE_OK ) Then Exit Do
If( curl_easy_setopt( handle, CURLOPT_TIMEOUT_MS, total_timeout ) <> CURLE_OK ) Then Exit Do
If( curl_easy_setopt( handle, CURLOPT_FAILONERROR, fail_http ) <> CURLE_OK ) Then Exit Do
result = curl_easy_perform( handle )
Loop While False
If( result <> CURLE_OK ) Then Print "curl transfer failed: "; *curl_easy_strerror( result )
curl_easy_cleanup( handle )
curl_global_cleanup( )
If( result <> CURLE_OK ) Then Return 1
Return 0
End Function
End main()
'' end of curl.bas