How do you make a HTTP request with C++?

2018-12-31 09:51发布

Is there any way to easily make a HTTP request with C++? Specifically, I want to download the contents of a page (an API) and check the contents to see if it contains a 1 or a 0. Is it also possible to download the contents into a string?

19条回答
何处买醉
2楼-- · 2018-12-31 10:14

C and C++ don't have a standard library for HTTP or even for socket connections. Over the years some portable libraries have been developed. The most widely used, as others have said, is libcurl.

Here is a list of alternatives to libcurl (coming from the libcurl's web site).

Also, for Linux, this is a simple HTTP client. You could implement your own simple HTTP GET client, but this won't work if there are authentication or redirects involved or if you need to work behind a proxy. For these cases you need a full-blown library like libcurl.

For source code with libcurl, this is the closest to what you want (Libcurl has many examples). Look at the main function. The html content will be copied to the buffer, after a successfully connection. Just replace parseHtml with your own function.

查看更多
长期被迫恋爱
3楼-- · 2018-12-31 10:15

The HTTP protocol is very simple, so it is very simple to write a HTTP client. Here is one

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

It uses HTTP GET to retrieve a file from a web server, both server and file are command line parameters. The remote file is saved to a local copy.

Disclaimer: I am the author

EDIT: edited URL

查看更多
一个人的天荒地老
4楼-- · 2018-12-31 10:17

There is a newer, less mature curl wrapper being developed called C++ Requests. Here's a simple GET request:

#include <iostream>
#include <cpr.h>

int main(int argc, char** argv) {
    auto response = cpr::Get(cpr::Url{"http://httpbin.org/get"});
    std::cout << response.text << std::endl;
}

It supports a wide variety of HTTP verbs and curl options. There's more usage documentation here.

Disclaimer: I'm the maintainer of this library.

查看更多
零度萤火
5楼-- · 2018-12-31 10:17

You can use embeddedRest library. It is lightweight header-only library. So it is easy to include it to your project and it does not require compilation cause there no .cpp files in it.

Request example from readme.md from repo:

#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;
}
查看更多
唯独是你
6楼-- · 2018-12-31 10:20

You can use ACE in order to do so:

#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;
}
查看更多
一个人的天荒地老
7楼-- · 2018-12-31 10:20

Here is some code that will work with no need to use any 3rd party library: First define your gateway, user, password and any other parameters you need to send to this specific server.

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

Here is the code itself:

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);

That should work on a Win32 API environment.

Here is an example.

查看更多
登录 后发表回答