HttpSendRequestA имеет значение false и возвращает 0 - PullRequest
0 голосов
/ 06 апреля 2020

Привет, я пытаюсь загрузить что-то, используя Win Inet с помощью агента пользователя costum. Проблема в том, что я не могу выполнить HttpSendRequestA, ошибка, которую она возвращает, равна 0, я не знаю, что означает эта ошибка, я пытался найти ее, но ничего не приходит вверх я получаю ошибку, используя std::to_string(GetLastError()); Вот код bolow

std::string GetUrlData(const std::string& resource, const std::string& host)
{
    std::string output = "";
    output.clear();

    HINTERNET hIntSession = InternetOpenA("token", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
    if (!hIntSession) {
        return "ERROR: Session Cannot Start";
    }

    HINTERNET hHttpSession = InternetConnectA(hIntSession, host.c_str(), 80, 0, 0, INTERNET_SERVICE_HTTP, 0, NULL);
    if (!hHttpSession) {
        InternetCloseHandle(hIntSession);
        return "ERROR: Cannot Connect To Internet";
    }

    HINTERNET hHttpRequest = HttpOpenRequestA(hHttpSession, "GET", resource.c_str(), 0, 0, 0, INTERNET_FLAG_RELOAD, 0);
    if (!hHttpRequest) {
        InternetCloseHandle(hHttpSession);
        InternetCloseHandle(hIntSession);
        return "ERROR: Http Request Failed";
    }

   // const char* szHeaders = "User-Agent: Mozzila\r\n";
    if (!HttpSendRequestA(hHttpRequest, NULL, 0, NULL, 0)) {
        InternetCloseHandle(hHttpRequest);
        InternetCloseHandle(hHttpSession);
        InternetCloseHandle(hIntSession);
        return "ERROR: Http Request Failed 2";

    }

    char szBuffer[1024];
    DWORD dwRead = 0;

    do {
        if (!InternetReadFile(hHttpRequest, szBuffer, sizeof(szBuffer), &dwRead)) {
            InternetCloseHandle(hHttpRequest);
            InternetCloseHandle(hHttpSession);
            InternetCloseHandle(hIntSession);
            return "ERROR: Cannot Download";
        }

        if (dwRead == 0)
            break;

        output.append(szBuffer, dwRead);
    }
    while (true);
    return output;
}

Я называю эту функцию следующим образом: std :: string data = GetUrlData("http://example.com/", "http://example.com/");

1 Ответ

0 голосов
/ 06 апреля 2020

Проблема в том, что ваш параметр host должен быть только именем хоста, а не полным URL, а ресурс должен быть только частью ресурса на хосте.

Например:

std::string data = GetUrlData("/", "example.com");

Заметка: вы приобретаете до трех ресурсов, которые необходимо высвободить вручную, и стараетесь их высвобождать, используя InternetCloseHandle(), но вскоре он становится многословным, и вы рискуете в конце концов забыть о нем. Как это случается, если ваш GetUrlData() вызов завершается успешно, вы не освобождаете каких-либо ресурсов.

Рассмотрите возможность оборачивания каждого ресурса в std::unique_ptr для его автоматического освобождения. Это не только делает его более безопасным, но и облегчает чтение и обслуживание кода.

Пример:

#include <Windows.h>
#include <wininet.h>

#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
#include <type_traits>
// custom deleter for the resource
struct internet_deleter {
    void operator()(HINTERNET hi) { InternetCloseHandle(hi); }
};

// the resource's wrapper type
using ihandle = std::unique_ptr<std::remove_pointer_t<HINTERNET>, internet_deleter>;

// functions for acquiring resources
auto RAII_InternetOpen() {
    ihandle rv(InternetOpenA("token", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0));

    if (rv) return rv;

    throw std::runtime_error("InternetOpenA: " + std::to_string(GetLastError()));
}

auto RAII_InternetConnect(const ihandle& hIntSession, const std::string& host) {
    ihandle rv(
        InternetConnectA(hIntSession.get(), host.c_str(), 80, 0, 0,
                         INTERNET_SERVICE_HTTP, 0, NULL));
    if (rv) return rv;

    throw std::runtime_error("InternetConnectA: " + std::to_string(GetLastError()));
}

auto RAII_HttpOpenRequest(const ihandle& hHttpSession, const std::string& resource) {
    ihandle rv(
        HttpOpenRequestA(hHttpSession.get(), "GET", resource.c_str(), 0, 0, 0,
                         INTERNET_FLAG_RELOAD, 0));
    if (rv) return rv;

    throw std::runtime_error("HttpOpenRequestA: " + std::to_string(GetLastError()));
}

С тремя вышеупомянутыми функциями GetUrlData() функция становится проще и не будет пропускать ресурсы:

std::string GetUrlData(const std::string& resource, const std::string& host)
{
    std::string output;

    auto hIntSession = RAII_InternetOpen();
    auto hHttpSession = RAII_InternetConnect(hIntSession, host);
    auto hHttpRequest = RAII_HttpOpenRequest(hHttpSession, resource);

    if (!HttpSendRequestA(hHttpRequest.get(), NULL, 0, NULL, 0))
        throw std::runtime_error("HttpSendRequestA: " + 
                                 std::to_string(GetLastError()));

    char szBuffer[1024];
    DWORD dwRead = 0;

    do {
        if (!InternetReadFile(hHttpRequest.get(), szBuffer, sizeof(szBuffer), &dwRead))
            throw std::runtime_error("InternetReadFile: " +
                                     std::to_string(GetLastError()));

        if (dwRead == 0)
            break;

        output.append(szBuffer, dwRead);
    } while (true);

    return output;
}

int main() {
    try {
        std::cout << GetUrlData("/", "www.google.com");
    }
    catch (const std::exception& ex) {
        std::cerr << "Exception: " << ex.what() << '\n';
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...