HTTP/HTTPS接続メモ

接続

接続を行うには以下のように行えばよい
void Cxxxx::Connect(CString &strURL){
    CHttpConnection *pHttp  = NULL;
    CString strUser         = "";
    CString strPass         = "";
    CHttpFile *pHttpFile    = NULL;
    DWORD dwServiceType     = 0;
    CString strServer       = "";
    CString strObject       = "";
    INTERNET_PORT nPort     = 80;
    DWORD dwReqFlag         = 0;
    DWORD dwRc              = 0;
    BOOL bRet               = TRUE;
    LPTSTR lpServer         = NULL;
    LPTSTR lpUser           = NULL;
    LPTSTR lpPass           = NULL;
    LPTSTR lpObject         = NULL;
    CInternetSession objSession("Browser Name", 0,
                                INTERNET_OPEN_TYPE_PRECONFIG,
                                NULL, NULL,
                                INTERNET_FLAG_DONT_CACHE);
    try{
        //サーバー名の取得
        bRet = AfxParseURL(strURL, dwServiceType, strServer, strObject, nPort);
        if(!bRet){
            return;
        }

        if(dwServiceType == AFX_INET_SERVICE_HTTPS){
            dwReqFlag = INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_SECURE;
        }else{
            dwReqFlag = INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE;
        }

        //HTTPコネクションを取得
        pHttp = objSession.GetHttpConnection(strServer, nPort, strUser, strPass);

        //HTTPコネクションからのデータを取得するためのCHTTPFileクラスのポインタを取得
        pHttpFile = pHttp->OpenRequest(CHttpConnection::HTTP_VERB_GET,
                                       strObject, NULL, 1, NULL, NULL, dwReqFlag);
        if( !pHttpFile ){
            pHttp->Close();
            delete pHttp;
            objSession.Close();
            return;
        }

        if(dwServiceType == AFX_INET_SERVICE_HTTPS){
            // 認証エラーをスルーさせる
            DWORD dwFlags = 0;
            DWORD dwBuffLen = sizeof(dwFlags);
            InternetQueryOption(*pHttpFile, 
                                INTERNET_OPTION_SECURITY_FLAGS,
                                (LPVOID)&dwFlags, &dwBuffLen );

            dwFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;
            InternetSetOption(*pHttpFile, INTERNET_OPTION_SECURITY_FLAGS, 
                              &dwFlags,  sizeof (dwFlags));
        }

        //リクエストの送信
        if(!pHttpFile->SendRequest()){
            pHttpFile->Close();
            delete pHttpFile;
            pHttp->Close();
            delete pHttp;
            objSession.Close();
            return;
        }

        pHttpFile->QueryInfoStatusCode(dwRc);
        if (dwRc != HTTP_STATUS_OK){
            pHttpFile->Close();
            delete pHttpFile;
            pHttp->Close();
            delete pHttp;
            objSession.Close();
            return;
        }

    }catch(CInternetException *e){
        if(pHttpFile){
            pHttpFile->Close();
            delete pHttpFile;
        }
        if(pHttp){
            pHttp->Close();
            delete pHttp;
        }
        objSession.Close();
        return;
    }

    if(pHttpFile){
    
        TRY{
            //受信内容を読み込む
            DWORD dwSize = pHttpFile->GetLength();
            CString strLine;
            CString strBuff;
            strBuff = "";
            while(pHttpFile->ReadString(strLine)){
                strBuff += strLine + "\r\n";
            }
        }CATCH_ALL(e){
        }END_CATCH_ALL
        pHttpFile->Close();
        delete pHttpFile;
        pHttpFile = NULL;
    }
    if(pHttp){
        pHttp->Close();
        delete pHttp;
        pHttp = NULL;
    }
    objSession.Close();
}

認証を意識した接続

BASIC認証を必要とする接続の場合、ユーザー名とパスワードを指定する必要がある。
HTTPの場合は2つを指定するだけで接続可能。
HTTPSの場合は現在うまくいっていない。
void Cxxxx::Connect(CString &strURL){
    CHttpConnection *pHttp  = NULL;
    CString strUser         = "";
    CString strPass         = "";
    CHttpFile *pHttpFile    = NULL;
    DWORD dwServiceType     = 0;
    CString strServer       = "";
    CString strObject       = "";
    INTERNET_PORT nPort     = 80;
    DWORD dwReqFlag         = 0;
    DWORD dwRc              = 0;
    BOOL bRet               = TRUE;
    LPTSTR lpServer         = NULL;
    LPTSTR lpUser           = NULL;
    LPTSTR lpPass           = NULL;
    LPTSTR lpObject         = NULL;
    CInternetSession objSession("Browser Name", 0,
                                INTERNET_OPEN_TYPE_PRECONFIG,
                                NULL, NULL,
                                INTERNET_FLAG_DONT_CACHE);
    try{
        //サーバー名の取得
        bRet = AfxParseURL(strURL, dwServiceType, strServer, strObject, nPort);
        if(!bRet){
            return;
        }

        if(dwServiceType == AFX_INET_SERVICE_HTTPS){
            dwReqFlag = INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE | INTERNET_FLAG_SECURE;
        }else{
            dwReqFlag = INTERNET_FLAG_RELOAD | INTERNET_FLAG_DONT_CACHE;
        }

        //HTTPコネクションを取得
        pHttp = objSession.GetHttpConnection(strServer, nPort, strUser, strPass);

        //HTTPコネクションからのデータを取得するためのCHTTPFileクラスのポインタを取得
        pHttpFile = pHttp->OpenRequest(CHttpConnection::HTTP_VERB_GET,
                                       strObject, NULL, 1, NULL, NULL, dwReqFlag);
        if( !pHttpFile ){
            pHttp->Close();
            delete pHttp;
            objSession.Close();
            return;
        }

        if(dwServiceType == AFX_INET_SERVICE_HTTPS){
            // 認証エラーをスルーさせる
            DWORD dwFlags = 0;
            DWORD dwBuffLen = sizeof(dwFlags);
            InternetQueryOption(*pHttpFile, 
                                INTERNET_OPTION_SECURITY_FLAGS,
                                (LPVOID)&dwFlags, &dwBuffLen );

            dwFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;
            InternetSetOption(*pHttpFile, INTERNET_OPTION_SECURITY_FLAGS, 
                              &dwFlags,  sizeof (dwFlags));
        }

        //ユーザーID/パスワードの設定する。
        if(!strUser.IsEmpty()){
            //ユーザーID
            bRet = InternetSetOption(*pHttpFile, 
                                     INTERNET_OPTION_USERNAME, 
                                     (LPVOID)(LPCTSTR)strUser,  
                                     strUser.GetLength());

            if(!bRet){
                DWORD dwErr = GetLastError();
                pHttpFile->Close();
                delete pHttpFile;
                pHttp->Close();
                delete pHttp;
                objSession.Close();
                strMsg.Format("Error Code = %d", dwErr);
                OutDebugLog(strMsg);
                return 0;
            }
        }

        if(!strPass.IsEmpty()){
            //パスワード
            bRet = InternetSetOption(*pHttpFile, 
                                     INTERNET_OPTION_PASSWORD, 
                                     (LPVOID)(LPCTSTR)strPass,  
                                     strPass.GetLength());

            if(!bRet){
                DWORD dwErr = GetLastError();
                pHttpFile->Close();
                delete pHttpFile;
                pHttp->Close();
                delete pHttp;
                objSession.Close();
                strMsg.Format("Error Code = %d", dwErr);
                OutDebugLog(strMsg);
                return 0;
            }
        }

        //リクエストの送信
        if(!pHttpFile->SendRequest()){
            pHttpFile->Close();
            delete pHttpFile;
            pHttp->Close();
            delete pHttp;
            objSession.Close();
            return;
        }

        pHttpFile->QueryInfoStatusCode(dwRc);
        if (dwRc != HTTP_STATUS_OK){
            pHttpFile->Close();
            delete pHttpFile;
            pHttp->Close();
            delete pHttp;
            objSession.Close();
            return;
        }

    }catch(CInternetException *e){
        if(pHttpFile){
            pHttpFile->Close();
            delete pHttpFile;
        }
        if(pHttp){
            pHttp->Close();
            delete pHttp;
        }
        objSession.Close();
        return;
    }

    if(pHttpFile){
    
        TRY{
            //受信内容を読み込む
            DWORD dwSize = pHttpFile->GetLength();
            CString strLine;
            CString strBuff;
            strBuff = "";
            while(pHttpFile->ReadString(strLine)){
                strBuff += strLine + "\r\n";
            }
        }CATCH_ALL(e){
        }END_CATCH_ALL
        pHttpFile->Close();
        delete pHttpFile;
        pHttpFile = NULL;
    }
    if(pHttp){
        pHttp->Close();
        delete pHttp;
        pHttp = NULL;
    }
    objSession.Close();
}

参考

  • MASAPICO's PAGE
  • Wininet Programing
  • Kashiko - うぇブログ(Googleキャッシュ)
  • 2005年9月の日記
  • How To Using HttpSendRequestEx with Password Protected URLs
  • テクニカルライティング MSDNの羅針盤第13回
  • (表15) HttpOpenRequest()関数のdwFlags