WinHTTP セッションの概要
Microsoft Windows HTTP Services (WinHTTP) は、アプリケーションが Web 上の HTTP リソースにアクセスできるようにする一連の C/C++ 関数を公開します。 このトピックでは、これらの関数を使用して HTTP サーバーを操作する方法の概要について説明します。
- WinHTTP API を使用して Web にアクセスする
- WinHTTP の初期化
- 要求を開く
- 要求ヘッダーの追加
- 要求の送信
- サーバーへのデータの投稿
- 要求に関する情報の取得
- Web からリソースをダウンロードする
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 を使用して、データをサーバーに投稿します。
または、WinHttpSendRequest の lpOptional パラメーターを、サーバーにポストするデータを含むバッファーのアドレスに設定します。 この手法を使用する場合は、WinHttpSendRequest の dwOptionalLength パラメーターと dwTotalLength パラメーターの両方を、投稿するデータのサイズに設定する必要があります。 この方法で WinHttpSendRequest を 呼び出すと、 WinHttpWriteData を呼び出す必要がなくなります。
要求に関する情報の取得
WinHttpQueryHeaders 関数を使用すると、アプリケーションは HTTP 要求に関する情報を取得できます。 この関数には、WinHttpOpenRequest によって作成された HINTERNET ハンドル、情報レベル値、およびバッファー長が必要です。 WinHttpQueryHeaders は、情報を格納するバッファーと、同じ名前の複数のヘッダーを列挙する 0 から始まるヘッダー インデックスも受け入れます。
情報が WinHttpQueryHeaders の lpvBuffer パラメーターに格納される形式を制御するには、 [クエリ情報フラグ] ページにある情報レベルの値を修飾子と共に使用します。
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 );