Using an HTTP Client
Go Up to Using the RTL in Multi-Device Applications
The RTL provides two components that you can use to send HTTP requests to servers and handle their responses:
Contents
- 1 Configuring Your Application at Design Time
- 2 Sending a Request and Handling its Response
- 3 Managing Cookies
- 4 Handling Redirects
- 5 Handling the Download of the Response Data
- 6 Sending a Request with Custom Headers
- 7 Handling Secure Connections
- 8 Handling Authentication and Certificates
- 9 Making Requests Asynchronous
- 10 See Also
Configuring Your Application at Design Time
Creating an HTTP Client
To create an HTTP client that you can use to send HTTP request, drag a TNetHTTPClient from the Tool Palette onto a form or data module of your application. The TNetHTTPClient does not require any initial configuration.
Creating and Configuring HTTP Requests
You also need to drop one or more TNetHTTPRequest components onto your form or data module.
After you drop your new HTTP request component, double-click its Client property on the Object Inspector so that its value is the HTTP client component that you previously dropped.
You can use any number of request components that you like. However, if you need to send several different HTTP requests, a better approach might be to use a single HTTP request component and reconfigure that component at run time to send each request.
Sending a Request and Handling its Response
Sending an HTTP Request
To send an HTTP request, you must specify at least the following:
- HTTP request method
- A resource URL
The HTTP request method determines the action that you want the server to perform on the resource located at the specified URL, such as sending you the data of the resource or updating the resource with data that you include in your request.
How you send an HTTP request using a TNetHTTPRequest component depends on the HTTP request method that you want to use.
Sending an HTTP Request Using the DELETE, GET, HEAD, OPTIONS, or TRACE HTTP Request Methods
The following HTTP request methods do not require input data other than the target resource URL:
To send an HTTP request using any of these HTTP request methods, first configure your request at design time:
- Configure the URL property with the URL of the target resource.
- Configure the MethodString property with the name of the HTTP request method that you want to use.
Then call Execute to send your request.
Sending an HTTP Request Using the MERGE, PATCH, or PUT HTTP Request Methods
In addition to the target resource URL, the following HTTP request methods require input data:
To send an HTTP request using any of these HTTP request methods, call its matching function as shown in the table below. In your call, specify the URL of the target resource as your first argument and an instance of TStream as your second argument.
HTTP Request Method | TNetHTTPRequest Function |
---|---|
PUT | Put |
PATCH | Patch |
MERGE | Merge |
PATCH through PUT* | PatchAlternative |
MERGE through PUT* | MergeAlternative |
- * Some HTTP proxies do not support the latest standard HTTP request methods (such as PATCH) or non-standard HTTP request methods (such as MERGE). In these cases, you can proxy HTTP request methods through another HTTP request method. To do this, the request includes headers that specify the intended HTTP request method.
Sending an HTTP Request Using the POST HTTP Request Method
In addition to the target resource URL, the POST HTTP request method requires input data.
To send an HTTP request using the POST HTTP request method, call Post. In your call, you must specify the URL of the target resource as your first argument. The other arguments depend on how you want to provide the input data of your request:
- To send the content of a local file, specify the local path to that file as the second argument of your call.
- To send the content of a stream, provide your instance of TStream as the second argument of your call.
- To send form data encoded as a MIME multipart message following the HTML 4 standard, provide your instance of TMultipartFormData as the second argument of your call.
- To send the content of a string list, provide your instance of TStrings as the second argument of your call, and if your strings are not encoded in UTF-8, provide an instance of TEncoding as the fourth argument. For example:
Delphi:
NetHTTPRequest1.Post('http://www.example.com/rest/items', String1, nil, TEncoding.Default);
C++:
NetHTTPRequest1->Post("http://www.example.com/rest/items", String1, NULL, TEncoding::Default);
Handling an HTTP Response
When the target server sends a response to your request, the OnRequestCompleted event of your HTTP request component occurs. Define an event handler for this event to read the data from the server response. If there is an error during your request, the OnRequestError event of your HTTP request component occurs instead.
The event handler of OnRequestCompleted receives two parameters:
Sender
is your HTTP request component.AResponse
in an object that implements the IHTTPResponse interface.
You can obtain all the response data from AResponse
:
- Version indicates the version of the HTTP protocol that the server used.
- StatusCode contains the status code of the response, and StatusText contains a human-readable text that describes the status, such as "OK" when StatusCode is 200.
- ContentAsString contains the body of the response as a string. You may also read the raw data of the response body as a stream from ContentStream.
- You may read the response headers using Headers, HeaderValue, ContainsHeader, or any of the following helper properties that provide the value of common HTTP response header fields: ContentCharSet, ContentEncoding, ContentLanguage, ContentLength, Date, LastModified, MimeType.
- Cookies contains the cookies of the server response.
Managing Cookies
The AllowCookies property of the HTTP client component allows you to specify whether you want to accept the cookies that the server sends in the response.
If AllowCookies is True
, the HTTP client saves the received cookies in his CookieManager.
Handling Redirects
Use the HandleRedirects property to control how the HTTP client component handles redirects. The default value is True
, which means that the HTTP client component automatically follows redirects.
Use the MaxRedirects property of the HTTP client component to specify a maximum number of redirects that you allow the component to follow. If the HTTP client component reaches the specified number of maximum redirects, it raises an exception of type ENetHTTPRequestException.
Handling the Download of the Response Data
As your HTTP client downloads the response to your request, the OnReceiveData event of your HTTP request object keeps occurring. Provide an event handler for OnReceiveData to keep track of the progress of the download of the response data. Your event handler receives the following parameters:
Sender
, which is your HTTP request object.AContentLength
, which is the expected length of the response data in number of bytes.AReadCount
, which is the number of bytes of the response data that the HTTP client has downloaded so far.Abort
, which is a Boolean parameter that allows you to cancel the download.
When the download finishes, OnReceiveData occurs for the last time, and the values of AContentLength
and AReadCount
are the same. OnRequestCompleted occurs soon afterwards.
Tracking the Progress of the Download of the Response Data
To track the progress of the downloaded data, use the values of AContentLength
and AReadCount
in the OnReceiveData event handler.
This is an example that calculates the percentage of the downloaded data:
Delphi:
procedure TForm1.NetHTTPRequest1ReceiveData(const Sender: TObject;
AContentLength, AReadCount: Int64; var Abort: Boolean);
var
percentageDownloaded:Double;
begin
if AContentLength > 0 then
percentageDownloaded := (AReadCount / AContentLength) * 100;
else
// the server did not provide the Content-Length header
end;
C++:
void __fastcall TForm1::NetHTTPRequest1ReceiveData(TObject * const Sender, __int64 AContentLength,
__int64 AReadCount, bool &Abort)
{
float percentageDownloaded;
if (AContentLength > 0)
{
percentageDownloaded = ((float)AReadCount / (float)AContentLength) * 100.f;
}
else
{
// the server did not provide the Content-Length header
}
}
Canceling the Download of the Response Data
To cancel the download of the response data, change the value of Abort
to True
in the OnReceiveData event handler.
Sending a Request with Custom Headers
The HTTP client component and the HTTP request component both allow you to set custom headers. The custom headers that you can specify are:
- In the HTTP client component:
- In the HTTP request component:
When you execute a request, the THTTPClient.Execute method of the HTTP framework combines the custom headers from the HTTP client component and the corresponding HTTP request component and adds those headers to the final request.
Handling Secure Connections
The HTTP client component supports secure (HTTPS) connections. The HTTP framework automatically handles any certificate request that occurs and fires the appropriate event if necessary:
- OnNeedClientCertificate when a server requests a certificate from the client.
- OnValidateServerCertificate if the server provides an invalid certificate.
For more information about handling certificates, see the Handling Server-side Certificates and the Handling Client-side Certificates section for more information.
Handling Authentication and Certificates
Handling HTTP Basic Access Authentication
When you send an HTTP request to a server that requires HTTP basic access authentication, the OnAuthEvent of your HTTP client object occurs. To submit your access credentials, provide an event handler for this event and, if the value of the second parameter that the event handler receives (AnAuthTarget
) is TAuthTargetType.Server, fill the AUserName
and APassword
variables with your username and password for HTTP access. For example:
Delphi:
procedure TForm1.NetHTTPClient1AuthEvent(const Sender: TObject;
AnAuthTarget: TAuthTargetType; const ARealm, AURL: string;
var AUserName, APassword: string; var AbortAuth: Boolean;
var Persistence: TAuthPersistenceType);
begin
if AnAuthTarget = TAuthTargetType.Server then
begin
AUserName := 'MyUsername';
APassword := '1234';
end;
end;
C++:
void __fastcall TForm1::NetHTTPClient1AuthEvent(TObject * const Sender,
TAuthTargetType AnAuthTarget, const UnicodeString ARealm,
const UnicodeString AURL, UnicodeString &AUserName, UnicodeString &APassword,
bool &AbortAuth, TAuthPersistenceType &Persistence)
{
if (AnAuthTarget == TAuthTargetType::Server) {
AUserName = "MyUsername";
APassword = "1234";
}
}
Your event handler also receives the realm of the HTTP server that requires authentication (ARealm
) and the target URL of your request (AURL
).
To abort the HTTP authentication process, change the value of AbortAuth
to True
.
Sending a Request Behind a Proxy
When you are behind a proxy that requires authentication, you can define your proxy settings that are used for authentication. This example demonstrates how to do that:
Delphi:
NetHTTPClient1.ProxySettings := TProxySettings.Create('192.168.1.1', 8080, 'MyUserName', 'MyPassword');
C++:
TProxySettings MyProxySettings("192.168.1.1", 8080, "MyUserName", "MyPassword", "");
NetHTTPClient1->ProxySettings = MyProxySettings;
Another way to specify your proxy settings is to provide a URL string that includes the proxy-related information:
Delphi:
NetHTTPClient1.ProxySettings := TProxySettings.Create('http://MyUserName:[email protected]:8080');
C++:
TProxySettings MyProxySettings("http://MyUserName:[email protected]:8080");
NetHTTPClient1->ProxySettings = MyProxySettings;
Alternatively, you can specify the credential for proxy authentication in the OnAuthEvent event handler. See the Handling HTTP Basic Access Authentication section, and check that the value of AnAuthTarget
is TAuthTargetType.Proxy
instead of TAuthTargetType.Server
.
Handling System Proxy Settings With an HTTP Client
The following table explains how the HTTP Client handles the system proxy settings on different platforms:
Platform | Behavior |
---|---|
Windows |
The HTTP Client uses the system proxy settings. You can bypass the system proxy settings and you can also provide alternative proxy settings for the HTTP Client. To bypass the system proxy settings, create proxy settings for the HTTP Client and specify |
macOS |
The HTTP Client always uses the system proxy settings. Even if you provide alternative proxy settings for the HTTP Client, the HTTP Client uses the system proxy settings. |
iOS |
The HTTP Client always uses the system proxy settings. Even if you provide alternative proxy settings for the HTTP Client, the HTTP Client uses the system proxy settings. |
Android |
The HTTP Client uses the system proxy settings. You cannot bypass those settings, but you can provide alternative proxy settings for the HTTP Client. |
Linux |
The HTTP Client uses the system proxy settings. You cannot bypass those settings, but you can provide alternative proxy settings for the HTTP Client. |
Managing the Storage of User Credentials
TNetHTTPClient allows you to store credentials for HTTP or proxy authentication. Each stored credential can contain a username, a password, an authentication target type, a realm and a target URL.
This example demonstrates how to use TNetHTTPClient.CredentialsStorage to save a credential and then use that credential to authenticate when connecting to an HTTP server that requires basic authentication:
- Create a credential and add that credential to your credential storage:
Delphi:
NetHTTPClient1.CredentialsStorage.AddCredentials(TCredentialsStorage.TCredential.Create(TAuthTargetType.Server, '', '', 'MyUserName', 'MyPassword');
C++:
TCredentialsStorage::TCredential *MyCredential = new TCredentialsStorage::TCredential(TAuthTargetType::Server, "", "", "MyUserName", "MyPassword"); NetHTTPClient1->CredentialsStorage->AddCredential(*MyCredential);
- Use the saved credential.
For example, you can write an OnAuthEvent event handler where you:
- Use TCredentialsStorage.FindAccurateCredential to search for a credential that matches the type of authentication required (
TAuthTargetType.Server
). - Use the username and the password from the appropriate credential to authenticate.
Delphi:
procedure TForm1.NetHTTPClient1AuthEvent(const Sender: TObject; AnAuthTarget: TAuthTargetType; const ARealm, AURL: string; var AUserName, APassword: string; var AbortAuth: Boolean; var Persistence: TAuthPersistenceType); var MyCredential: TCredentialsStorage.TCredential; begin MyCredential := NetHTTPClient1.CredentialsStorage.FindAccurateCredential(AnAuthTarget, ''); AUserName := MyCredential.UserName; APassword := MyCredential.Password; end;
C++:
void __fastcall TForm2::NetHTTPClient1AuthEvent(TObject * const Sender, TAuthTargetType AnAuthTarget, const UnicodeString ARealm, const UnicodeString AURL, UnicodeString &AUserName, UnicodeString &APassword, bool &AbortAuth, TAuthPersistenceType &Persistence) { TCredentialsStorage::TCredential MyCredential; MyCredential = NetHTTPClient1->CredentialsStorage->FindAccurateCredential(AnAuthTarget, ""); AUserName = MyCredential.UserName; APassword = MyCredential.Password; }
- Use TCredentialsStorage.FindAccurateCredential to search for a credential that matches the type of authentication required (
Handling Server-side Certificates
If the server provides an SSL certificate, but this certificate is invalid, the OnValidateServerCertificate event occurs. Provide an event handler for OnValidateServerCertificate
so that you can check the server certificate (Certificate
) and determine whether or not you accept the server certificate. If you accept the server certificate, change the value of the Accept
parameter to True
.
Handling Client-side Certificates
If the server requires a client certificate, the OnNeedClientCertificate event occurs. Provide an event handler for OnNeedClientCertificate
so that you can check your list of client certificates (ACertificateList
), and determine which certificate you want to send to the server. To send a given certificate from the list, change the value of AnIndex
to the index of the target certificate in ACertificateList
.
Making Requests Asynchronous
Requests are synchronous by default. During a request, the execution of your application stops when you start your request, and only resumes when you obtain a response from the server or the request times out.
If you want to make your requests asynchronous, so that requests do not stop the execution of your application, you must enable the Asynchronous property of the client component or the Asynchronous property of the request component, depending on which component you use to perform your request.