Browse documentation

Request API reference

On this page

This unit provides the stateless Request-FP API. Add Request to the uses clause and call methods on the global Http value.

For a task-oriented overview, start with Getting started. For shared cookies and configuration, see the session guide.

First request

uses Request;

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

No request or response objects need to be freed.

Key/value pairs

Headers, query parameters, forms, and multipart requests use TKeyValue. KV is the concise constructor:

KV('Authorization', 'Bearer ' + Token)

It is equivalent to:

TKeyValue.Create('Authorization', 'Bearer ' + Token)

THttp

GET

Http.Get(URL)
Http.Get(URL, Headers)
Http.Get(URL, Headers, Params)
Http.GetWithParams(URL, Params)

Examples:

Response := Http.Get('https://api.example.com/users');

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

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

POST

Use Post for a body that is already encoded:

Http.Post(URL, Body)
Http.Post(URL, Body, Headers)
Http.Post(URL, Body, Headers, Params)

When Body is not empty and no content type was supplied, Post uses application/x-www-form-urlencoded.

Form POST

Use PostForm to let Request-FP encode form fields:

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

Names and values are percent-encoded as UTF-8.

JSON POST

PostJSON accepts either a JSON string or TJSONData and sets Content-Type: application/json.

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

Passing a JSON object does not transfer ownership. The caller remains responsible for freeing it:

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;

Passing nil in place of TJSONData raises ERequestError.

PUT, PATCH, DELETE, and HEAD

Http.Put(URL, Body)
Http.Put(URL, Body, Headers)
Http.Put(URL, Body, Headers, Params)

Http.Patch(URL, Body)
Http.Patch(URL, Body, Headers)
Http.Patch(URL, Body, Headers, Params)

Http.Delete(URL)
Http.Delete(URL, Headers)
Http.Delete(URL, Headers, Params)

Http.Head(URL)
Http.Head(URL, Headers)
Http.Head(URL, Headers, Params)

For JSON, use PutJSON and PatchJSON (string or TJSONData, optional Headers, plus TryPutJSON / TryPatchJSON):

Http.PutJSON(URL, '{"name":"Ada"}');
Http.PatchJSON(URL, Body);  // TJSONData; you keep ownership

Authentication

Http.Get(URL, [KVBearer(Token)]);
Http.Get(URL, [KVBasic('user', 'secret')]);

Authorization is dropped when a redirect goes to a different host, so credentials are not sent to another server.

Proxy

Http.SetProxy('proxy.local', 3128);                   // all Http requests
Http.SetProxy('proxy.local', 3128, 'user', 'secret'); // with proxy auth
Http.SetProxy('', 0);                                 // remove

The proxy is used for http:// URLs only. FPC 3.2.2 cannot tunnel HTTPS through a proxy, so an https:// request raises ERequestError while a proxy is set.

Timeout

Http.SetTimeout(10000); // milliseconds, all stateless requests
WriteLn(Http.GetTimeout);

The default is 30000. 0 waits forever. It is the I/O timeout.

The connect timeout is separate (default 3000 ms; 0 uses the system default). Both raise ETimeoutError:

Http.SetConnectTimeout(5000);
WriteLn(Http.GetConnectTimeout);

Multipart POST

Http.PostMultipart(URL, Fields, Files)
Http.PostMultipart(URL, Fields, Files, Headers)
Http.PostMultipart(URL, Fields, Files, Headers, Params)

Each item in Files maps a multipart field name to a local file path:

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

Downloads and streaming

Download and GetToStream write the body as it arrives, so large files never sit in memory:

Http.Download(URL, FilePath)
Http.Download(URL, FilePath, OnProgress)
Http.Download(URL, FilePath, Headers, Params)
Http.Download(URL, FilePath, Headers, Params, OnProgress)

Http.GetToStream(URL, Stream)                 // same four forms
procedure ShowProgress(Received, Total: Int64);
begin
  if Total > 0 then
    Write(#13, Received * 100 div Total, '%');
end;

Response := Http.Download('https://example.com/big.zip', 'big.zip',
  @ShowProgress);
if not Response.OK then
  WriteLn('Failed: ', Response.StatusCode, ' ', Response.Text);

Exception-free methods

The Try* methods return TRequestResult rather than allowing request exceptions to escape:

Http.TryGet(URL)
Http.TryGet(URL, Headers)
Http.TryGet(URL, Headers, Params)
Http.TryGetWithParams(URL, Params)

Http.TryPost(URL, Body)
Http.TryPost(URL, Body, Headers)
Http.TryPost(URL, Body, Headers, Params)

Http.TryPostForm(URL, Fields)
Http.TryPostForm(URL, Fields, Headers)
Http.TryPostForm(URL, Fields, Headers, Params)

Http.TryPostJSON(URL, JSON)
Http.TryPostJSON(URL, JSON, Headers)
Http.TryPostJSON(URL, JSON, Headers, Params)

Http.TryPut(URL, Body)
Http.TryPut(URL, Body, Headers)
Http.TryPut(URL, Body, Headers, Params)

Http.TryPatch(URL, Body)
Http.TryPatch(URL, Body, Headers)
Http.TryPatch(URL, Body, Headers, Params)

Http.TryDelete(URL)
Http.TryDelete(URL, Headers)
Http.TryDelete(URL, Headers, Params)

Http.TryHead(URL)
Http.TryHead(URL, Headers)
Http.TryHead(URL, Headers, Params)

Http.TryPostMultipart(URL, Fields, Files)
Http.TryPostMultipart(URL, Fields, Files, Headers)
Http.TryPostMultipart(URL, Fields, Files, Headers, Params)

TryPostJSON accepts both JSON strings and TJSONData.

Example:

Result := Http.TryGet('https://api.example.com/users/42');
if Result.OK then
  WriteLn(Result.Response.Text)
else if not Result.Success then
  WriteLn(Result.Error)
else
  WriteLn('HTTP status: ', Result.Response.StatusCode);

Success and OK answer different questions:

TResponse

Members

StatusCode: Integer
Text: string
JSON: TJSONData
OK: Boolean

function HeaderValue(const Name: string): string;
function HeaderValues(const Name: string): TStringArray;
function HeaderNames: TStringArray;
function IsSuccessStatus: Boolean;
procedure RaiseForStatus;
procedure SaveToFile(const FilePath: string);
procedure SaveToStream(Stream: TStream);
function Bytes: TBytes;

The response owns the value returned by JSON. Do not free that value or a child obtained with FindPath.

TRequestResult

Success: Boolean
Response: TResponse
Error: string
OK: Boolean

When Success is false, Error contains the caught exception message and Response.StatusCode is zero.

Error policy

Stateless methods separate transport success from HTTP status:

Retries

Requests are retried automatically, so short outages and rate limits often go unnoticed:

Http.SetRetry(5, 100);  // 5 retries: 100, 200, 400, 800, 1600 ms
Http.SetRetry(0, 0);    // disable
WriteLn(Http.GetRetryCount, ' retries, first delay ', Http.GetRetryDelay, ' ms');

Sessions have their own Session.SetRetry with the same defaults.

HTTPS

Request-FP uses FPC’s OpenSSL support. On Windows, it automatically works around FPC 3.2.2’s DLL-name issue by selecting the standard OpenSSL 3 names first while retaining FPC’s OpenSSL 1.1 fallback. The installed DLL architecture must still match the executable.

OpenSSL loads on the first HTTPS request, so HTTP-only programs run without it. Call EnsureSSL at startup to fail fast instead; it raises ERequestError with setup hints if OpenSSL cannot be loaded.

If HTTPS setup fails, run examples/ssl_debug and follow the SSL/HTTPS guide. For the exact Windows loading order, see OpenSSL version selection.