代码之家  ›  专栏  ›  技术社区  ›  Simon Linder

使用wininet和winhttp调用服务器

  •  1
  • Simon Linder  · 技术社区  · 16 年前


    我有一个请求,当我使用wininet api时,它可以正常工作。我现在想用WinHTTP API发出这个请求,因为我已经在我的项目中使用了它,而且它是更好的。我的请求用于调用JSON。打电话之前我已经验证过了。当认证时,我会得到一个sessionid,它是我通过cookie发送的。
    下面是我的工作wininet代码:

    DWORD dwError;
    HINTERNET hOpen = NULL, hReq = NULL;
    hOpen = InternetOpen(_T(""), INTERNET_OPEN_TYPE_DIRECT, _T(""), _T(""), 0);
    if(hOpen == NULL)
    {
        dwError = GetLastError();
        return false;
    }
    
    CString cstrCookies = _T("Cookie: JSESSIONID=") + cstrSession;
    CString cstr = _T("https://") + cstrServer + _T("/list/") + cstrFileOrFolder;
    hReq = InternetOpenUrl(hOpen, cstr, cstrCookies, -1L,
        INTERNET_FLAG_SECURE | INTERNET_FLAG_NO_COOKIES, 0); // without NO_COOKIES I'll get a 401
    if(hReq == NULL)
    {
        dwError = GetLastError();
        InternetCloseHandle(hOpen);
        return false;
    }
    
    DWORD dwCode, dwCodeSize;
    dwCodeSize = sizeof(DWORD);
    if(!HttpQueryInfo(hReq, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &dwCode, &dwCodeSize, NULL))
    {
        dwError = GetLastError();
        InternetCloseHandle(hReq);
        InternetCloseHandle(hOpen);
        return false;
    }
    
    InternetCloseHandle(hOpen);
    InternetCloseHandle(hReq);
    return dwCode == 200;
    

    所以我现在想用WinHTTP API来做同样的事情。以下是我目前的情况:

    DWORD dwError = 0;
    HINTERNET hConnect = NULL, hRequest = NULL;
    
    hConnect = WinHttpConnect(m_hSession, cstrServer, INTERNET_DEFAULT_HTTPS_PORT, 0);
    if (hConnect == NULL)
    {
        return false;
    }
    
    hRequest = WinHttpOpenRequest(hConnect, NULL, cstrMethod + _T("/list/") + cstrFileOrFolder,
        NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE);
    if (hRequest == NULL)
    {
        WinHttpCloseHandle(hConnect);
        return false;
    }
    
    DWORD dwOptionValue = WINHTTP_DISABLE_COOKIES;
    if (WinHttpSetOption(hRequest, WINHTTP_OPTION_DISABLE_FEATURE, &dwOptionValue,
        sizeof(dwOptionValue)) != TRUE)
    {
        WinHttpCloseHandle(hConnect);
        WinHttpCloseHandle(hRequest);
        return false;
    }
    
    const CString cstrHeaders = _T("Cookie: JSESSIONID=") + cstrSession;
    if (WinHttpAddRequestHeaders(hRequest, cstrHeaders, cstrHeaders.GetLength(),
        WINHTTP_ADDREQ_FLAG_ADD) != TRUE)
    {
        WinHttpCloseHandle(hConnect);
        WinHttpCloseHandle(hRequest);
        return false;
    }
    
    if (WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, -1L, WINHTTP_NO_REQUEST_DATA, 0,
        0, 0) != TRUE)
    {
        WinHttpCloseHandle(hConnect);
        WinHttpCloseHandle(hRequest);
        return false;
    }
    
    if (WinHttpReceiveResponse(hRequest, NULL) != TRUE)
    {
        WinHttpCloseHandle(hConnect);
        WinHttpCloseHandle(hRequest);
        return false;
    }
    
    DWORD dwCode, dwCodeSize;
    dwCodeSize = sizeof(DWORD);
    if(!WinHttpQueryHeaders(hRequest, WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER, NULL, &dwCode, &dwCodeSize, NULL))
    {
        WinHttpCloseHandle(hConnect);
        WinHttpCloseHandle(hRequest);
        return false;
    }
    
    WinHttpCloseHandle(hConnect);
    WinHttpCloseHandle(hRequest);
    return dwCode == 200;
    

    对于后一个调用,我总是收到401,但我应该得到200,就像第一个方法一样。我还发现,当我没有指定 INTERNET_FLAG_NO_COOKIES 旗帜。所以我怀疑cookie头有问题。有人看到我做错了什么吗?或者这两种方法有什么区别?
    谢谢。。。

    3 回复  |  直到 12 年前
        1
  •  0
  •   Cheeso    16 年前

    看起来不错。 如果我是你,我会连接一个HTTP调试代理,比如fiddler,并检查和比较两种方法的HTTP流量。这可能会告诉你你需要做什么。

        2
  •  0
  •   Simon Linder    16 年前

    好的,我找到了。从我发布的代码来看不明显…
    cstrMethod 包含以前从身份验证调用的响应头中提取的用户ID。然后,此ID用于构造方法调用。现在的问题是,用户ID来自响应头,因此以 \r\n . 因此构造的方法调用还包含 \ r\n 因此,用户ID是错误的,我得到401。
    所以在我可以使用它进行进一步的调用之前,我必须从头中修剪用户ID字符串。
    嗯,这有点奇怪,wininet呼叫接受了 \rn .

        3
  •  0
  •   Michael Haephrati    12 年前