Share via


WinHTTP セッションの概要

Microsoft Windows HTTP Services (WinHTTP) は、アプリケーションが Web 上の HTTP リソースにアクセスできるようにする一連の C/C++ 関数を公開します。 このトピックでは、これらの関数を使用して HTTP サーバーを操作する方法の概要について説明します。

WinHTTP API を使用して Web にアクセスする

次の図は、HTTP サーバーと対話するときに WinHTTP 関数が通常呼び出される順序を示しています。 網かけのボックスは HINTERNET ハンドルを生成する関数を表し、プレーン ボックスはそれらのハンドルを使用する関数を表します。

ハンドルを作成する関数

WinHTTP の初期化

サーバーと対話する前に、WinHttpOpen を呼び出して WinHTTP を初期化する必要があります。 WinHttpOpen は 、HTTP セッションに関する詳細を保持するセッション コンテキストを作成し、セッション ハンドルを返します。 このハンドルを使用すると、 WinHttpConnect 関数はターゲット HTTP または Secure Hypertext Transfer Protocol (HTTPS) サーバーを指定できます。

Note

WinHttpConnect を呼び出しても、特定のリソースに対して要求が行われるまで、HTTP サーバーへの実際の接続は行われません。

 

要求を開く

WinHttpOpenRequest 関数は、特定のリソースに対する HTTP 要求を開き、他の HTTP 関数で使用できる HINTERNET ハンドルを返します。 WinHttpOpenRequest は、呼び出し時にサーバーに要求を送信しません。 WinHttpSendRequest 関数は、実際にはネットワーク経由で接続を確立し、要求を送信します。

次の例は、既定のオプションを使用する WinHttpOpenRequest のサンプル呼び出しを示しています。

HINTERNET hRequest = WinHttpOpenRequest( hConnect, L"GET", NULL, NULL, NULL, NULL, 0);

要求ヘッダーの追加

WinHttpAddRequestHeaders 関数を使用すると、アプリケーションで追加のフリーフォーマット要求ヘッダーを HTTP 要求ハンドルに追加できます。 これは、HTTP サーバーに送信される要求を正確に制御する必要がある高度なアプリケーションで使用することを目的としています。

WinHttpAddRequestHeaders 関数には、WinHttpOpenRequest によって作成された HTTP 要求ハンドル、ヘッダー、ヘッダーの長さ、および修飾子を含む文字列が必要です。

WinHttpAddRequestHeaders では、次の修飾子を使用できます。

修飾子 説明
WINHTTP_ADDREQ_FLAG_ADD 存在しない場合は、ヘッダーを追加します。 WINHTTP_ADDREQ_FLAG_REPLACEで使用されます。
WINHTTP_ADDREQ_FLAG_ADD_IF_NEW ヘッダーがまだ存在しない場合にのみ、ヘッダーを追加します。それ以外の場合は、エラーが返されます。
WINHTTP_ADDREQ_FLAG_COALESCE 同じ名前のヘッダーをマージします。
WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA コンマを使用して、同じ名前のヘッダーをマージします。 たとえば、"Accept: text/*" の後に "Accept: audio/*" をこのフラグで追加すると、単一ヘッダー "Accept: text/*, audio/*" が形成され、最初に見つかったヘッダーがマージされます。 マージまたは分離されたヘッダーに関するまとまりのあるスキームを確保するのは、呼び出し元のアプリケーションにかかっています。
WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON セミコロンを使用して、同じ名前のヘッダーをマージします。
WINHTTP_ADDREQ_FLAG_REPLACE ヘッダーを置換または削除します。 ヘッダー値が空で、ヘッダーが見つかった場合は削除されます。 ヘッダー値が空でない場合は、ヘッダー値が置き換えられます。

 

要求の送信

WinHttpSendRequest 関数は、サーバーへの接続を確立し、指定したサイトに要求を送信します。 この関数には、WinHttpOpenRequest によって作成された HINTERNET ハンドルが必要です。 WinHttpSendRequest は、追加のヘッダーまたはオプションの情報を送信することもできます。 オプションの情報は、通常、PUT や POST などの情報をサーバーに書き込む操作に使用されます。

WinHttpSendRequest 関数が要求を送信した後、アプリケーションは HINTERNET ハンドルで WinHttpReadData 関数と WinHttpQueryDataAvailable 関数を使用してサーバーのリソースをダウンロードできます。

サーバーへのデータの投稿

サーバーにデータを投稿するには、WinHttpOpenRequest の呼び出しの HTTP 動詞が POST または PUT である必要があります。 WinHttpSendRequest が呼び出されると、dwTotalLength パラメーターにデータのサイズをバイト単位で設定する必要があります。 次に 、WinHttpWriteData を使用して、データをサーバーに投稿します。

または、WinHttpSendRequestlpOptional パラメーターを、サーバーにポストするデータを含むバッファーのアドレスに設定します。 この手法を使用する場合は、WinHttpSendRequestdwOptionalLength パラメーターと dwTotalLength パラメーターの両方を、投稿するデータのサイズに設定する必要があります。 この方法で WinHttpSendRequest を 呼び出すと、 WinHttpWriteData を呼び出す必要がなくなります。

要求に関する情報の取得

WinHttpQueryHeaders 関数を使用すると、アプリケーションは HTTP 要求に関する情報を取得できます。 この関数には、WinHttpOpenRequest によって作成された HINTERNET ハンドル、情報レベル値、およびバッファー長が必要です。 WinHttpQueryHeaders は、情報を格納するバッファーと、同じ名前の複数のヘッダーを列挙する 0 から始まるヘッダー インデックスも受け入れます。

情報が WinHttpQueryHeaderslpvBuffer パラメーターに格納される形式を制御するには、 [クエリ情報フラグ] ページにある情報レベルの値を修飾子と共に使用します。

Web からリソースをダウンロードする

WinHttpOpenRequest 関数を使用して要求を開き、WinHttpSendRequest を使用してサーバーに送信し、WinHttpReceiveResponse で応答を受信するように要求ハンドルを準備した後、アプリケーションは WinHttpReadData 関数と WinHttpQueryDataAvailable 関数を使用して、HTTP サーバーからリソースをダウンロードできます。

次のサンプル コードは、セキュリティで保護されたトランザクション セマンティクスを持つリソースをダウンロードする方法を示しています。 このサンプル コードでは、WinHTTP アプリケーション プログラミング インターフェイス (API) を初期化し、ターゲット HTTPS サーバーを選択し、このセキュリティで保護されたリソースの要求を開いて送信します。 WinHttpQueryDataAvailable は、ダウンロードできるデータの量を判断するために要求ハンドルと共に使用され、そのデータの読み取りには WinHttpReadData が使用されます。 このプロセスは、ドキュメント全体が取得されて表示されるまで繰り返されます。

  DWORD dwSize = 0;
  DWORD dwDownloaded = 0;
  LPSTR pszOutBuffer;
  BOOL  bResults = FALSE;
  HINTERNET  hSession = NULL, 
             hConnect = NULL,
             hRequest = NULL;

  // Use WinHttpOpen to obtain a session handle.
  hSession = WinHttpOpen( L"WinHTTP Example/1.0",  
                          WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
                          WINHTTP_NO_PROXY_NAME, 
                          WINHTTP_NO_PROXY_BYPASS, 0 );

  // Specify an HTTP server.
  if( hSession )
    hConnect = WinHttpConnect( hSession, L"www.microsoft.com",
                               INTERNET_DEFAULT_HTTPS_PORT, 0 );

  // Create an HTTP request handle.
  if( hConnect )
    hRequest = WinHttpOpenRequest( hConnect, L"GET", NULL,
                                   NULL, WINHTTP_NO_REFERER, 
                                   WINHTTP_DEFAULT_ACCEPT_TYPES, 
                                   WINHTTP_FLAG_SECURE );

  // Send a request.
  if( hRequest )
    bResults = WinHttpSendRequest( hRequest,
                                   WINHTTP_NO_ADDITIONAL_HEADERS, 0,
                                   WINHTTP_NO_REQUEST_DATA, 0, 
                                   0, 0 );


  // End the request.
  if( bResults )
    bResults = WinHttpReceiveResponse( hRequest, NULL );

  // Keep checking for data until there is nothing left.
  if( bResults )
  {
    do 
    {
      // Check for available data.
      dwSize = 0;
      if( !WinHttpQueryDataAvailable( hRequest, &dwSize ) )
        printf( "Error %u in WinHttpQueryDataAvailable.\n",
                GetLastError( ) );

      // Allocate space for the buffer.
      pszOutBuffer = new char[dwSize+1];
      if( !pszOutBuffer )
      {
        printf( "Out of memory\n" );
        dwSize=0;
      }
      else
      {
        // Read the data.
        ZeroMemory( pszOutBuffer, dwSize+1 );

        if( !WinHttpReadData( hRequest, (LPVOID)pszOutBuffer, 
                              dwSize, &dwDownloaded ) )
          printf( "Error %u in WinHttpReadData.\n", GetLastError( ) );
        else
          printf( "%s", pszOutBuffer );

        // Free the memory allocated to the buffer.
        delete [] pszOutBuffer;
      }
    } while( dwSize > 0 );
  }


  // Report any errors.
  if( !bResults )
    printf( "Error %d has occurred.\n", GetLastError( ) );

  // Close any open handles.
  if( hRequest ) WinHttpCloseHandle( hRequest );
  if( hConnect ) WinHttpCloseHandle( hConnect );
  if( hSession ) WinHttpCloseHandle( hSession );