4.1 HTTPサーバへリクエストを送信する
HTTPサーバへリクエストを送信するときは、API関数/InternetOpenとAPI関数/InternetConnectを使ってHTTPサーバへ接続した後、API関数/HttpOpenRequestでリクエストの初期化し、API関数/HttpSendRequestでリクエストの送信を行います。

なお、ここでは「GET形式でのリクエスト送信例」を解説しています。POST形式については、「4.4 POST形式でリクエストを送信する」を参照してください。

また、リクエストを送信しただけでは何も起きません。サーバからの応答を受け取る方法は「4.2 HTTPサーバからの応答を取得する」、サーバからファイルをダウンロードする方法は「4.3 HTTPサーバからファイルを取得する」を、この章とあわせて参照してください。

参考までに、この技はAccess VBA以外に、Excelマクロなど他のVBAでも使用することができます。
API関数/HttpOpenRequestを定義する
API関数を使うとき、まずはこの関数がどこにある・どんな関数であるかといった、この関数を使うための準備(API関数の宣言)が必要です。また、定義する場所はフォーム、モジュール、クラスモジュールの(General)(Declarations)です。

次の例は、API関数/HttpOpenRequestを使うときの記述例です。API関数を使用するときは、ついでにAPI関数で使用する定数も定義しておきましょう。

'(General)(Declarations)へ記述します
Private Declare Function HttpOpenRequest _
            Lib "wininet.dll" _
          Alias "HttpOpenRequestA" _
         (ByVal hConnect As Long _
        , ByVal lpszVerb As String _
        , ByVal lpszObjectName As String _
        , ByVal lpszVersion As String _
        , ByVal lpszReferer As String _
        , ByVal lpszAcceptTypes As Long _
        , ByVal dwFlags As Long _
        , ByVal dwContext As Long) As Long

'dwFlags(ダウンロード方法)
'キャッシュを無視し、サーバから強制的にダウンロード
Private Const INTERNET_FLAG_RELOAD        As Long = &H80000000
'ダウンロードファイルをキャッシュに加えない
Private Const INTERNET_FLAG_DONT_CACHE    As Long = &H4000000
'サーバから再読み込みします
Private Const INTERNET_FLAG_RESYNCHRONIZE As Long = &H800
'キャッシュできないときに一時ファイルを生成
Private Const INTERNET_FLAG_NEED_FILE     As Long = &H10
'有効期限、最終更新時刻がサーバから返されない場合は強制的に再読み込み
Private Const INTERNET_FLAG_HYPERLINK     As Long = &H400
'クッキーを保存しない
Private Const INTERNET_FLAG_NO_COOKIES    As Long = &H80000
'リダイレクトしない
Private Const INTERNET_FLAG_NO_AUTO_REDIRECT As Long = &H200000
 ※決まり事なので、悩まずにコピペして使ってしまいましょう

なお、この関数の戻り値にはリクエストを使用するための管理番号(リクエストハンドル)が返ります。( )内に記述している引数は、以下を参照してください。

 ◆HttpOpenRequestの引数
ByVal hConnect As Long InternetConnectで取得したコネクションハンドルを指定します。
ByVal lpszVerb As String リクエストの形式を指定します。GET形式ならGET、POST形式ならPOSTと指定します。
ByVal lpszObjectName As String HTTPサーバ上のパス(ドメイン名を除く)を指定します。たとえば、「http://www.happy2-island.com/access/gogo03/capter90401.shtml」このURLの情報を取り出したいときは、「/access/gogo03/capter90401.shtml」を指定します。なお、ここに指定する内容は「255文字の固定長文字列」にしましょう。
ByVal lpszVersion As String HTTPのバージョンを指定します。HTTP/1.1を指定しておけばOK。
ByVal lpszReferer As String 参照元のURL(HTTP_REFERER)を指定します。特に必要がなければ。vbNullStringを指定しておけばOK。
ByVal lpszAcceptTypes As Long 受け入れ許可ファイルタイプ(HTTP_ACCEPT)を指定します。この設定は、HTTPヘッダーの設定(HttpAddRequestHeaders関数)で自由に設定できるので、ここでは0を指定しておけばOK。
ByVal dwFlags As Long ダウンロード方法を指定します。普段は、INTERNET_FLAG_RELOADを指定しておけばOKです。
ByVal dwContext As Long 0を指定しておいてOKです。
API関数/HttpSendRequestを定義する
API関数を使うとき、まずはこの関数がどこにある・どんな関数であるかといった、この関数を使うための準備(API関数の宣言)が必要です。また、定義する場所はフォーム、モジュール、クラスモジュールの(General)(Declarations)です。

次の例は、API関数/HttpSendRequestを使うときの記述例です。

'(General)(Declarations)へ記述します
Private Declare Function HttpSendRequest _
            Lib "wininet.dll" _
          Alias "HttpSendRequestA" _
         (ByVal hRequest As Long _
        , ByVal lpszHeaders As String _
        , ByVal dwHeadersLength As Long _
        , ByVal lpOptional As String _
        , ByVal dwOptionalLength As Long) As Integer
 ※決まり事なので、悩まずにコピペして使ってしまいましょう

なお、この関数の戻り値にはリクエストの送信に成功したか、失敗したかが返ります。Trueが成功、Falseが失敗です。

 ◆HttpSendRequestの引数
ByVal hRequest As Long HttpOpenRequestで取得したリクエストハンドルを指定します。
ByVal lpszHeaders As String リクエストに追加するHTTPヘッダーを指定します。必要ない場合は、vbNullStringを指定しましょう。
ByVal dwHeadersLength As Long lpszHeadersで指定した追加ヘッダーの文字列長を指定します。vbNullStringを指定した場合は0です。
ByVal lpOptional As String POST形式のときに、送信するデータを指定します。詳しくは「4.4 POST形式でリクエストを送信する」の章を参照してください。GET形式のときはvbNullStringでOK。
ByVal dwOptionalLength As Long lpOptionalに指定したデータの長さを指定します。データ参照元のURL(HTTP_REFERER)を指定します。vbNullStringを指定した場合は0です。
リクエストの送信例
HttpOpenRequestHttpSendRequestを使って、HTTPへGETリクエストを送信する例です。Subプロシージャ「prcHTTPSendRequestSample」を実行すると、HTTPサーバへGET形式でのリクエストを送ります。

HTTPサーバへリクエストを送信するときは、InternetOpenInternetConnectを使ってHTTPサーバへ接続した後、HttpOpenRequestHttpSendRequestの順序で実行します。

最初に、リクエストの初期化です。リクエストの初期化は、Functionプロシージャ「fcHTTPOpenRequest」で行っています。ポイントは、HttpOpenRequestの引数lpszObjectName255文字の固定長文字列で指定するところです。取得ドキュメントのパスは、呼び出し元プロシージャから渡された情報(strURLが"/document/news.html")を使用しますが、引数をそのまま指定せず、tmpURLという変数(255文字固定長)に保存してから使用します。なお、HttpOpenRequestの引数hConnectには、InternetConnectで取得したコネクションハンドルを指定しましょう。

次に、リクエストの送信です。リクエストの送信は、Functionプロシージャ「fcHTTPSendRequest」で行っています。HttpSendRequestには、追加するHTTPヘッダーやPOSTデータを指定することができますが、例では追加ヘッダーはなし、GET形式でのリクエストなので、引数には省略値を指定しています。

そして、最後にリクエストのクローズです。クローズするときは、クローズするHTTPリクエストハンドルを指定しInternetCloseHandleを実行します。例では、Functionプロシージャ「fcHttpRequestClose」で行っています。指定しているハンドルは、リクエスト初期化のときに取得したHTTPリクエストハンドル(例ではlngReqHnd)です。

なお、APIを実行したときの結果コードErr.LastDllErrorに返ります。0なら正常終了、0以外は失敗です。

'変数の定義 ※(General)(Declarations)です
Private lngWinINet As Long 'インターネットハンドルの保存用
Private lngHttpHnd As Long 'HTTPハンドルの保存用
Private lngReqHnd  As Long 'HTTPリクエストハンドルの保存用


Sub prcHTTPSendRequestSample()

    Dim lngRC As Long

    'インターネットサービスをオープンします
    lngRC = fcInternetOpen

    'オープンに成功したらHTTPサーバとの接続と切断を行います
    If lngRC = 0 Then

       'HTTPサーバへ接続します
       lngRC = fcHTTPConnect("www.uso-web-server.net")

       '接続に成功したらリクエストを初期化します
       If lngRC = 0 Then
          lngRC = fcHTTPOpenRequest("GET", "/document/news.html")
       End If

       'リクエストの初期化に成功したら、リクエストを送信します
       If lngRC = 0 Then
          lngRC = fcHTTPSendRequest
       End If

       'HTTPリクエストをクローズします
       Call fcHttpRequestClose

       'HTTPサーバから切断します
       Call fcHTTPDisConnect

    End If

    'インターネットサービスをクローズします
    Call fcInternetClose

End Sub


Function fcHTTPOpenRequest(strMethod As String, strURL As String) As Long

    Dim tmpURL     As String * 255

    'URLは255バイトの固定長文字列で渡す
    tmpURL = strURL

    'APIの実行/リクエストを初期化
    lngReqHnd = HttpOpenRequest(lngHttpHnd _
                              , strMethod _
                              , tmpURL _
                              , "HTTP/1.1" _
                              , vbNullString _
                              , 0 _
                              , INTERNET_FLAG_RELOAD _
                              , 0)

    'この関数の戻り値には、APIの処理結果コードを返します
    fcHTTPOpenRequest = Err.LastDllError

End Function


Function fcHTTPSendRequest() As Long

    'APIの実行/リクエストを送信
    Call HttpSendRequest(lngReqHnd _
                       , vbNullString _
                       , 0 _
                       , vbNullString _
                       , 0)

    'この関数の戻り値には、APIの処理結果コードを返します
    fcHTTPSendRequest = Err.LastDllError

End Function


Function fcHttpRequestClose() As Long

    'APIの実行/インターネットサービスをクローズ
    Call InternetCloseHandle(lngReqHnd)

    'この関数の戻り値には、APIの処理結果コードを返します
    fcHttpRequestClose = Err.LastDllError

End Function


Function fcHTTPConnect(Server As String) As Long

    'APIの実行/HTTPサーバへ接続
    lngHttpHnd = InternetConnect(lngWinINet _
                              , Server _
                              , INTERNET_DEFAULT_HTTP_PORT _
                              , vbNullString _
                              , vbNullString _
                              , INTERNET_SERVICE_HTTP _
                              , 0 _
                              , 0)

    'この関数の戻り値には、APIの処理結果コードを返します
    fcHTTPConnect = Err.LastDllError

End Function


Function fcHTTPDisConnect() As Long

    'APIの実行/HTTPサーバから切断
    Call InternetCloseHandle(lngHttpHnd)

    'この関数の戻り値には、APIの処理結果コードを返します
    fcHTTPDisConnect = Err.LastDllError

End Function


Function fcInternetOpen() As Long

    'APIの実行/インターネットサービスをオープン
    lngWinINet = InternetOpen(vbNullString _
                            , INTERNET_OPEN_TYPE_PRECONFIG _
                            , vbNullString _
                            , vbNullString _
                            , 0)

    'この関数の戻り値には、APIの処理結果コードを返します
    fcInternetOpen = Err.LastDllError

End Function


Function fcInternetClose() As Long

    'APIの実行/インターネットサービスをクローズ
    Call InternetCloseHandle(lngWinINet)

    'この関数の戻り値には、APIの処理結果コードを返します
    fcInternetClose = Err.LastDllError

End Function
 ※この他に、API関数を定義する必要があります。
 ※www.uso-web-server.netは架空のドメイン名です。
GET形式でデータを送信する場合
HTTPサーバへGET形式でデータを送信する場合は、HttpOpenRequestの第3引数(lpszObjectName)へ、?記号に続けて次の書式で記述します。

●書式
 キー名=データ
 [1]上記で1セット。複数セットを送信するときは&記号で繋ぐ。
 [2]日本語や一部の記号などは%xx形式にエンコードする必要がある。

●例(/cgi/get.cgiに指定する場合)
 /cgi/get.cgi?data1=abc&data2=def&data3=123

ただし、日本語や一部の記号などを使う場合は%xx形式へのエンコードが必要です。4.7 送信データのエンコードを参考にしてください。
Copyright(C) 1999-2006 結城圭介。 All rights reserved