Как вы делаете HTTP-запрос с C ++? - PullRequest
228 голосов
/ 18 июня 2009

Есть ли способ легко сделать HTTP-запрос с C ++? В частности, я хочу загрузить содержимое страницы (API) и проверить содержимое, чтобы увидеть, содержит ли оно 1 или 0. Можно ли также загрузить содержимое в строку?

Ответы [ 20 ]

3 голосов
/ 15 августа 2016

Протокол HTTP очень прост, поэтому написать клиент HTTP очень просто. Вот один

https://github.com/pedro-vicente/lib_netsockets

Он использует HTTP GET для получения файла с веб-сервера, и сервер, и файл являются параметрами командной строки. Удаленный файл сохраняется в локальной копии.

Отказ от ответственности: я автор

РЕДАКТИРОВАТЬ: отредактированный URL

3 голосов
/ 26 октября 2018

Вот код, который будет работать без необходимости использования какой-либо сторонней библиотеки: Сначала определите свой шлюз, пользователя, пароль и любые другие параметры, которые вам нужно отправить на этот конкретный сервер.

#define USERNAME "user"
#define PASSWORD "your password"
#define GATEWAY "your gateway"

Вот сам код:

HINTERNET hOpenHandle, hResourceHandle, hConnectHandle;
const TCHAR* szHeaders = _T("Content-Type:application/json; charset=utf-8\r\n");


hOpenHandle = InternetOpen(_T("HTTPS"), INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
if (hOpenHandle == NULL)
{
    return false;
}


hConnectHandle = InternetConnect(hOpenHandle,
    GATEWAY,
    INTERNET_DEFAULT_HTTPS_PORT,
    NULL, NULL, INTERNET_SERVICE_HTTP,
    0, 1);

if (hConnectHandle == NULL)
{
    InternetCloseHandle(hOpenHandle);
    return false;
}


hResourceHandle = HttpOpenRequest(hConnectHandle,
    _T("POST"),
    GATEWAY,
    NULL, NULL, NULL, INTERNET_FLAG_SECURE | INTERNET_FLAG_KEEP_CONNECTION,
    1);

if (hResourceHandle == NULL)
{
    InternetCloseHandle(hOpenHandle);
    InternetCloseHandle(hConnectHandle);
    return false;
}

InternetSetOption(hResourceHandle, INTERNET_OPTION_USERNAME, (LPVOID)USERNAME, _tcslen(USERNAME));
InternetSetOption(hResourceHandle, INTERNET_OPTION_PASSWORD, (LPVOID)PASSWORD, _tcslen(PASSWORD));

std::string buf;
if (HttpSendRequest(hResourceHandle, szHeaders, 0, NULL, 0))
{
    while (true)
    {
        std::string part;
        DWORD size;
        if (!InternetQueryDataAvailable(hResourceHandle, &size, 0, 0))break;
        if (size == 0)break;
        part.resize(size);
        if (!InternetReadFile(hResourceHandle, &part[0], part.size(), &size))break;
        if (size == 0)break;
        part.resize(size);
        buf.append(part);
    }
}

if (!buf.empty())
{
    // Get data back
}

InternetCloseHandle(hResourceHandle);
InternetCloseHandle(hConnectHandle);
InternetCloseHandle(hOpenHandle);

Это должно работать в среде Win32 API.

Вот пример .

3 голосов
/ 19 февраля 2016

Вы можете использовать библиотеку embeddedRest . Это легкая библиотека только для заголовков. Поэтому его легко включить в проект, и он не требует компиляции, потому что в нем нет .cpp файлов.

Пример запроса от readme.md из репо:

#include "UrlRequest.hpp"

//...

UrlRequest request;
request.host("api.vk.com");
const auto countryId=1;
const auto count=1000;
request.uri("/method/database.getCities",{
    {"lang","ru"},
    {"country_id",countryId},
    {"count",count},
    {"need_all","1"},
});
request.addHeader("Content-Type: application/json");
auto response=std::move(request.perform());
if(response.statusCode()==200){
  cout<<"status code = "<<response.statusCode()<<", body = *"<<response.body()<<"*"<<endl;
}else{
  cout<<"status code = "<<response.statusCode()<<", description = "<<response.statusDescription()<<endl;
}
3 голосов
/ 10 июля 2009

C и C ++ не имеют стандартной библиотеки для HTTP или даже для сокетных соединений. За эти годы было разработано несколько портативных библиотек. Как уже говорили другие, наиболее широко используемым является libcurl .

Вот список альтернатив libcurl (с веб-сайта libcurl).

Кроме того, для Linux это простой HTTP-клиент. Вы можете реализовать свой собственный простой HTTP-клиент GET, но это не сработает, если задействованы аутентификация или перенаправления, или если вам нужно работать за прокси-сервером. Для этих случаев вам нужна полноценная библиотека, такая как libcurl.

Для исходного кода с libcurl, это наиболее близко к тому, что вы хотите (у Libcurl есть много примеров ). Посмотрите на основную функцию. Содержание html будет скопировано в буфер после успешного подключения. Просто замените parseHtml своей собственной функцией.

2 голосов
/ 22 августа 2018

Обратите внимание, что для этого не требуется libcurl, Windows.h или WinSock! Нет компиляции библиотек, нет конфигурации проекта и т. Д. У меня есть этот код, работающий в Visual Studio 2017 c ++ на Windows 10:

#pragma comment(lib, "urlmon.lib")

#include <urlmon.h>
#include <sstream>

using namespace std;

...

IStream* stream;
//Also works with https URL's - unsure about the extent of SSL support though.
HRESULT result = URLOpenBlockingStream(0, "http://google.com", &stream, 0, 0);
if (result != 0)
{
    return 1;
}
char buffer[100];
unsigned long bytesRead;
stringstream ss;
stream->Read(buffer, 100, &bytesRead);
while (bytesRead > 0U)
{
    ss.write(buffer, (long long)bytesRead);
    stream->Read(buffer, 100, &bytesRead);
}
stream.Release();
string resultString = ss.str();

Я только что понял, как это сделать, так как я хотел простой скрипт доступа к API, библиотеки, такие как libcurl, вызывали у меня всевозможные проблемы (даже когда я следовал инструкциям ...), а WinSock слишком низок уровень и сложность.

Я не совсем уверен насчет всего кода чтения IStream (особенно условия while - не стесняйтесь исправлять / улучшать), но, эй, это работает , без проблем ! (Для меня имеет смысл, что, поскольку я использовал блокирующий (синхронный) вызов , это нормально, что bytesRead всегда будет> 0U до потока ( ISequentialStream ?) закончили читать, но кто знает.)

См. Также: Справочник по URL Monikers и асинхронному подключаемому протоколу

2 голосов
/ 12 февраля 2014

Обычно я бы рекомендовал что-нибудь кроссплатформенное, например, cURL, POCO или Qt. Тем не менее, вот пример Windows !:

#include <atlbase.h>
#include <msxml6.h>
#include <comutil.h> // _bstr_t

HRESULT hr;
CComPtr<IXMLHTTPRequest> request;

hr = request.CoCreateInstance(CLSID_XMLHTTP60);
hr = request->open(
    _bstr_t("GET"),
    _bstr_t("https://www.google.com/images/srpr/logo11w.png"),
    _variant_t(VARIANT_FALSE),
    _variant_t(),
    _variant_t());
hr = request->send(_variant_t());

// get status - 200 if succuss
long status;
hr = request->get_status(&status);

// load image data (if url points to an image)
VARIANT responseVariant;
hr = request->get_responseStream(&responseVariant);
IStream* stream = (IStream*)responseVariant.punkVal;
CImage *image = new CImage();
image->Load(stream);
stream->Release();
2 голосов
/ 11 ноября 2014

Вот некоторый (относительно) простой код C ++ 11, который использует libCURL для загрузки содержимого URL в std::vector<char>:

http_download.hh

# pragma once

#include <string>
#include <vector>

std::vector<char> download(std::string url, long* responseCode = nullptr);

http_download.cc

#include "http_download.hh"

#include <curl/curl.h>
#include <sstream>
#include <stdexcept>

using namespace std;

size_t callback(void* contents, size_t size, size_t nmemb, void* user)
{
  auto chunk = reinterpret_cast<char*>(contents);
  auto buffer = reinterpret_cast<vector<char>*>(user);

  size_t priorSize = buffer->size();
  size_t sizeIncrease = size * nmemb;

  buffer->resize(priorSize + sizeIncrease);
  std::copy(chunk, chunk + sizeIncrease, buffer->data() + priorSize);

  return sizeIncrease;
}

vector<char> download(string url, long* responseCode)
{
  vector<char> data;

  curl_global_init(CURL_GLOBAL_ALL);
  CURL* handle = curl_easy_init();
  curl_easy_setopt(handle, CURLOPT_URL, url.c_str());
  curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, callback);
  curl_easy_setopt(handle, CURLOPT_WRITEDATA, &data);
  curl_easy_setopt(handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
  CURLcode result = curl_easy_perform(handle);
  if (responseCode != nullptr)
    curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, responseCode);
  curl_easy_cleanup(handle);
  curl_global_cleanup();

  if (result != CURLE_OK)
  {
    stringstream err;
    err << "Error downloading from URL \"" << url << "\": " << curl_easy_strerror(result);
    throw runtime_error(err.str());
  }

  return move(data);
}
1 голос
/ 15 мая 2019

Если вы ищете клиентскую библиотеку HTTP на C ++, которая поддерживается на нескольких платформах (Linux, Windows и Mac) для использования веб-служб Restful. Вы можете иметь ниже варианты.

  1. QT Network Library - позволяет приложению отправлять сетевые запросы и получать ответы
  2. C ++ REST SDK - появляющаяся сторонняя HTTP-библиотека с поддержкой PPL
  3. Libcurl - Вероятно, это одна из наиболее часто используемых библиотек http в родном мире.
1 голос
/ 14 июня 2017

Хотя немного поздно. Вы можете предпочесть https://github.com/Taymindis/backcurl.

Позволяет выполнять http-вызов при разработке для мобильного c ++. Подходит для разработки мобильных игр

bcl::init(); // init when using

bcl::execute<std::string>([&](bcl::Request *req) {
    bcl::setOpts(req, CURLOPT_URL , "http://www.google.com",
             CURLOPT_FOLLOWLOCATION, 1L,
             CURLOPT_WRITEFUNCTION, &bcl::writeContentCallback,
             CURLOPT_WRITEDATA, req->dataPtr,
             CURLOPT_USERAGENT, "libcurl-agent/1.0",
             CURLOPT_RANGE, "0-200000"
            );
}, [&](bcl::Response * resp) {
    std::string ret =  std::string(resp->getBody<std::string>()->c_str());
    printf("Sync === %s\n", ret.c_str());
});


bcl::cleanUp(); // clean up when no more using
0 голосов
/ 11 марта 2015

Вы можете использовать ACE для этого:

#include "ace/SOCK_Connector.h"

int main(int argc, ACE_TCHAR* argv[])
{
    //HTTP Request Header
    char* szRequest = "GET /video/nice.mp4 HTTP/1.1\r\nHost: example.com\r\n\r\n"; 
    int ilen = strlen(szRequest);

    //our buffer
    char output[16*1024];

    ACE_INET_Addr server (80, "example.com");
    ACE_SOCK_Stream peer;
    ACE_SOCK_Connector connector;
    int ires = connector.connect(peer, server);
    int sum = 0;
    peer.send(szRequest, ilen);
    while (true)
    {
        ACE_Time_Value timeout = ACE_Time_Value(15);
        int rc = peer.recv_n(output, 16*1024, &timeout);
        if (rc == -1)
        {
            break;
        }
        sum += rc;
    }
    peer.close();
    printf("Bytes transffered: %d",sum);

    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...