Catalog · How the catalog works
CurlClient4Pascal
Fluent, memory-safe HTTP client
- ★ 1 on GitHub
Anyone may press Interesting, signed in or not. It helps others find this project.
README
CurlClient4Pascal a Pascal libcurl HTTP client
Fluent, memory-safe HTTP client for Delphi 12+ and Free Pascal 3.2.2+,
built on libcurl through the supplied vendor/libcurl.pas binding.
uses Http.Client, Http.Response, Http.Curl.Transport; // last unit = libcurl
var
Client: IHttpClient; // always keep it in an interface variable
Resp: IHttpResponse;
begin
Client := NewHttpClient
.SetBaseUrl('https://httpbin.org')
.SetTimeout(10000)
.SetHeader('Accept', 'application/json')
.SetBearerToken('secret');
Resp := Client.Get('/get');
WriteLn(Resp.StatusCode, ' ', Resp.Text);
Resp := Client.PostJson('/post', '{"a":1}').EnsureSuccess;
end;Layout
vendor/libcurl.pas your Chet-generated binding (unchanged)
data/services bundled copy of /etc/services (IANA list)
src/
Http.Defines.inc {$IFDEF FPC}{$MODE DELPHI}{$ENDIF} + string settings
Http.Utils.pas URL/Base64/date helpers (pure Pascal)
Http.Url.pas ParseUrl -> IUrl (parts + iterable query)
Http.Services.pas /etc/services parser (TServiceDatabase), scheme -> port
Http.Logging.pas IHttpLogger, console/file/memory/proc loggers, secret redaction
Http.Interceptors.pas IHttpInterceptor + logging, headers, bearer-token, timing
Http.Errors.pas EHttpError, ECurlError, EHttpStatusError, ...
Http.Headers.pas THttpHeaders (case-insensitive, multi-value)
Http.Cookies.pas THttpCookieJar (RFC 6265 subset, thread-safe)
Http.Request.pas IHttpRequest / THttpRequest (fluent)
Http.Response.pas IHttpResponse / THttpResponse
Http.Options.pas THttpClientOptions record
Http.Transport.pas IHttpTransport (the seam between client and wire)
Http.Client.pas IHttpClient, THttpClient, IHttpClientBuilder
curl/
Http.Curl.Native.pas LOW LEVEL : cdecl callbacks, CURL*/slist owners
Http.Curl.Transport.pas HIGH LEVEL: TCurlHttpClient (IHttpTransport)
examples/ Example.Get / .Post / .Builder / .Upload / .Interceptors
tests/
RunUnitTests.dpr no network, no libcurl needed
RunIntegrationTests.dpr libcurl + local echo server
unit/ integration/ one small file per feature
support/ Test.Framework, Test.FakeTransport, echo_server.py
build.sh / test.sh FPC on Linux/macOS
build.bat / test.bat FPC and/or Delphi on WindowsDesign
- SOLID -
THttpClient(fluent API, header/cookie/option state) depends only onIHttpTransport. libcurl lives inTCurlHttpClient; tests injectTFakeTransport. - Builder -
NewHttpClientBuilder.BaseUrl(..).Timeout(..).Header(..).Build. - Resource safety - every request creates a
CURL*(TCurlEasy), a headercurl_slist(TCurlSlist) and the callback contexts inside nestedtry..finallyblocks:curl_easy_cleanup/curl_slist_free_allalways run. Per-request handles also makeExecutethread-safe. Verified leak-free with FPCheaptrc. - Callbacks - plain
cdeclglobal functions; theCURLOPT_*DATApointer is a Pascal object (TCurlBodySink,TCurlHeaderSink,TCurlBodySource). Exceptions are caught inside the callbacks (never cross the C boundary) and reported through libcurl's return-value protocol. A seek callback lets 307/308 redirects re-send bodies. - Errors - every
curl_easy_setopt/getinfo/performresult is checked and raised asECurlError(Code,CurlMessage=curl_easy_strerror,Detail= error buffer). HTTP 4xx/5xx are not exceptions; callResponse.EnsureSuccess(EHttpStatusError). - Hardening - only
http/https(also after redirects); CR/LF in header values rejected; optionalMaxResponseBytes;CURLOPT_NOSIGNALset; cookies are domain/path/Secure scoped. longportability - variadiccurl_easy_setoptvalues useNativeInt, which is correct forlongon Win32, Win64 (LLP64) and LP64 Unix.
Building and testing
Requirements: libcurl of the same bitness as your compiler target
(Windows: libcurl.dll next to the .exe, or set CURL_DLL_DIR;
Debian/Ubuntu: apt install libcurl4-openssl-dev because the binding imports libcurl.so).
Integration tests need Python 3 (stdlib only) for the echo server and, on Windows, curl.exe.
./build.sh # build examples + test runners -> build/fpc/bin
./test.sh # build, start echo server, run unit + integration + examplesset BDS=C:\Program Files (x86)\Embarcadero\Studio\37.0
build.bat [fpc|delphi|all] [win32|win64]
test.bat [fpc|delphi] [win32|win64]Run the examples against the internet instead: build\fpc\bin\Example.Get (defaults to
https://httpbin.orgg or pass any base URL as the first argument.
Curl in Windows
git clone --depth 1 https://github.com/Microsoft/vcpkg
cd vcpkg
bootstrap-vcpkg.bat
vcpkg integrate install
vcpkg install curl[tool]
cd installed\x64-windows\tools\curl\
copy libcurl.dll my-project
copy z.dll my-projectNotes and limits
- Hold clients in
IHttpClientvariables (reference counted); never keep a bareTHttpClientand call the fluent methods on it. - The Pascal cookie jar keeps cookies from the final response. For redirect chains,
persistence and full RFC semantics use
SetCookieFile(path)(libcurl's engine). - Configure a client before sharing it between threads;
Executeitself is thread-safe. - Not included: async/multi interface, upload/download progress and cancel callbacks.
- Validation status: the full suite (191 unit + 89 integration tests, 5 examples) was
executed with FPC 3.2.2 on Linux/Windows x86-64 and Delphi 13 Version
37.0.57242.3601.

