HTTP クライアントの使用

提供: RAD Studio
移動先: 案内検索

マルチデバイス アプリケーションでの RTL の使用 への移動


RTL では、サーバーに HTTP 要求を送信し、その応答を処理できるよう、次の 2 つのコンポーネントを提供しています。

メモ: または、THTTPClient のインスタンスを使用して HTTP 要求を管理することもできます。

設計時のアプリケーションの構成

HTTP クライアントを作成する

HTTP 要求の送信に使用できる HTTP クライアントを作成するには、[ツール パレット]からアプリケーションのフォームまたはデータ モジュールへ、TNetHTTPClient をドラッグします。TNetHTTPClient の初期構成は必要ありません。

HTTP 要求を作成し構成する

また、1 つ以上の TNetHTTPRequest コンポーネントをフォームまたはデータ モジュールにドロップする必要があります。

新しい HTTP 要求コンポーネントをドロップしたら、[オブジェクト インスペクタ]Client プロパティをダブルクリックし、その値に先ほどドロップした HTTP クライアント コンポーネントを設定します。

要求コンポーネントは、必要な数だけ使用することができます。ただし、異なる複数の HTTP 要求を送信する必要がある場合、1 つの HTTP 要求コンポーネントを使用して、実行時にそのコンポーネントを再構成してそれぞれの要求を送信する方がよいでしょう。

要求の送信と応答の処理

HTTP 要求を送信する

HTTP 要求を送信するには、少なくとも以下を指定しなければなりません。

HTTP 要求メソッドによって、指定された URL にあるリソース上でサーバーに実行させるアクション(リソースのデータを送り返す、要求に含まれるデータでリソースを更新する、など)が決まります。

TNetHTTPRequest コンポーネントを使用して HTTP 要求を送信する方法は、使用する HTTP 要求メソッドによって異なります。

メモ: 要求を送信する関数(Execute またはメソッド固有の関数)は、すべてブロッキング呼び出しです。 つまり、これらの関数は、サーバーから応答があるまで終了しません。 後の「応答データのダウンロードの進行状況を追跡する応答データのダウンロードの進行状況を追跡する」のセクションを参照してください。

DELETE、GET、HEAD、OPTIONS、または TRACE HTTP 要求メソッドを使用して HTTP 要求を送信する

以下の HTTP 要求メソッドには、送信先リソースの URL 以外の入力データは必要ありません。

この HTTP 要求メソッドのいずれかを使用して HTTP 要求を送信するには、まず、設計時に要求を以下のように構成します。

  1. URL プロパティを、送信先リソースの URL に構成します。
  2. MethodString プロパティを、使用したい HTTP 要求メソッドの名前に構成します。
メモ: HTTP 要求メソッド名では大文字と小文字が区別されます

その後、Execute を呼び出して要求を送信します。

MERGE、PATCH、または PUT HTTP 要求メソッドを使用して HTTP 要求を送信する

以下の HTTP 要求メソッドには、送信先リソースの URL の他にも入力データが必要です。

この HTTP 要求メソッドのいずれかを使用して HTTP 要求を送信するには、次の表に示す対応する関数を呼び出します。呼び出し時には、第 1 引数に送信先リソースの URL を、第 2 引数に TStream のインスタンスを指定します。

HTTP 要求メソッド TNetHTTPRequest の関数
PUT Put
PATCH Patch
MERGE Merge
PUT 経由の PATCH* PatchAlternative
PUT 経由の MERGE* MergeAlternative
* HTTP プロキシの中には、最新の標準 HTTP 要求メソッド(PATCH など)や非標準の HTTP 要求メソッド(MERGE など)をサポートしていないものがあります。その場合には、別の HTTP 要求メソッドを代理として HTTP 要求メソッドを実行することができます。そのためには、別の要求に、実行したい HTTP 要求メソッドを指定するヘッダーを含めます。

POST HTTP 要求メソッドを使用して HTTP 要求を送信する

POST HTTP 要求メソッドには、送信先リソースの URL の他にも入力データが必要です。

POST HTTP 要求メソッドを使用して HTTP 要求を送信するには、Post を呼び出します。その呼び出しの第 1 引数に、送信先リソースの URL を指定します。残りの引数は、要求の入力データを渡す方法によって異なります。

  • ローカル ファイルの内容を送信する場合は、そのファイルへのローカル パスを呼び出しの第 2 引数に指定します。
  • ストリームの内容を送信する場合は、TStream のインスタンスを呼び出しの第 2 引数に指定します。
  • HTML 4 標準に沿って MIME マルチパート メッセージとしてエンコードされたフォーム データを送信する場合は、TMultipartFormData のインスタンスを呼び出しの第 2 引数に指定します。
  • 文字列リストの内容を送信する場合は、TStrings のインスタンスを呼び出しの第 2 引数に指定します。このとき文字列のエンコードが UTF-8 でなければ、TEncoding のインスタンスを第 4 引数に指定します。次に例を示します。
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);

HTTP 応答を処理する

ターゲット サーバーが要求に対する応答を送信すると、HTTP 要求コンポーネントの OnRequestCompleted イベントが発生します。このイベントのイベント ハンドラを定義して、サーバー応答からデータを読み取ります。要求の実行中にエラーが発生した場合は、HTTP 要求コンポーネントの OnRequestError イベントが発生します。

OnRequestCompleted のイベント ハンドラは、次の 2 つのパラメータを受け取ります。

  • Sender: HTTP 要求コンポーネント
  • AResponseIHTTPResponse インターフェイスを実装したオブジェクト

応答データはすべて、AResponse から取得することができます。

クッキーの管理

HTTP クライアント コンポーネントの AllowCookies プロパティを使用すると、サーバーからの応答で送信されるクッキーを受け入れるかどうかを指定できます。 AllowCookiesTrue の場合、HTTP クライアントでは、受け取ったクッキーを自分の CookieManager プロパティに保存します。

メモ: HTTP クライアントは、AllowCookies の値に関係なく、常に自分の 既存のクッキー を要求に付け加えます。

リダイレクトの処理

HandleRedirects プロパティを使用すると、HTTP クライアント コンポーネントでのリダイレクトの処理方法を制御できます。デフォルト値は True で、HTTP クライアント コンポーネントがリダイレクトに自動的に従うことを意味します。

HTTP クライアント コンポーネントの MaxRedirects プロパティを使用すると、コンポーネントで従うことができるリダイレクトの回数の上限を指定できます。HTTP クライアント コンポーネントが、指定されたリダイレクト回数の上限に達すると、ENetHTTPRequestException 型の例外が発生します。

応答データのダウンロードの処理

要求に対する応答を HTTP クライアントがダウンロードしている間、HTTP 要求オブジェクトの OnReceiveData イベントが発生し続けます。OnReceiveData のイベント ハンドラを用意すると、応答データのダウンロードの進行状況を追跡できます。このイベント ハンドラは次のパラメータを受け取ります。

  • Sender: HTTP 要求オブジェクト
  • AContentLength: 応答データの予想される長さ(バイト数)
  • AReadCount: HTTP クライアントがこれまでにダウンロードした応答データのバイト数
  • Abort: ダウンロードをキャンセルするかどうかを示す論理型パラメータ

ダウンロードが終了すると、最後に OnReceiveData イベントが発生し、このときの AContentLengthAReadCount の値は同じです。その後すぐに OnRequestCompleted イベントが発生します。

応答データのダウンロードの進行状況を追跡する

応答データのダウンロードの進行状況を追跡するには、OnReceiveData イベントのイベント ハンドラで AContentLengthAReadCount の値を使用します。 次の例では、ダウンロードしたデータの割合(%)を計算しています。

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
    }
}

応答データのダウンロードをキャンセルする

応答データのダウンロードをキャンセルするには、OnReceiveData イベント ハンドラの中で、Abort の値を True に変更します。

カスタム ヘッダーを含んだ要求の送信

HTTP クライアント コンポーネントでも HTTP 要求コンポーネントでも、カスタム ヘッダーを設定することができます。 指定可能なカスタム ヘッダーは次のとおりです。

要求を実行すると、HTTP フレームワークの THTTPClient.Execute メソッドにより、HTTP クライアント コンポーネントからのカスタム ヘッダーと、対応する HTTP 要求コンポーネントからのカスタム ヘッダーが結合され、その一体化されたヘッダーが最終的な要求に付け加えられます。

セキュアな接続の処理

HTTP クライアント コンポーネントでは、セキュアな接続(HTTPS 接続)をサポートしています。発生して必要に応じて下記の適切なイベントを起動する証明書要求はすべて、HTTP フレームワークで自動的に処理されます。

証明書の処理の詳細については、「サーバー側の証明書を処理する」セクションと「クライアント側の証明書を処理する」セクションを参照してください。

認証と証明書の処理

HTTP 基本アクセス認証を処理する

HTTP 基本アクセス認証が必要なサーバーに HTTP 要求を送信すると、HTTP クライアント オブジェクトの OnAuthEvent イベントが発生します。アクセス資格情報を送信するには、このイベントのイベント ハンドラを用意し、イベント ハンドラが受け取る第 2 パラメータ(AnAuthTarget)の値が TAuthTargetType.Server の場合に、AUserName 変数と APassword 変数に HTTP アクセスのユーザー名とパスワードを設定します。次に例を示します。

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";
    }
}

また、このイベント ハンドラは、認証が必要な HTTP サーバーの領域(ARealm)と、要求の送信先 URL(AURL)も受け取ります。

HTTP 認証プロセスを中止するには、AbortAuth の値を True に変更します。

プロキシ経由で要求を送信する

認証が必要なプロキシを経由して送信する場合は、認証に使用されるプロキシ設定を定義できます。 その方法を次の例で説明します。

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;

プロキシ設定を指定するには、プロキシ関連情報を含んだ URL 文字列を渡す方法もあります。

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;

あるいは、プロキシ認証の資格情報を OnAuthEvent イベントのイベント ハンドラで指定することもできます。「HTTP 基本アクセス認証を処理する」セクションを参照し、AnAuthTarget の値が TAuthTargetType.Server ではなく TAuthTargetType.Proxy になっていることを確認してください。

HTTP クライアントでのシステム プロキシ設定の扱い

以下の表は、HTTP クライアントがシステム プロキシ設定をどう扱うかをプラットフォームごとにまとめたものです。

プラットフォーム 動作

Windows

HTTP クライアントはシステム プロキシ設定を使用します。システム プロキシ設定を無視したり、HTTP クライアント用に別のプロキシ設定を指定することも可能です。 システム プロキシ設定を無視するには、HTTP クライアント用のプロキシ設定を作成し、URL に http://direct を指定します。

macOS

HTTP クライアントは常にシステム プロキシ設定を使用します。HTTP クライアント用に別のプロキシ設定を指定した場合でも、HTTP クライアントではシステム プロキシ設定が使用されます。

iOS

HTTP クライアントは常にシステム プロキシ設定を使用します。HTTP クライアント用に別のプロキシ設定を指定した場合でも、HTTP クライアントではシステム プロキシ設定が使用されます。

Android

HTTP クライアントはシステム プロキシ設定を使用します。この設定を無視することはできませんが、HTTP クライアント用に別のプロキシ設定を指定することは可能です。

Linux

HTTP クライアントはシステム プロキシ設定を使用します。この設定を無視することはできませんが、HTTP クライアント用に別のプロキシ設定を指定することは可能です。

メモ: システムがプロキシ設定を指定しなかった場合(ダイレクト接続の場合)、それも「設定」と見なされます。 たとえば、システム プロキシ設定のない iOS または macOS 上では、HTTP Client に対してプロキシ設定を提供することはできません。 用意した設定は無視されます。これは、システム設定(「プロキシなし」設定)が使用されるためです。
注意: RAD Studio 10.4 まで、HTTP クライアント ライブラリは NSURLConnection API を使用していましたが、Apple は Mac OS X 10.11 および iOS 9 でこれを廃止予定としています。RAD Studio10.4.1 では、両プラットフォームでの新しい API NSURLSession を導入し、また、macOS でのプロキシ サポートの問題にも対処しています。

ユーザー資格情報のストレージを管理する

TNetHTTPClient では、HTTP 認証またはプロキシ認証の資格情報を保存することができます。保存される各資格情報には、ユーザー名、パスワード、認証ターゲットの種類、領域、ターゲット URL を含めることができます。

TNetHTTPClient.CredentialsStorage を使用して資格情報を保存したあと、基本認証が必要な HTTP サーバーに接続する際にその資格情報を使用して認証を行う方法を次の例で説明します。

  1. 次のように、資格情報を作成して資格情報ストレージに追加します。
    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. 保存した資格情報を使用します。 たとえば、OnAuthEvent イベントのイベント ハンドラを記述し、その中で次の処理を行うことができます。
    • TCredentialsStorage.FindAccurateCredential を使用して、必要な認証タイプ(TAuthTargetType.Server)と一致する資格情報を検索する。
    • 該当する資格情報から得られたユーザー名とパスワードを使用して認証を行う。
    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;
    }
    

サーバー側の証明書を処理する

サーバーが SSL 証明書を提供していて、その証明書が無効だった場合、OnValidateServerCertificate イベントが発生します。OnValidateServerCertificate のイベント ハンドラを作成し、そこでサーバー証明書(Certificate)を確認して、サーバー証明書を受け入れるかどうかを判断します。サーバー証明書を受け入れる場合には、Accept パラメータの値を True に変更します。

クライアント側の証明書を処理する

サーバーでクライアント証明書が要求される場合、OnNeedClientCertificate イベントが発生します。OnNeedClientCertificate のイベント ハンドラを作成し、そこでクライアント証明書のリスト(ACertificateList)を確認して、どの証明書をサーバーに送信するかを判断します。リスト内の特定の証明書を送信するには、AnIndex の値を ACertificateList における対象の証明書のインデックスに変更します。

メモ: クライアント側証明書を要求するサーバーに対する最初の要求の HTTP メソッドが、HEAD でも GET でもない(たとえば POST である)場合、サーバー応答のステータス コードは 413 になります。 最初は必ず HEAD 要求または GET 要求を送信してください。 転送するデータが少ない HEAD 要求の方が通常は適しています。

非同期に要求を送信する

要求はデフォルトでは、同期をとります。要求の間、アプリケーションの実行は要求が開始されたところで停止し、サーバーから応答を受け取るか、要求がタイムアウトしたときのみ再開します。

要求がアプリケーションの実行を停止させないよう、要求を非同期に行いたい場合、クライアント コンポーネントの Asynchronous プロパティか、要求コンポーネントの Asynchronous プロパティを有効にしなければなりません。どちらのコンポーネントかは、要求の実行にどちらを使用するかによります。

関連項目