Windows底层IDL实现http/https客户端api框架

xingyun86 2023-2-7 1039

1.添加C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Include\httprequest.idl到项目工程目录

2.基础框架代码

#include <string>
//通用版将wstring转化为string
__inline static
std::string WCToMB(const std::wstring& ws, unsigned long cp = CP_ACP)
{
    if (ws.empty() == true)return ("");
    std::string s(WideCharToMultiByte(cp, 0, ws.data(), ws.size(), NULL, 0, NULL, NULL), ('\0'));
    return s.substr(0, WideCharToMultiByte(cp, 0, ws.c_str(), ws.size(), (LPSTR)s.data(), (int)s.size(), NULL, NULL));
}
//通用版将string转化为wstring
__inline static
std::wstring MBToWC(const std::string& s, unsigned long cp = CP_ACP)
{
    if (s.empty() == true)return (L"");
    std::wstring ws(MultiByteToWideChar(cp, 0, s.data(), s.size(), NULL, 0), (L'\0'));
    return ws.substr(0, MultiByteToWideChar(cp, 0, s.data(), s.size(), (LPWSTR)ws.data(), (int)ws.size()));
}
#define ANSIToWIDE(A)  MBToWC(A,CP_ACP)
#define WIDEToANSI(W)  WCToMB(W,CP_ACP)
#define UTF8ToWIDE(U)  MBToWC(U,CP_UTF8)
#define WIDEToUTF8(W)  WCToMB(W,CP_UTF8)
#define ANSIToUTF8(A)  WIDEToUTF8(ANSIToWIDE(A))
#define UTF8ToANSI(U)  WIDEToANSI(UTF8ToWIDE(U))
#include <iostream>
#include <json.hpp>
#include <httplib.h>
#include <httprequest_h.h>
#include <zip.h>
class CWinhttpRequest : public IWinHttpRequestEvents {
public:
    static int GZipCompress(unsigned char* dst, unsigned long* dstLen, const unsigned char* src, unsigned long srcLen)
    {
        int ret = Z_ERRNO;
        z_stream stream = { 0 };
        stream.zalloc = (alloc_func)0;
        stream.zfree = (free_func)0;
        stream.opaque = (voidpf)0;
        ret = deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, MAX_WBITS | 16, 8, Z_DEFAULT_STRATEGY);
        if (ret != Z_OK)
        {
            return ret;
        }
        stream.next_in = (Bytef*)src;
        stream.avail_in = srcLen;
        stream.next_out = (Bytef*)dst;
        stream.avail_out = (*dstLen);
        while ((stream.avail_in > 0) && (stream.total_out < (*dstLen)))
        {
            ret = deflate(&stream, Z_NO_FLUSH);
            if (ret != Z_OK)
            {
                return ret;
            }
        }
        if (stream.avail_in > 0)
        {
            return Z_DATA_ERROR;
        }
        for (; ((ret = deflate(&stream, Z_FINISH)) != Z_STREAM_END);)
        {
            if (ret != Z_OK)
            {
                return ret;
            }
        }
        if ((ret = deflateEnd(&stream)) != Z_OK)
        {
            return ret;
        }
        (*dstLen) = stream.total_out;
        return ret;
    }
    static int GZipDecompress(unsigned char* dst, unsigned long* dstLen, const unsigned char* src, unsigned long srcLen) {
        int ret = Z_ERRNO;
        z_stream stream = { 0 };
        stream.zalloc = NULL;
        stream.zfree = NULL;
        stream.opaque = NULL;
        stream.avail_in = srcLen;
        stream.avail_out = (*dstLen);
        stream.next_in = (Bytef*)src;
        stream.next_out = (Bytef*)dst;
        ret = inflateInit2(&stream, MAX_WBITS + 16);
        if (ret == Z_OK)
        {
            ret = inflate(&stream, Z_FINISH);
            if (ret == Z_STREAM_END)
            {
                (*dstLen) = stream.total_out;
                ret = Z_OK;
            }
        }
        inflateEnd(&stream);
        return ret;
    }
    static LPCWSTR getAppPath()
    {
        static WCHAR CFGL_APP_PATH[MAX_PATH] = { 0 };
        if (!(*CFGL_APP_PATH))
        {
            DWORD dwLen = GetModuleFileNameW(NULL, CFGL_APP_PATH, MAX_PATH);
            for (--dwLen; dwLen > 0; dwLen--)
            {
                if (CFGL_APP_PATH[dwLen] == L'\\')
                {
                    memset(&CFGL_APP_PATH[dwLen + 1], 0, MAX_PATH - dwLen);
                    break;
                }
            }
        }
        return CFGL_APP_PATH;
    }
    static LPCWSTR getAppName()
    {
        static WCHAR CFGL_APP_NAME[MAX_PATH] = { 0 };
        if (!(*CFGL_APP_NAME))
        {
            DWORD dwLen = GetModuleFileNameW(NULL, CFGL_APP_NAME, MAX_PATH);
            for (--dwLen; dwLen > 0; dwLen--)
            {
                if (CFGL_APP_NAME[dwLen] == L'\\')
                {
                    memcpy(&CFGL_APP_NAME[0], &CFGL_APP_NAME[dwLen + 1], MAX_PATH - dwLen);
                    memset(&CFGL_APP_NAME[dwLen + 1], 0, dwLen);
                    break;
                }
            }
        }
        return CFGL_APP_NAME;
    }
    static unsigned char ToHex(unsigned char x)
    {
        return  x > 9 ? x + 55 : x + 48;
    }
    static unsigned char FromHex(unsigned char x)
    {
        unsigned char y;
        if (x >= 'A' && x <= 'Z') y = x - 'A' + 10;
        else if (x >= 'a' && x <= 'z') y = x - 'a' + 10;
        else if (x >= '0' && x <= '9') y = x - '0';
        else;// assert(0);
        return y;
    }
    static std::string UrlEncode(const std::string& str)
    {
        std::string strTemp = "";
        size_t length = str.length();
        for (size_t i = 0; i < length; i++)
        {
            if (isalnum((unsigned char)str[i]) ||
                (str[i] == '-') ||
                (str[i] == '_') ||
                (str[i] == '.') ||
                (str[i] == '~'))
                strTemp += str[i];
            else if (str[i] == ' ')
                strTemp += "+";
            else
            {
                strTemp += '%';
                strTemp += ToHex((unsigned char)str[i] >> 4);
                strTemp += ToHex((unsigned char)str[i] % 16);
            }
        }
        return strTemp;
    }
    static std::string UrlDecode(const std::string& str)
    {
        std::string strTemp = "";
        size_t length = str.length();
        for (size_t i = 0; i < length; i++)
        {
            if (str[i] == '+') strTemp += ' ';
            else if (str[i] == '%')
            {
                //assert(i + 2 < length);
                unsigned char high = FromHex((unsigned char)str[++i]);
                unsigned char low = FromHex((unsigned char)str[++i]);
                strTemp += high * 16 + low;
            }
            else strTemp += str[i];
        }
        return strTemp;
    }
private:
    ULONG m_refCount = 0;
    DWORD m_dwCookie = 0;
    UINT64 m_nOwnedSize = 0;
    BOOL m_bInitFlag = FALSE;
    IUnknown* m_pIUnknownHandler = NULL;
    HANDLE m_hfile = INVALID_HANDLE_VALUE;
    IWinHttpRequest* m_pIWinHttpRequest = NULL;
    IConnectionPoint* m_pIConnectionPoint = NULL;
    IConnectionPointContainer* m_pIConnectionPointContainer = NULL;
    typedef INT(__stdcall* PFN_CallBackHandlerValue)(LPCVOID lpValue, LPCVOID lpParam, LPVOID lpInstance);
    typedef HRESULT(__stdcall* PFN_CallBackHandlerIWinHttpRequest)(IWinHttpRequest* pIWinHttpRequest, LPVOID lpInstance);
public:
    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, __RPC__deref_out void __RPC_FAR* __RPC_FAR* ppvObject)
    {
        if (riid == IID_IWinHttpRequestEvents)
        {
            m_refCount++;
            *ppvObject = (void*)this;
            return S_OK;
        }
        if (riid == IID_IUnknown)
        {
            m_refCount++;
            *ppvObject = (void*)this;
            return S_OK;
        }
        return E_NOINTERFACE;
    }
    virtual ULONG STDMETHODCALLTYPE AddRef(void)
    {
        m_refCount++;
        return 0;
    }
    virtual ULONG STDMETHODCALLTYPE Release(void)
    {
        m_refCount--;
        if (m_refCount == 0)
        {
            delete this;
        }
        return m_refCount;
    }
    virtual void STDMETHODCALLTYPE OnResponseStart(LONG Status, BSTR ContentType)
    {
        //printf("[%s]:%d Status=%d, ContentType=%ws\n", __func__, __LINE__, Status, ContentType);
    }
    virtual void STDMETHODCALLTYPE OnResponseDataAvailable(SAFEARRAY** Data)
    {
        //printf("[%s]:%d len=%lu\n", __func__, __LINE__, (*Data)->rgsabound[0].cElements);
        if ((*Data)->rgsabound[0].cElements > 0)
        {
            //printf("%s", (const char*)((*Data)->pvData));//        
            if (m_hfile != INVALID_HANDLE_VALUE)
            {
                WriteFile(m_hfile, (*Data)->pvData, (*Data)->rgsabound[0].cElements, NULL, NULL);
                //FlushFileBuffers(m_hfile);
                m_nOwnedSize += (*Data)->rgsabound[0].cElements;
                //printf("%lld\r", m_nOwnedSize);
            }
        }
    }
    virtual void STDMETHODCALLTYPE OnResponseFinished()
    {
        if (m_hfile != INVALID_HANDLE_VALUE)
        {
            CloseHandle(m_hfile);
            m_hfile = INVALID_HANDLE_VALUE;
        }
    }
    virtual void STDMETHODCALLTYPE OnError(LONG ErrorNumber, BSTR ErrorDescription)
    {
        //printf("[%s]:%d ErrorNumber=%d, ErrorDescription=%ws\n", __func__, __LINE__, ErrorNumber, ErrorDescription);
        if (m_hfile != INVALID_HANDLE_VALUE)
        {
            CloseHandle(m_hfile);
            m_hfile = INVALID_HANDLE_VALUE;
        }
    }
public:
    CWinhttpRequest() {
        m_bInitFlag = (
            SUCCEEDED(::CoInitialize(NULL)) &&
            SUCCEEDED(this->QueryInterface(IID_IUnknown, (void**)&m_pIUnknownHandler)) &&
            SUCCEEDED(CoCreateInstance(CLSID_WinHttpRequest, NULL, CLSCTX_INPROC_SERVER, IID_IWinHttpRequest, (void**)&m_pIWinHttpRequest)) &&
            SUCCEEDED(m_pIWinHttpRequest->QueryInterface(IID_IConnectionPointContainer, (void**)&m_pIConnectionPointContainer)) &&
            SUCCEEDED(m_pIConnectionPointContainer->FindConnectionPoint(IID_IWinHttpRequestEvents, &m_pIConnectionPoint)) &&
            SUCCEEDED(m_pIConnectionPoint->Advise(m_pIUnknownHandler, &m_dwCookie)) &&
            EnableRedirects() && SetSslErrorIgnoreFlags() && EnableHttpsToHttpRedirects()
            );
    }
    virtual ~CWinhttpRequest() {
        if (m_bInitFlag == TRUE)
        {
            m_bInitFlag = FALSE;
            m_pIConnectionPoint->Unadvise(m_dwCookie);
            if (m_hfile != INVALID_HANDLE_VALUE)
            {
                CloseHandle(m_hfile);
                m_hfile = INVALID_HANDLE_VALUE;
            }
            if (m_pIConnectionPoint)
            {
                m_pIConnectionPoint->Release();
                m_pIConnectionPoint = NULL;
            }
            if (m_pIConnectionPointContainer)
            {
                m_pIConnectionPointContainer->Release();
                m_pIConnectionPointContainer = NULL;
            }
            if (m_pIWinHttpRequest)
            {
                m_pIWinHttpRequest->Release();
                m_pIWinHttpRequest = NULL;
            }
            ::CoUninitialize();
        }
    }
public:
    BOOL SetSslErrorIgnoreFlags(WinHttpRequestSslErrorFlags sslErrorIgnoreFlags = SslErrorFlag_Ignore_All)
    {
        HRESULT hr = S_FALSE;
        VARIANT varSslErrorIgnoreFlags = { 0 };
        VariantInit(&varSslErrorIgnoreFlags);
        V_VT(&varSslErrorIgnoreFlags) = VT_I4;
        V_I4(&varSslErrorIgnoreFlags) = sslErrorIgnoreFlags;
        hr = SUCCEEDED(m_pIWinHttpRequest->put_Option(WinHttpRequestOption_SslErrorIgnoreFlags, varSslErrorIgnoreFlags));
        VariantClear(&varSslErrorIgnoreFlags);
        return hr;
    }
    BOOL SetSecureProtocols(WinHttpRequestSecureProtocols secureProtocols = SecureProtocol_ALL)
    {
        HRESULT hr = S_FALSE;
        VARIANT varSecureProtocols = { 0 };
        VariantInit(&varSecureProtocols);
        V_VT(&varSecureProtocols) = VT_I4;
        V_I4(&varSecureProtocols) = secureProtocols;
        hr = SUCCEEDED(m_pIWinHttpRequest->put_Option(WinHttpRequestOption_SecureProtocols, varSecureProtocols));
        VariantClear(&varSecureProtocols);
        return hr;
    }
    BOOL EnableRedirects(BOOL bEnableRedirects = TRUE)
    {
        HRESULT hr = S_FALSE;
        VARIANT varEnableRedirects = { 0 };
        VariantInit(&varEnableRedirects);
        V_VT(&varEnableRedirects) = VT_BOOL;
        V_BOOL(&varEnableRedirects) = (bEnableRedirects == TRUE) ? VARIANT_TRUE : VARIANT_FALSE;
        hr = SUCCEEDED(m_pIWinHttpRequest->put_Option(WinHttpRequestOption_EnableRedirects, varEnableRedirects));
        VariantClear(&varEnableRedirects);
        return hr;
    }
    BOOL EnableHttpsToHttpRedirects(BOOL bEnableHttpsToHttpRedirects = TRUE)
    {
        HRESULT hr = S_FALSE;
        VARIANT varEnableHttpsToHttpRedirects = { 0 };
        VariantInit(&varEnableHttpsToHttpRedirects);
        V_VT(&varEnableHttpsToHttpRedirects) = VT_BOOL;
        V_BOOL(&varEnableHttpsToHttpRedirects) = (bEnableHttpsToHttpRedirects == TRUE) ? VARIANT_TRUE : VARIANT_FALSE;
        hr = SUCCEEDED(m_pIWinHttpRequest->put_Option(WinHttpRequestOption_EnableHttpsToHttpRedirects, varEnableHttpsToHttpRedirects));
        VariantClear(&varEnableHttpsToHttpRedirects);
        return hr;
    }
    BOOL EnableTracing(BOOL bEnableTracing = TRUE)
    {
        HRESULT hr = S_FALSE;
        VARIANT varEnableTracing = { 0 };
        VariantInit(&varEnableTracing);
        V_VT(&varEnableTracing) = VT_BOOL;
        V_BOOL(&varEnableTracing) = (bEnableTracing == TRUE) ? VARIANT_TRUE : VARIANT_FALSE;
        hr = SUCCEEDED(m_pIWinHttpRequest->put_Option(WinHttpRequestOption_EnableTracing, varEnableTracing));
        VariantClear(&varEnableTracing);
        return hr;
    }
    BOOL SetRequestHeader(LPCWSTR lpszHeader, LPCWSTR lpszValue)
    {
        return SUCCEEDED(m_pIWinHttpRequest->SetRequestHeader((BSTR)lpszHeader, (BSTR)lpszValue));
    }
    BOOL PutOption(WinHttpRequestOption nOption, const VARIANT& varValue)
    {
        return SUCCEEDED(m_pIWinHttpRequest->put_Option(nOption, varValue));
    }
public:
    BOOL GetStatus(long& status)
    {
        // Get Status.
        return SUCCEEDED(m_pIWinHttpRequest->get_Status(&status));
    }
    BOOL GetStatusText(const PFN_CallBackHandlerValue& pfnCallBackHandler, LPVOID lpInstance = NULL)
    {
        BOOL bRet = FALSE;
        BSTR bstrStatusText = NULL;
        bRet = SUCCEEDED(m_pIWinHttpRequest->get_StatusText(&bstrStatusText));
        if ((bRet == TRUE) && (bstrStatusText != NULL))
        {
            if (pfnCallBackHandler != NULL)
            {
                pfnCallBackHandler(bstrStatusText, bstrStatusText, lpInstance);
            }
            SysFreeString(bstrStatusText);
            bstrStatusText = NULL;
        }
        return bRet;
    }
    BOOL GetResponseHeader(LPCWSTR lpHeader, const PFN_CallBackHandlerValue& pfnCallBackHandler, LPVOID lpInstance = NULL)
    {
        BOOL bRet = FALSE;
        BSTR bstrResponseHeader = NULL;
        bRet = SUCCEEDED(m_pIWinHttpRequest->GetResponseHeader((BSTR)lpHeader, &bstrResponseHeader));
        if ((bRet == TRUE) && (bstrResponseHeader != NULL))
        {
            if (pfnCallBackHandler != NULL)
            {
                pfnCallBackHandler(bstrResponseHeader, bstrResponseHeader, lpInstance);
            }
            SysFreeString(bstrResponseHeader);
            bstrResponseHeader = NULL;
        }
        return bRet;
    }
    BOOL GetAllResponseHeaders(const PFN_CallBackHandlerValue& pfnCallBackHandler, LPVOID lpInstance = NULL)
    {
        BOOL bRet = FALSE;
        BSTR bstrResponseHeaders = NULL;
        bRet = SUCCEEDED(m_pIWinHttpRequest->GetAllResponseHeaders(&bstrResponseHeaders));
        if ((bRet == TRUE) && (bstrResponseHeaders != NULL))
        {
            if (pfnCallBackHandler != NULL)
            {
                pfnCallBackHandler(bstrResponseHeaders, bstrResponseHeaders, lpInstance);
            }
            SysFreeString(bstrResponseHeaders);
            bstrResponseHeaders = NULL;
        }
        return bRet;
    }
    BOOL GetResponseText(const PFN_CallBackHandlerValue& pfnCallBackHandler, LPVOID lpInstance = NULL)
    {
        BOOL bRet = FALSE;
        BSTR bstrResponseText = NULL;
        BSTR bstrResponseHeaders = NULL;
        bRet = SUCCEEDED(m_pIWinHttpRequest->GetAllResponseHeaders(&bstrResponseHeaders));
        if ((bRet == TRUE) && (bstrResponseHeaders != NULL))
        {
            bRet = SUCCEEDED(m_pIWinHttpRequest->get_ResponseText(&bstrResponseText));
            if ((bRet == TRUE) && (bstrResponseText != NULL))
            {
                if (pfnCallBackHandler != NULL)
                {
                    pfnCallBackHandler(bstrResponseText, bstrResponseHeaders, lpInstance);
                }
                SysFreeString(bstrResponseText);
                bstrResponseText = NULL;
            }
            SysFreeString(bstrResponseHeaders);
            bstrResponseHeaders = NULL;
        }
        return bRet;
    }
    BOOL GetResponseBody(const PFN_CallBackHandlerValue& pfnCallBackHandler, LPVOID lpInstance = NULL)
    {
        BOOL bRet = FALSE;
        VARIANT varResponseBody = {};
        BSTR bstrResponseHeaders = NULL;
        bRet = SUCCEEDED(m_pIWinHttpRequest->GetAllResponseHeaders(&bstrResponseHeaders));
        if ((bRet == TRUE) && (bstrResponseHeaders != NULL))
        {
            VariantInit(&varResponseBody);
            bRet = SUCCEEDED(m_pIWinHttpRequest->get_ResponseBody(&varResponseBody));
            if (bRet == TRUE)
            {
                if (pfnCallBackHandler != NULL)
                {
                    pfnCallBackHandler(&varResponseBody, bstrResponseHeaders, lpInstance);
                }
            }
            VariantClear(&varResponseBody);
            SysFreeString(bstrResponseHeaders);
            bstrResponseHeaders = NULL;
        }
        return bRet;
    }
    BOOL GetResponseStream(const PFN_CallBackHandlerValue& pfnCallBackHandler, LPVOID lpInstance = NULL)
    {
        BOOL bRet = FALSE;
        HRESULT hr = S_OK;
        IStream* pIStream = NULL;
        VARIANT varResponseStream = {};
        BSTR bstrResponseHeaders = NULL;
        bRet = SUCCEEDED(m_pIWinHttpRequest->GetAllResponseHeaders(&bstrResponseHeaders));
        if ((bRet == TRUE) && (bstrResponseHeaders != NULL))
        {
            VariantInit(&varResponseStream);
            bRet = SUCCEEDED(m_pIWinHttpRequest->get_ResponseStream(&varResponseStream));
            if (bRet == TRUE)
            {
            	// Check that an IStream was received.
                if ((V_VT(&varResponseStream) == VT_UNKNOWN) || (V_VT(&varResponseStream) == VT_STREAM))
                {
                    // Get IStream interface pIStream.
                    if (SUCCEEDED(hr = V_UNKNOWN(&varResponseStream)->QueryInterface(IID_IStream, reinterpret_cast<void**>(&pIStream))))
                    {
                        if (pfnCallBackHandler != NULL)
                        {
                            pfnCallBackHandler(pIStream, bstrResponseHeaders, lpInstance);
                        }
                        pIStream->Release();
                    }
                }
            }
            VariantClear(&varResponseStream);
            SysFreeString(bstrResponseHeaders);
            bstrResponseHeaders = NULL;
        }
        return bRet;
    }
    BOOL Request_Response_Async(LPCWSTR lpszUrl, LPCWSTR lpszMethod, LPCWSTR lpszBody, PFN_CallBackHandlerIWinHttpRequest pfnCallback = NULL, LPVOID lpInstance = NULL)
    {
        // variable for return value
        HRESULT hr = S_OK;
        VARIANT varDataFlag = { 0 };
        VARIANT_BOOL varResult = { 0 };
        if (SUCCEEDED(hr))
        {
            VariantInit(&varDataFlag);
            V_VT(&varDataFlag) = VT_BOOL;
            V_BOOL(&varDataFlag) = VARIANT_TRUE;
            // Open WinHttpRequest.
            hr = m_pIWinHttpRequest->Open((BSTR)lpszMethod, (BSTR)lpszUrl, varDataFlag);
            VariantClear(&varDataFlag);
        }
        if (SUCCEEDED(hr))
        {
            hr = m_pIWinHttpRequest->SetRequestHeader((BSTR)L"Accept-Language", (BSTR)L"zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2");
        }
        if (SUCCEEDED(hr))
        {
            hr = m_pIWinHttpRequest->SetRequestHeader((BSTR)L"User-Agent", (BSTR)L"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0");
        }
        if (SUCCEEDED(hr))
        {
            if (pfnCallback != NULL)
            {
                hr = pfnCallback(m_pIWinHttpRequest, lpInstance);
            }
        }
        if (SUCCEEDED(hr))
        {
            VariantInit(&varDataFlag);
            if ((lpszBody != NULL) && ((*lpszBody) != L'\0'))
            {
                V_VT(&varDataFlag) = VT_BSTR;
                varDataFlag.bstrVal = (BSTR)lpszBody;
            }
            else
            {
                V_VT(&varDataFlag) = VT_ERROR;
            }
			// Send Request.
            hr = m_pIWinHttpRequest->Send(varDataFlag);
            if ((V_VT(&varDataFlag) == VT_BSTR) && (varDataFlag.bstrVal != NULL))
            {
                V_VT(&varDataFlag) = VT_EMPTY;
                varDataFlag.bstrVal = NULL;
            }
            VariantClear(&varDataFlag);
        }
        if (SUCCEEDED(hr))
        {
            VariantInit(&varDataFlag);
            V_VT(&varDataFlag) = VT_EMPTY;
            // Wait for response.
            hr = m_pIWinHttpRequest->WaitForResponse(varDataFlag, &varResult);
            VariantClear(&varDataFlag);
        }
        return SUCCEEDED(hr);
    }
public:
    BOOL Get(LPCWSTR lpszUrl, LPCWSTR lpszFileName = NULL, PFN_CallBackHandlerIWinHttpRequest  pfnCallback = NULL, LPVOID lpInstance = NULL)
    {
        BOOL bRet = TRUE;
        if ((lpszFileName != NULL) && ((*lpszFileName) != L'\0'))
        {
            bRet &= ((m_hfile = CreateFileW(lpszFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, NULL, NULL)) != INVALID_HANDLE_VALUE);
        }
        bRet &= Request_Response_Async(lpszUrl, L"GET", NULL, pfnCallback, lpInstance);
        if (m_hfile != INVALID_HANDLE_VALUE)
        {
            CloseHandle(m_hfile);
            m_hfile = INVALID_HANDLE_VALUE;
        }
        return bRet;
    }
    BOOL Head(LPCWSTR lpszUrl, PFN_CallBackHandlerIWinHttpRequest pfnCallback = NULL, LPVOID lpInstance = NULL)
    {
        HRESULT hr = S_FALSE;
        VARIANT varFlag = { 0 };
        VariantInit(&varFlag);
        V_VT(&varFlag) = VT_BOOL;
        V_BOOL(&varFlag) = VARIANT_FALSE;
        hr = (SUCCEEDED(m_pIWinHttpRequest->put_Option(WinHttpRequestOption_EnableRedirects, varFlag)) && Request_Response_Async(lpszUrl, L"HEAD", NULL, pfnCallback, lpInstance));
        VariantClear(&varFlag);
        return hr;
    }
    BOOL Options(LPCWSTR lpszUrl, PFN_CallBackHandlerIWinHttpRequest  pfnCallback = NULL, LPVOID lpInstance = NULL)
    {
        return Request_Response_Async(lpszUrl, L"OPTIONS", NULL, pfnCallback, lpInstance);
    }
    BOOL Post(LPCWSTR lpszUrl, LPCWSTR lpszBody, PFN_CallBackHandlerIWinHttpRequest  pfnCallback = NULL, LPVOID lpInstance = NULL)
    {
        return Request_Response_Async(lpszUrl, L"POST", lpszBody, pfnCallback, lpInstance);
    }
};

3.测试代码

BOOL DoGetPage(const std::wstring& uri)
{
	BOOL bRet = FALSE;
	LONG nStatus = 0;
	CWinhttpRequest winhttpRequest = {};
	std::wstring wUrl = L"http://www.ceic.ac.cn/ajax/search?page=1&&start=2023-02-03&&end=2023-02-06&&jingdu1=-180&&jingdu2=180&&weidu1=-90&&weidu2=90&&height1=0&&height2=1000000&&zhenji1=0&&zhenji2=100&&callback=jQuery18006827866337828736_1675644566680&_=1675669770074";// +uri;
	bRet = winhttpRequest.Get(wUrl.c_str(), L"", [](IWinHttpRequest* pIWinHttpRequest, LPVOID lpInstance)->HRESULT
		{
			HRESULT hr = S_OK;
			hr &= pIWinHttpRequest->SetRequestHeader((BSTR)L"Pragma", (BSTR)L"no-cache");
			hr &= pIWinHttpRequest->SetRequestHeader((BSTR)L"Accept", (BSTR)L"application/json, text/javascript, */*");
			hr &= pIWinHttpRequest->SetRequestHeader((BSTR)L"Accept-Encoding", (BSTR)L"gzip, deflate, br");
			hr &= pIWinHttpRequest->SetRequestHeader((BSTR)L"Content-Type", (BSTR)L"application/x-www-form-urlencoded");
			hr &= pIWinHttpRequest->SetRequestHeader((BSTR)L"Connection", (BSTR)L"Keep-Alive");
			hr &= pIWinHttpRequest->SetRequestHeader((BSTR)L"User-Agent", (BSTR)L"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0");
			return hr;
		}, this);
	if (bRet == TRUE)
	{
		bRet = winhttpRequest.GetStatus(nStatus);
		switch (nStatus)
		{
		case 200:
		{
			bRet = winhttpRequest.GetResponseBody([](LPCVOID lpValue, LPCVOID lpParam, LPVOID lpInstance)->INT
				{
					CEarthQuakeProbeApp* thiz = (CEarthQuakeProbeApp*)lpInstance;
					VARIANT* pVariant = (VARIANT*)lpValue;
					BSTR bstrHeaders = (BSTR)lpParam;
					if (pVariant->vt == (VT_ARRAY | VT_UI1))
					{
						if (pVariant->parray->rgsabound[0].cElements > 0)
						{
							std::string sData((PCHAR)pVariant->parray->pvData, pVariant->parray->rgsabound[0].cElements);
							std::cout << sData << std::endl;
							std::wstring wHeaders(bstrHeaders);
							for (auto it = wHeaders.begin(); it != wHeaders.end();)if (*it == L'\r' || *it == L'\n' || *it == L' ')(it = wHeaders.erase(it)); else(it++);
							if (StrStrIW(wHeaders.c_str(), L"content-encoding:gzip") != NULL)
							{
								ULONG nTextSize = pVariant->parray->rgsabound[0].cElements * (MAX_WBITS + 1);
								std::string sText(nTextSize, '\0');
								int nRet = CWinhttpRequest::GZipDecompress((unsigned char*)sText.data(), &nTextSize, (PUCHAR)sData.data(), sData.size());
								if (nRet == 0)
								{
									std::wstring resp = UTF8ToWIDE(sText.c_str()).c_str();
									std::string respA = UTF8ToANSI(sText.c_str()).c_str();
								}
							}
							else
							{
								std::string respA = UTF8ToANSI(sData.c_str()).c_str();
							}
						}
					}
					return 0;
				}, this);
		}
		break;
		}
	}
	return bRet;
}


×
打赏作者
最新回复 (0)
只看楼主
全部楼主
返回