Skip to content

Repository files navigation

Request-FP

Request-FP — easy HTTP for Free Pascal

License: MIT Free Pascal Lazarus Supports Windows Supports Linux Version

An easy, memory-safe HTTP client for Free Pascal. Request-FP wraps FPC's HTTP stack with a small API, automatic cleanup, and no application-level dependencies.

Start here

Add src to your unit search path and make a request:

uses Request;

var
  Response: TResponse;
begin
  Response := Http.Get('https://api.example.com/users');
  Response.RaiseForStatus;
  WriteLn(Response.Text);
end.

There is no client to create or free. TResponse cleans itself up.

Use the stateless Http API for one-off requests. Use THttpSession when requests need to share a base URL, headers, or cookies.

Common requests

Query parameters

KV is the short syntax for a header, query parameter, form field, or multipart field:

Response := Http.GetWithParams('https://api.example.com/search', [
  KV('q', 'free pascal'),
  KV('page', '2')
]);

Request-FP percent-encodes names and values as UTF-8.

Headers and query parameters together

Response := Http.Get('https://api.example.com/search',
  [KV('Authorization', 'Bearer ' + Token)],
  [KV('q', 'free pascal')]);

The second array is headers and the third is query parameters. TKeyValue.Create(...) remains available for existing code.

Form data

Response := Http.PostForm('https://api.example.com/login', [
  KV('email', 'ada@example.com'),
  KV('password', Password)
]);

PostForm performs the form encoding and sets application/x-www-form-urlencoded. Use Http.Post when the body is already encoded or is another content type.

JSON

Post a JSON string:

Response := Http.PostJSON(
  'https://api.example.com/users',
  '{"name":"Ada"}'
);

Or pass an existing TJSONData value directly:

uses Request, fpjson;

var
  Body: TJSONObject;
begin
  Body := TJSONObject.Create;
  try
    Body.Add('name', 'Ada');
    Response := Http.PostJSON('https://api.example.com/users', Body);
  finally
    Body.Free;
  end;
end;

Request-FP reads JSON responses lazily:

WriteLn(Response.JSON.FindPath('user.name').AsString);

Response owns the parsed value returned by Response.JSON. Do not free that value yourself. Invalid JSON raises ERequestError with a JSON Parse Error message.

Multipart file upload

Response := Http.PostMultipart('https://api.example.com/upload',
  [KV('description', 'avatar')],
  [KV('file', 'avatar.png')]);

The key in the files array is the form field name; the value is the local file path.

Handling success and errors

Choose the style that fits your program.

Exceptions for transport errors

Normal methods raise ERequestError for network, TLS, and request failures. Inspect the response or opt in to raising for a non-2xx status:

try
  Response := Http.Get('https://api.example.com/users/42');
  Response.RaiseForStatus;
  WriteLn(Response.Text);
except
  on E: ERequestError do
    WriteLn(E.Message);
end;

You can also branch without raising:

if Response.OK then
  WriteLn(Response.Text)
else
  WriteLn('HTTP status: ', Response.StatusCode);

Response.OK and Response.IsSuccessStatus are true for status codes 200 through 299.

No exceptions

Every Try* method catches request exceptions:

Result := Http.TryGet('https://api.example.com/users/42');
if Result.OK then
  WriteLn(Result.Response.Text)
else if not Result.Success then
  WriteLn('Request failed: ', Result.Error)
else
  WriteLn('HTTP status: ', Result.Response.StatusCode);
  • Result.Success means the HTTP exchange completed, even if the server returned 404 or 500.
  • Result.OK means the exchange completed and the status is 2xx.
  • TryGet, TryGetWithParams, TryPost, TryPostForm, TryPostJSON, TryPut, TryDelete, and TryPostMultipart do not raise request exceptions.

Sessions

Add Request.Session when calls should share configuration or cookies:

uses Request, Request.Session;

var
  Session: THttpSession;
  Response: TResponse;
begin
  Session.SetBaseURL('https://api.example.com');
  Session.SetHeader('Authorization', 'Bearer ' + Token);

  Response := Session.Get('/profile');
  if Response.OK then
    WriteLn(Response.Text);
end.

Sessions initialize and clean themselves up automatically. You do not need to call Session.Init; call it only when you want to reset an existing session to its defaults.

The base URL works with or without a trailing slash, and paths work with or without a leading slash.

Post JSON with the same convenience as the stateless API:

Response := Session.PostJSON('/profile', '{"displayName":"Ada"}');

See the session guide for cookies, timeouts, and the complete API.

Installation

  1. Copy src/Request.pas and, if needed, src/Request.Session.pas into your project, or clone this repository.
  2. Add the src directory to the project's unit search path.
  3. Add Request to your uses clause.

Requirements:

  • Free Pascal 3.2.2+ or Lazarus 4.8+
  • Windows or Linux
  • OpenSSL libraries for HTTPS

On Linux, install the distribution's OpenSSL development package. On Windows, the OpenSSL DLL architecture must match the executable architecture. Request-FP v1.3.0 automatically handles FPC 3.2.2's OpenSSL 3 DLL-name issue and retains its OpenSSL 1.1 fallback; applications do not need to patch FPC. If HTTPS setup fails, run examples/ssl_debug and follow the SSL/HTTPS guide.

API at a glance

// Requests
Http.Get(URL)
Http.GetWithParams(URL, Params)
Http.Post(URL, Body)
Http.PostForm(URL, Fields)
Http.PostJSON(URL, JSON)
Http.Put(URL, Body)
Http.Delete(URL)
Http.PostMultipart(URL, Fields, Files)

// Response
Response.StatusCode
Response.Text
Response.JSON
Response.OK
Response.HeaderValue('Content-Type')
Response.RaiseForStatus
Response.SaveToFile('output.dat')

Most methods also have header/query-parameter overloads and exception-free Try* counterparts. See the API reference for exact signatures.

Documentation and examples

Build all examples

The repository includes scripts that compile every Lazarus example in Release mode and collect the executables in example-bin/.

Windows PowerShell:

.\build-examples.ps1

If script execution is disabled by local policy:

powershell -ExecutionPolicy Bypass -File .\build-examples.ps1

Linux or Git Bash:

bash ./build-examples.sh

Both scripts require lazbuild on PATH. They discover all .lpi projects under examples/, skip Lazarus backup directories, and clean example-bin/ before compiling. The generated directory is ignored by Git.

Run an example after building:

.\example-bin\easy_get.exe
./example-bin/easy_get

Testing

Build the suite with Lazarus or:

lazbuild --build-mode=Release tests/TestRunner.lpi
tests/TestRunner.exe -a --format=plain

On Linux, run tests/TestRunner. CI starts tests/http_fixture.py and points the suite at that local service, so CI does not depend on a public HTTP test service. A direct local run without REQUEST_FP_TEST_BASE_URL falls back to https://httpbin.org and therefore requires network access.

Contributing

See CONTRIBUTING.md.

License

Request-FP is available under the MIT License.

About

Zero‑memory‑leak, high‑level HTTP client for Free Pascal. Built on top of FPC's HTTP stack with a clean API and zero boilerplate.

Topics

Resources

Code of conduct

Contributing

Stars

17 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages