We’re going to take a look at the following libraries:
- WinInet
- WinHttp
- Casablanca
- Qt
- POCO
- wxWidgets
- Boost.Asio
- libcurl
- neon
- .NET (С++/CLI)
- IXMLHTTPRequest
- HappyHttp
- cpp-netlib
WinInet
Website: http://msdn.microsoft.com/en-us/library/windows/desktop/aa385483(v=vs.85).aspxPlatform: Windows 95 and later
Example
#include
#include
/// ....
HINTERNET hIntSession =
::InternetOpen(_T("MyApp"), INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);
HINTERNET hHttpSession =
InternetConnect(hIntSession, _T("api.twitter.com"), 80, 0, 0, INTERNET_SERVICE_HTTP, 0, NULL);
HINTERNET hHttpRequest = HttpOpenRequest(
hHttpSession,
_T("GET"),
_T("1/statuses/user_timeline.xml?screen_name=twitterapi"),
0, 0, 0, INTERNET_FLAG_RELOAD, 0);
TCHAR* szHeaders = _T("Content-Type: text/html\nMySpecialHeder: whatever");
CHAR szReq[1024] = "";
if( !HttpSendRequest(hHttpRequest, szHeaders, _tcslen(szHeaders), szReq, strlen(szReq))) {
DWORD dwErr = GetLastError();
/// handle error
}
CHAR szBuffer[1025];
DWORD dwRead=0;
while(::InternetReadFile(hHttpRequest, szBuffer, sizeof(szBuffer)-1, &dwRead) && dwRead) {
szBuffer[dwRead] = 0;
OutputDebugStringA(szBuffer);
dwRead=0;
}
::InternetCloseHandle(hHttpRequest);
::InternetCloseHandle(hHttpSession);
::InternetCloseHandle(hIntSession);
WinHttp
Website: http://msdn.microsoft.com/en-us/library/windows/desktop/aa382925(v=vs.85).aspxPlatform: Windows 2000 and later
Example
DWORD dwSize = 0;
DWORD dwDownloaded = 0;
LPSTR pszOutBuffer;
BOOL bResults = FALSE;
HINTERNET hSession = NULL,
hConnect = NULL,
hRequest = NULL;
// Use WinHttpOpen to obtain a session handle.
hSession = WinHttpOpen( L"WinHTTP Example/1.0",
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS, 0 );
// Specify an HTTP server.
if( hSession )
hConnect = WinHttpConnect( hSession, L"www.microsoft.com",
INTERNET_DEFAULT_HTTPS_PORT, 0 );
// Create an HTTP request handle.
if( hConnect )
hRequest = WinHttpOpenRequest( hConnect, L"GET", NULL,
NULL, WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
WINHTTP_FLAG_SECURE );
// Send a request.
if( hRequest )
bResults = WinHttpSendRequest( hRequest,
WINHTTP_NO_ADDITIONAL_HEADERS, 0,
WINHTTP_NO_REQUEST_DATA, 0,
0, 0 );
// End the request.
if( bResults )
bResults = WinHttpReceiveResponse( hRequest, NULL );
// Keep checking for data until there is nothing left.
if( bResults )
{
do
{
// Check for available data.
dwSize = 0;
if( !WinHttpQueryDataAvailable( hRequest, &dwSize ) )
printf( "Error %u in WinHttpQueryDataAvailable.\n",
GetLastError( ) );
// Allocate space for the buffer.
pszOutBuffer = new char[dwSize+1];
if( !pszOutBuffer )
{
printf( "Out of memory\n" );
dwSize=0;
}
else
{
// Read the data.
ZeroMemory( pszOutBuffer, dwSize+1 );
if( !WinHttpReadData( hRequest, (LPVOID)pszOutBuffer,
dwSize, &dwDownloaded ) )
printf( "Error %u in WinHttpReadData.\n", GetLastError( ) );
else
printf( "%s", pszOutBuffer );
// Free the memory allocated to the buffer.
delete [] pszOutBuffer;
}
} while( dwSize > 0 );
}
// Report any errors.
if( !bResults )
printf( "Error %d has occurred.\n", GetLastError( ) );
// Close any open handles.
if( hRequest ) WinHttpCloseHandle( hRequest );
if( hConnect ) WinHttpCloseHandle( hConnect );
if( hSession ) WinHttpCloseHandle( hSession );
Casablanca
Website: https://casablanca.codeplex.comPlatform: all
Example
http_client client(L"http://www.myhttpserver.com");
http_request request(methods::GET);
client.request(request).then([](http_response response)
{
// Perform actions here to inspect the HTTP response...
if(response.status_code() == status_codes::OK)
{
}
});
Qt
Website: http://qt-project.orgPlatform: all
Example use for Qt 4.x (already outdated)
#include "handler.h"
Handler::Handler(QObject *parent) :QObject(parent) {
http = new QHttp(this);
connect(http, SIGNAL(stateChanged(int)), this, SLOT(stateChanged(int)));
connect(http, SIGNAL(responseHeaderReceived(QHttpResponseHeader)), this, SLOT(responseHeaderReceived(QHttpResponseHeader)));
connect(http, SIGNAL(requestFinished(int,bool)), this, SLOT(requestFinished(int,bool)));
}
void Handler::doHttp() {
http->setHost("google.com");
http->get("/");
}
void Handler::stateChanged(int state) {
switch(state) {
case 0:
qDebug() << "Unconnected";
break;
case 1:
qDebug() << "Host Lookup";
break;
case 2:
qDebug() << "Connecting";
break;
case 3:
qDebug() << "Sending";
break;
case 4:
qDebug() << "Reading";
break;
case 5:
qDebug() << "Connect";
break;
case 6:
qDebug() << "Closing";
break;
}
}
void Handler::responseHeaderReceived(const QHttpResponseHeader &resp) {
qDebug() << "Size : " << resp.contentLength();
qDebug() << "Type : " << resp.contentType();
qDebug() << "Status Code : " << resp.statusCode();
}
void Handler::requestFinished(int id, bool error) {
qDebug() << "Request Id : " << id;
if(error) {
qDebug() << "Error";
} else {
qDebug() << http->readAll();
}
}
Example use for Qt 5.x
void Downloader::doDownload()
{
manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(replyFinished(QNetworkReply*)));
manager->get(QNetworkRequest(QUrl("http://google.com")));
}
void Downloader::replyFinished (QNetworkReply *reply)
{
if(reply->error() != QNetworkReply::NoError)
{
qDebug() << "ERROR!";
qDebug() << reply->errorString();
}
else
{
qDebug() << reply->header(QNetworkRequest::ContentTypeHeader).toString();
qDebug() << reply->header(QNetworkRequest::LastModifiedHeader).toDateTime().toString();
qDebug() << reply->header(QNetworkRequest::ContentLengthHeader).toULongLong();
qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
qDebug() << reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
QFile file("C:/Qt/Dummy/downloaded.txt");
if(file.open(QFile::Append))
{
file.write(reply->readAll());
}
}
reply->deleteLater();
}
POCO
Website: http://pocoproject.orgPlatform: all
Example
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace Poco::Net;
using namespace Poco;
using namespace std;
int main(int argc, char **argv)
{
if (argc != 2)
{
cout << "Usage: " << argv[0] << " " << endl;
cout << " fetches the resource identified by and print it" << endl;
return -1;
}
try
{
// prepare session
URI uri(argv[1]);
HTTPClientSession session(uri.getHost(), uri.getPort());
// prepare path
string path(uri.getPathAndQuery());
if (path.empty()) path = "/";
// send request
HTTPRequest req(HTTPRequest::HTTP_GET, path, HTTPMessage::HTTP_1_1);
session.sendRequest(req);
// get response
HTTPResponse res;
cout << res.getStatus() << " " << res.getReason() << endl;
// print response
istream &is = session.receiveResponse(res);
StreamCopier::copyStream(is, cout);
}
catch (Exception &ex)
{
cerr << ex.displayText() << endl;
return -1;
}
return 0;
}
wxWidgets
Website: http://www.wxwidgets.orgPlatform: all
Example
#include
#include
wxHTTP get;
get.SetHeader(_T("Content-type"), _T("text/html; charset=utf-8"));
get.SetTimeout(10); // 10 seconds of timeout instead of 10 minutes ...
// this will wait until the user connects to the internet. It is important in case of dialup (or ADSL) connections
while (!get.Connect(_T("www.google.com"))) // only the server, no pages here yet ...
wxSleep(5);
wxApp::IsMainLoopRunning(); // should return true
// use _T("/") for index.html, index.php, default.asp, etc.
wxInputStream *httpStream = get.GetInputStream(_T("/intl/en/about.html"));
// wxLogVerbose( wxString(_T(" GetInputStream: ")) << get.GetResponse() << _T("-") << ((resStream)? _T("OK ") : _T("FAILURE ")) << get.GetError() );
if (get.GetError() == wxPROTO_NOERR)
{
wxString res;
wxStringOutputStream out_stream(&res);
httpStream->Read(out_stream);
wxMessageBox(res);
// wxLogVerbose( wxString(_T(" returned document length: ")) << res.Length() );
}
else
{
wxMessageBox(_T("Unable to connect!"));
}
wxDELETE(httpStream);
get.Close();
Boost.Asio
Website: http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio.htmlPlatform: all
Example
#include
#include
#include
#include
#include
using boost::asio::ip::tcp;
int main(int argc, char* argv[])
{
try
{
if (argc != 3)
{
std::cout << "Usage: sync_client \n";
std::cout << "Example:\n";
std::cout << " sync_client www.boost.org /LICENSE_1_0.txt\n";
return 1;
}
boost::asio::io_service io_service;
// Get a list of endpoints corresponding to the server name.
tcp::resolver resolver(io_service);
tcp::resolver::query query(argv[1], "http");
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
// Try each endpoint until we successfully establish a connection.
tcp::socket socket(io_service);
boost::asio::connect(socket, endpoint_iterator);
// Form the request. We specify the "Connection: close" header so that the
// server will close the socket after transmitting the response. This will
// allow us to treat all data up until the EOF as the content.
boost::asio::streambuf request;
std::ostream request_stream(&request);
request_stream << "GET " << argv[2] << " HTTP/1.0\r\n";
request_stream << "Host: " << argv[1] << "\r\n";
request_stream << "Accept: */*\r\n";
request_stream << "Connection: close\r\n\r\n";
// Send the request.
boost::asio::write(socket, request);
// Read the response status line. The response streambuf will automatically
// grow to accommodate the entire line. The growth may be limited by passing
// a maximum size to the streambuf constructor.
boost::asio::streambuf response;
boost::asio::read_until(socket, response, "\r\n");
// Check that response is OK.
std::istream response_stream(&response);
std::string http_version;
response_stream >> http_version;
unsigned int status_code;
response_stream >> status_code;
std::string status_message;
std::getline(response_stream, status_message);
if (!response_stream || http_version.substr(0, 5) != "HTTP/")
{
std::cout << "Invalid response\n";
return 1;
}
if (status_code != 200)
{
std::cout << "Response returned with status code " << status_code << "\n";
return 1;
}
// Read the response headers, which are terminated by a blank line.
boost::asio::read_until(socket, response, "\r\n\r\n");
// Process the response headers.
std::string header;
while (std::getline(response_stream, header) && header != "\r")
std::cout << header << "\n";
std::cout << "\n";
// Write whatever content we already have to output.
if (response.size() > 0)
std::cout << &response;
// Read until EOF, writing data to output as we go.
boost::system::error_code error;
while (boost::asio::read(socket, response,
boost::asio::transfer_at_least(1), error))
std::cout << &response;
if (error != boost::asio::error::eof)
throw boost::system::system_error(error);
}
catch (std::exception& e)
{
std::cout << "Exception: " << e.what() << "\n";
}
return 0;
}
libcurl
Website: http://curl.haxx.se/libcurlPlatform: all
Example
#include
#include
int main(void)
{
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://example.com");
/* example.com is redirected, so we tell libcurl to follow redirection */
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
/* always cleanup */
curl_easy_cleanup(curl);
}
return 0;
}
neon
Website: http://www.webdav.org/neonPlatform: all
Example
#include
#include
#include
#include
int httpResponseReader(void *userdata, const char *buf, size_t len)
{
string *str = (string *)userdata;
str->append(buf, len);
return 0;
}
int do_get(string host)
{
ne_session *sess;
ne_request *req;
string response;
ne_sock_init();
sess = ne_session_create("http", host.c_str(), 80);
ne_set_useragent(sess, "MyAgent/1.0");
req = ne_request_create(sess, "GET", "/SomeURL/method?with=parameter&value=data");
// if accepting only 2xx codes, use "ne_accept_2xx"
ne_add_response_body_reader(req, ne_accept_always, httpResponseReader, &response);
int result = ne_request_dispatch(req);
int status = ne_get_status(req)->code;
ne_request_destroy(req);
string errorMessage = ne_get_error(sess);
ne_session_destroy(sess);
printf("result %d, status %d\n", result, status);
cout << response << "\n";
switch (result) {
case NE_OK:
break;
case NE_CONNECT:
throw ConnectionError(errorMessage);
case NE_TIMEOUT:
throw TimeOutError(errorMessage);
case NE_AUTH:
throw AuthenticationError(errorMessage);
default:
throw AnotherWebError(errorMessage);
}
return 0;
}
.NET
Website: http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.aspxPlatform: Windows XP and later
Example
#using
using namespace System;
using namespace System::Net;
using namespace System::Text;
using namespace System::IO;
// Specify the URL to receive the request.
int main()
{
array^args = Environment::GetCommandLineArgs();
HttpWebRequest^ request = dynamic_cast(WebRequest::Create( args[ 1 ] ));
// Set some reasonable limits on resources used by this request
request->MaximumAutomaticRedirections = 4;
request->MaximumResponseHeadersLength = 4;
// Set credentials to use for this request.
request->Credentials = CredentialCache::DefaultCredentials;
HttpWebResponse^ response = dynamic_cast(request->GetResponse());
Console::WriteLine( "Content length is {0}", response->ContentLength );
Console::WriteLine( "Content type is {0}", response->ContentType );
// Get the stream associated with the response.
Stream^ receiveStream = response->GetResponseStream();
// Pipes the stream to a higher level stream reader with the required encoding format.
StreamReader^ readStream = gcnew StreamReader( receiveStream,Encoding::UTF8 );
Console::WriteLine( "Response stream received." );
Console::WriteLine( readStream->ReadToEnd() );
response->Close();
readStream->Close();
}
IXMLHTTPRequest
Website: http://msdn.microsoft.com/en-us/library/ms759148(v=vs.85).aspxPlatform: Windows XP and later
Example
#include
#include
HRESULT hr;
CComPtr 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();
HappyHttp
Website: http://scumways.com/happyhttp/happyhttp.htmlPlatform: all
Example
static int count=0;
// invoked when response headers have been received
void OnBegin( const happyhttp::Response* r, void* userdata )
{
printf( "BEGIN (%d %s)\n", r->getstatus(), r->getreason() );
count = 0;
}
// invoked to process response body data (may be called multiple times)
void OnData( const happyhttp::Response* r, void* userdata, const unsigned char* data, int n )
{
fwrite( data,1,n, stdout );
count += n;
}
// invoked when response is complete
void OnComplete( const happyhttp::Response* r, void* userdata )
{
printf( "COMPLETE (%d bytes)\n", count );
}
void TestGET()
{
happyhttp::Connection conn( "www.scumways.com", 80 );
conn.setcallbacks( OnBegin, OnData, OnComplete, 0 );
conn.request( "GET", "/happyhttp/test.php" );
while( conn.outstanding() )
conn.pump();
}
cpp-netlib
Website: http://cpp-netlib.orgPlatform: all
Example
using namespace boost::network;
using namespace boost::network::http;
client::request request_("http://127.0.0.1:8000/");
request_ << header("Connection", "close");
client client_;
client::response response_ = client_.get(request_);
std::string body_ = body(response_);
1 comment
Restbed brings asynchronous RESTful service to C++11 applications. I'm full throttle on the development and hope to have HTTP 2 functionality towards the end of the year.
I'd love to hear any feed back regarding the project.
Upload image