Using an HTTP Client

From RAD Studio
Jump to: navigation, search

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:

Note: Alternatively, you can use an instance of THTTPClient to manage your HTTP requests.

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:

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.

Note: Functions that send a request, either Execute or method-specific functions, all are blocking. That is, these functions do not return until there is a response from the server. See Tracking the Progress of the Download of the Response Data below.

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:

  1. Configure the URL property with the URL of the target resource.
  2. Configure the MethodString property with the name of the HTTP request method that you want to use.
    Note: HTTP request method names are case-sensitive.

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:

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.

Note: The HTTP client always adds its existing cookies to the request, regardless of the value of AllowCookies.

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:

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:

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:MyPassword@192.168.1.1:8080');

C++:

TProxySettings  MyProxySettings("http://MyUserName:MyPassword@192.168.1.1: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 http://direct as the URL.

OS X

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.

Note: If the system does not specify any proxy settings (the connection is direct), that is also considered a "setting". For example, on iOS or OS X with no system proxy settings, you cannot provide proxy settings for the HTTP Client. The settings that you provide are ignored because the system settings (the "no proxy" setting) are used.

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:

  1. 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);
    
  2. 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;
    }
    

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.

Note: If the HTTP method of the first request to a server that requires a client-side certificate is not either HEAD or GET (e.g. it is POST), the status code of the server response is 413. Always send a HEAD or GET request first. Using a HEAD request is usually a better choice, since less data is transferred.

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.

See Also