Session API guide
On this page
Request.Session provides a stateful HTTP client for calls that share a base URL, headers, cookies, or a connection.
Use the stateless Http API for one-off calls. Use THttpSession for a login flow or a group of calls to the same service.
Quick start
uses SysUtils, Request, Request.Session;
var
Session: THttpSession;
Response: TResponse;
begin
Session.SetBaseURL('https://api.example.com');
Session.SetHeader('Authorization', 'Bearer ' + Token);
Response := Session.Get('/profile');
Response.RaiseForStatus;
WriteLn(Response.Text);
end.
THttpSession is an advanced record. It initializes and cleans itself up automatically, so there is no required constructor, Init, Free, or try..finally block.
Session.Init is retained for compatibility and now means “reset this session to its defaults.” It is optional for a newly declared session.
Base URLs
Set a base URL once and pass relative paths:
Session.SetBaseURL('https://api.example.com/v1');
Response := Session.Get('/users');
Slash handling is automatic. These combinations all produce the same URL:
Session.SetBaseURL('https://api.example.com/v1');
Session.Get('users');
Session.SetBaseURL('https://api.example.com/v1/');
Session.Get('/users');
An absolute URL passed to a request method bypasses the base URL.
Headers
Headers set on a session are sent on every request:
Session.SetBearerToken(Token); // Authorization: Bearer ...
Session.SetBasicAuth('user', 'secret'); // or Authorization: Basic ...
Session.SetHeader('Accept-Language', 'en-AU');
Response := Session.Get('/profile');
Authorization is not sent when a redirect goes to a different host.
ClearHeaders removes custom headers and restores the default Accept: application/json header.
The session uses Request-FP/<version> as its default user agent. Override it with:
Session.SetUserAgent('MyApp/1.0');
JSON
Post a JSON string:
Response := Session.PostJSON('/users', '{"name":"Ada"}');
Or pass a TJSONData value:
uses Request, Request.Session, fpjson;
var
Body: TJSONObject;
begin
Body := TJSONObject.Create;
try
Body.Add('name', 'Ada');
Response := Session.PostJSON('/users', Body);
finally
Body.Free;
end;
end;
The caller retains ownership of a JSON value passed to PostJSON. PutJSON and PatchJSON (and TryPutJSON / TryPatchJSON) work the same way.
For other content types, use Post or Put directly:
Response := Session.Post('/submit', 'name=Ada',
'application/x-www-form-urlencoded');
Per-request headers and parameters
Session headers apply to every call. Add or override headers for one call with Get(URL, Headers) or the general Send:
Response := Session.Get('/report', [KV('Accept', 'text/csv')]);
Response := Session.GetWithParams('/search', [KV('q', 'pascal')]);
// Method, URL, Body, ContentType, Headers, Params
Response := Session.Send('PATCH', '/users/42', '{"active":false}',
'application/json', [KV('If-Match', ETag)], []);
Forms and uploads
Response := Session.PostForm('/login', [
KV('email', 'ada@example.com'),
KV('password', Password)
]);
Response := Session.PostMultipart('/upload',
[KV('description', 'avatar')],
[KV('file', 'avatar.png')]);
Downloads
Download and GetToStream stream the body to a file or stream, with session headers and cookies applied:
Response := Session.Download('/reports/2026.pdf', 'report.pdf');
Response := Session.Download('/backup.zip', 'backup.zip', @ShowProgress);
Response := Session.GetToStream('/export.csv', MyStream);
The rules match Http.Download: only a 2xx body is saved, the file is replaced only when complete, and the error body is in Response.Text. TryDownload and TryGetToStream return TRequestResult.
Cookies
Cookies received in Set-Cookie headers are stored and sent by later calls:
- Cookies set on redirect responses (common after a login POST) are kept.
DomainandPathare honoured (RFC 6265): a cookie is only sent to matching hosts and paths. WithoutDomain, only the exact host gets it; withoutPath, the request’s directory is used.- A
Domainthe server is not part of (or a bare top-level name such ascom) is ignored. There is no public-suffix list. Securecookies are only sent overhttps://.Max-AgeandExpiresare tracked; expired cookies are removed.
You can also manage them directly:
Session.SetCookie('session_id', 'abc123');
WriteLn(Session.GetCookie('session_id'));
Session.ClearCookies;
SetCookiecookies are sent with every request, to any host or path, but not when a redirect leaves the host. A server cookie with the same name replaces it.GetCookiereturns the first stored cookie with that name, from any host.
Timeouts
The default timeout is 30 seconds. Values are milliseconds:
Session.SetTimeout(10000);
The new timeout applies to the current connection and later calls. A request that exceeds it raises ETimeoutError. The connect timeout is separate:
Session.SetConnectTimeout(5000); // default 3000
Proxy
Session.SetProxy('proxy.local', 3128, 'user', 'secret');
Session.SetProxy('', 0); // remove
Like Http.SetProxy, this covers http:// URLs only; https:// requests raise ERequestError while a proxy is set.
Retries
Sessions retry GET, HEAD, PUT, and DELETE on network errors, 429, and 503 (2 retries, 250 ms then 500 ms), like the stateless API:
Session.SetRetry(5, 100); // more patient
Session.SetRetry(0, 0); // disable
Reading a response
Session methods return the same TResponse as the stateless API:
if Response.OK then
begin
WriteLn(Response.Text);
WriteLn(Response.HeaderValue('Content-Type'));
end;
The response owns its parsed Response.JSON value; do not free it manually. See the Request API reference for all response helpers.
Error handling
Session methods behave like the stateless API:
- Any HTTP status, including 4xx and 5xx, is returned in the response.
- Network, TLS, and request failures raise
ERequestError(ENetworkError/ETimeoutErrorfor transport failures). - Call
Response.RaiseForStatusto raise for non-2xx. Try*methods never raise; checkResult.SuccessorResult.OK.
Result := Session.TryGet('/profile');
if Result.OK then
WriteLn(Result.Response.Text)
else if Result.Success then
WriteLn('HTTP ', Result.Response.StatusCode)
else
WriteLn('Failed: ', Result.Error);
try
Response := Session.Get('/profile');
Response.RaiseForStatus;
except
on E: ERequestError do
WriteLn('Request failed: ', E.Message);
end;
Before v1.3.1, session methods raised for some non-error statuses (for example Get on 201 or 404) and Post could raise FPC exception types.
API reference
THttpSession = record
// Optional reset
procedure Init;
// Requests
function Get(const URL: string): TResponse;
function Get(const URL: string; const Headers: array of TKeyValue): TResponse;
function GetWithParams(const URL: string; const Params: array of TKeyValue): TResponse;
function Post(const URL: string; const Body: string = '';
const ContentType: string = 'application/x-www-form-urlencoded'): TResponse;
function PostJSON(const URL: string; const JSON: string): TResponse;
function PostJSON(const URL: string; const JSON: TJSONData): TResponse;
function PutJSON(const URL: string; const JSON: string): TResponse; // also TJSONData
function PatchJSON(const URL: string; const JSON: string): TResponse; // also TJSONData
function PostForm(const URL: string; const Fields: array of TKeyValue): TResponse;
function PostMultipart(const URL: string; const Fields, Files: array of TKeyValue): TResponse;
function Put(const URL: string; const Body: string = '';
const ContentType: string = 'application/json'): TResponse;
function Patch(const URL: string; const Body: string = '';
const ContentType: string = 'application/json'): TResponse;
function Delete(const URL: string): TResponse;
function Head(const URL: string): TResponse;
function Send(const Method, URL: string; const Body: string;
const ContentType: string; const Headers: array of TKeyValue;
const Params: array of TKeyValue): TResponse;
// Streaming (OnProgress is optional: TProgressProc or TProgressEvent)
function Download(const URL, FilePath: string; OnProgress): TResponse;
function GetToStream(const URL: string; Stream: TStream; OnProgress): TResponse;
// Exception-free: TryGet, TryPost, TryPostJSON, TryPostForm,
// TryPostMultipart, TryPut, TryPatch, TryDelete, TryHead, TrySend,
// TryDownload, TryGetToStream (same parameters, return TRequestResult)
// Configuration
procedure SetHeader(const Name, Value: string);
procedure SetCookie(const Name, Value: string);
procedure SetBaseURL(const URL: string);
procedure SetUserAgent(const UserAgent: string);
procedure SetTimeout(Timeout: Integer);
procedure SetRetry(MaxRetries, BaseDelayMS: Integer);
procedure SetConnectTimeout(Timeout: Integer);
procedure SetProxy(const Host: string; Port: Integer;
const UserName: string = ''; const Password: string = '');
procedure SetBasicAuth(const UserName, Password: string);
procedure SetBearerToken(const Token: string);
// State
procedure ClearCookies;
function GetCookie(const Name: string): string;
procedure ClearHeaders;
end;
TSimpleMap is public for compatibility but is an implementation detail for most users.
HTTPS
Session requests use the same FPC/OpenSSL stack and automatic Windows OpenSSL 3 filename selection as the stateless API. No session-specific TLS configuration is required.
See the SSL/HTTPS guide if setup fails, or OpenSSL version selection for the FPC 3.2.2 compatibility details.