开发者

Call server with WinInet and WinHTTP

开发者 https://www.devze.com 2022-12-22 14:17 出处:网络
I have a request that works fine when I use the WinInet API. I now want to make that request with the WinHTTP API as I already use it in my project and as it is simply better. My request is used for c

I have a request that works fine when I use the WinInet API. I now want to make that request with the WinHTTP API as I already use it in my project and as it is simply better. My request is used for calling JSON. I already authenticated before calling this. When authenticating I get a SessionID that I send via cookie.

So here is my working WinInet code:

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;

So I now want to do the same using the WinHTTP API. Here is what I have for the moment:

DWORD dwError = 0;
HIN开发者_运维知识库TERNET 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;

With that latter call I always receive a 401 but I should get a 200 like I do with the first method. I also found out that I get a 401 with the first call when I don't specify the INTERNET_FLAG_NO_COOKIES flag. So I suspect something with the cookie header is wrong. Do anyone see what I'm doing wrong? Or what is the difference between the two methods?

Thx...


Looks about right. If I were you I would hook up an HTTP debugging proxy, like Fiddler, and examine and compare the HTTP traffic for the two methods. That might point you to what you need to do.


Ok, I found it. Wasn't obvious from the code I posted...
The string cstrMethod contains a user id that I extracted previously from the response header from an authentication call. This id is then used for constructing the method call. Now problem was that the user id comes from a response header so it ends with \r\n. So the constructed method call also contains \r\n and as therefore the user id is wrong I get the 401.
So I had to trim the user id string from the header before I could use it for further calls.
Well it's a little bit odd that the WinInet call accepted the \r\n.

0

精彩评论

暂无评论...
验证码 换一张
取 消