I'm trying to make http requests from c++ using boost asio library based on the example given on boost website : http://www.boost.org/doc/libs/1_36_0/doc/html/boost_asio/example/http/client/sync_client.cpp
The implementation is working fine on some URL's example : www.amazon.com, www.cnn.com etc.
On the other hand on some URL's the request is beingg rejected from the server
eg: www.stackoverflow.com, www.flipkart.com, www.soundcloud.com etc.
The below code creates a new thread: httpRequest and calls a function task with params as host,path,portnumber
#include <iostream>
#include <thread>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
void createRequest(std::string host,std::string path,std::string port) {
try { 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(host, port);
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
tcp::resolver::iterator end;
// Try each endpoint until we successfully establish a connection.
tcp::socket socket(io_service);
boost::system::error_code error1 = boost::asio::error::host_not_found;
while (error1 && endpoint_iterator != end)
{
socket.close();
socket.connect(*endpoint_iterator++, error1);
}
if (error1)
throw boost::system::system_error(error1);
// 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 " << path << " HTTP/1.1\r\n";
request_stream << "Host: " << host << "\r\n";
request_stream << "Accept: */*\r\n";
request_stream << "Connection: close\r\n\r\n";
// Send the request.
boost::asio::write(socket, request);
//std::cout << typeid(socket).name() << std::endl;
// 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";;
}
if (status_code != 200) {
std::cout << "Response returned with status code " << status_code << "\n";
}
// 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";
}
}
int main() {
std::thread httpThred(createRequest, "www.stackoverflow.com","/","80");
std::cout << "async task launched\n";
std::cout << "main done\n";
httpThred.join();
}
output:
Response returned with status code 301
Content-Type: text/html; charset=UTF-8
Location: http://stackoverflow.com/
Date: Sun, 05 Jul 2015 19:50:44 GMT
Connection: close
Content-Length: 148
On the other hand on some URL's the request is beingg rejected from the server eg: ...
Response returned with status code 301 ... Location: https://stackoverflow.com/
This is no rejection but a redirect, i.e. you should request the resource at the given URI.
// 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.
Not true. You are making a HTTP/1.1 request so the response could be with Transfer-Encoding chunked. This kind of encoding needs special processing which you don't do. Note that the example code you refer too uses HTTP/1.0 so it is not affected by this problem.
I really recommend that you make yourself comfortable with the basics on how HTTP works before trying to implement it on your own.
Related
I wonder whether there is a possibility to access a web service using boost asio library.
I have tried following code (in IOS, C++11) which I got from boost asio documentation.
But it throws the following.
try
{
boost::asio::io_service io_service;
std::string address = "http://www.thomas-bayer.com/axis2/services/BLZService/";
// Get a list of endpoints corresponding to the server name.
tcp::resolver resolver(io_service);
tcp::resolver::query query(address,boost::asio::ip::resolver_query_base::numeric_service);
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
endpoint_iterator->host_name() = "www.thomas-bayer.com/axis2/services/BLZService/";
std::cout<<"Print Query --"<<std::endl;
// 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 << "POST: HTTP/1.0\r\n";
request_stream << "Host: " << address << "\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;
}
if (status_code != 200)
{
std::cout << "Response returned with status code " << status_code << "\n";
return;
}
// 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";
}
Exception: connect: Can't assign requested address
Or
Exception: resolve: Host not found (authoritative)
What is wrong with the code? Or I am doing completely wrong?
Thanks
The name resolution fails, because you are confusing what is a request, a URL, a protocol, hostname and an IP address.
Do the requestion on a FQDN. You need to supply a service unless you know it. The service in this case follows from the the protocol¹, `http:// is usually served on port 80:
std::string const address = "www.thomas-bayer.com";
tcp::resolver::query query(address, "80", boost::asio::ip::resolver_query_base::numeric_service);
Note that on most systems you can equivalently use:
std::string const address = "www.thomas-bayer.com";
tcp::resolver::query query(address, "http");
See where the http:// and www.thomas-bayer.com parts went?
Now /axis2/services/BLZService/ is the query path, as you would write in a GET request:
request_stream << "GET /axis2/services/BLZService/ HTTP/1.1\r\n";
Notes:
POST is not a header (so no colon!) it's a HTTP "verb" (GET, POST, DELETE, PUT...)
The "Host" header is a host name:
request_stream << "Host: " << address << "\r\n";
was correct iff address was really the logical name for the host
setting the hostname like this:
endpoint_iterator->host_name() = "www.thomas-bayer.com/axis2/services/BLZService/";
is something I've never seen before and I'm not sure what it should achieve. Perhaps it's just wrong?
¹ by convention, it could be other
Fixes
#include <boost/asio.hpp>
#include <iostream>
using boost::asio::ip::tcp;
void test() try {
boost::asio::io_service io_service;
std::string const address = "www.thomas-bayer.com";
// Get a list of endpoints corresponding to the server name.
tcp::resolver resolver(io_service);
tcp::resolver::query query(address, "80", boost::asio::ip::resolver_query_base::numeric_service);
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
std::cout << "Print Query --" << std::endl;
// 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 /axis2/services/BLZService HTTP/1.0\r\n";
request_stream << "Host: " << address << "\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, status_message;
unsigned int status_code;
std::getline(response_stream >> http_version >> status_code, status_message);
if (!response_stream || http_version.substr(0, 5) != "HTTP/") {
std::cout << "Invalid response\n";
return;
}
if (status_code != 200) {
std::cout << "Response returned with status code " << status_code << "\n";
return;
}
// 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";
}
int main() { test(); }
I'm trying to send a http GET request using the REST API of some domain.
Basically what I'm trying to do is to replace following curl request:
curl -k -H "Content-Type: application/json" -X GET
--data '{"username":"user#name.co", "password":"test"}' https:/domain.name/api/login/
with some c++ code using boost::asio.
I do not what to find all c++ code here , but some checkpoints would be great.
I found myself also working with boost in order to send some "customized" HTTP GET request - I ran the server locally on my Ubuntu machine (16.04).
In my case the request was of some proprietary API my server implemented (related to words it kept in its data base), but you can modify the queryStr variable to hold whatever query string you wish for.
Also, change the argv[1] and argv[2] when you ran the program to hold your required values (IP address, query, and port if needed - default is 80).
#include <iostream>
#include <istream>
#include <ostream>
#include <string>
#include <boost/asio.hpp>
using boost::asio::ip::tcp;
using namespace std;
int main(int argc, char* argv[])
{
cout << "main -start" << endl;
try
{
boost::asio::io_service io_service;
string ipAddress = argv[1]; //"localhost" for loop back or ip address otherwise, i.e.- www.boost.org;
string portNum = argv[2]; //"8000" for instance;
string hostAddress;
if (portNum.compare("80") != 0) // add the ":" only if the port number is not 80 (proprietary port number).
{
hostAddress = ipAddress + ":" + portNum;
}
else
{
hostAddress = ipAddress;
}
string wordToQuery = "aha";
string queryStr = argv[3]; //"/api/v1/similar?word=" + wordToQuery;
// Get a list of endpoints corresponding to the server name.
tcp::resolver resolver(io_service);
tcp::resolver::query query(ipAddress, portNum);
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 " << queryStr << " HTTP/1.1\r\n"; // note that you can change it if you wish to HTTP/1.0
request_stream << "Host: " << hostAddress << "\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;
}
The original example I followed is here: Boost-simple-http-get-request-sync-client
boost::asio is not an application level library. So you can open a connection with it, do an SSL handshake and so on. But you cannot construct HTTP requests via boost::asio since it's designed to just send/receive data.
But, you can try to experiment with this asio HTTP client example. Probably this can be a good thing to start with.
There is an Urdl library, created by Christopher M. Kohlhoff, the author of Boost.Asio:
Urdl is a cross-platform C++ library for downloading web content using
a URL. It provides an easy-to-use extension to standard C++ iostreams
and an asynchronous interface for use with Boost.Asio.
Your request sample would be like following:
#include <urdl/http.hpp>
urdl::istream is;
// Set request options: method, content type, content
is.set_option(urdl::http::request_method("GET"));
is.set_option(urdl::http::request_content_type("application/json"));
is.set_option(urdl::http::request_content("{\"username\":\"user#name.co\", \"password\":\"test\"}"));
// open HTTP stream at URL
is.open("https:/domain.name/api/login/");
I would like to read a source code of an thml page with boost::asio.
Here is my sample code :
#include "stdafx.h"
#include <boost/algorithm/string/replace.hpp>
#include <boost/asio.hpp>
#include <vector>
#include <string>
#include <algorithm>
#include <sstream>
#include <ostream>
int _tmain(int argc, _TCHAR* argv[])
{
std::string strHost = "www.fdj.fr";
std::string strPort = "80";
std::string strUrlPath = "https://www.fdj.fr/jeux/jeux-de-tirage/keno/resultats";
std::string strUserAgent = "Fiddler";
//std::vector<std::string> header;
unsigned int TimeOut = 5000;
//do_get(strHost, strPort, strUrlPath, header, TimeOut);
try
{
using boost::asio::ip::tcp;
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(strHost, "http");
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
tcp::resolver::iterator end;
// Try each endpoint until we successfully establish a connection.
tcp::socket socket(io_service);
boost::system::error_code error = boost::asio::error::host_not_found;
while (error && endpoint_iterator != end)
{
socket.close();
socket.connect(*endpoint_iterator++, error);
}
if (error)
throw boost::system::system_error(error);
// 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 " << strUrlPath << " HTTP/1.0\r\n";
request_stream << "User-Agent: " << strUserAgent << "\r\n";
request_stream << "Host: " << strHost << "\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.
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.
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);
char a;
std::cin>>a ;
}
catch (std::exception& e)
{
std::cout << "Exception: " << e.what() << "\n";
}
return 0;
}
The request sended is :
GET https://www.fdj.fr/jeux/jeux-de-tirage/keno/resultats HTTP/1.0
User-Agent: Fiddler
Host: www.fdj.fr
Accept: */*
Connection: close
If i run my programm i have :
If i run this request in fiddler ( by copy/paste) i have :
return code=200
(Accepted) and the page is loaded !
Anyone have an idea why i have this 301 error ?
I think it's due to an boost::asio parameters, but which ?
Thanks a lot,
Best regards,
Nixeus
There are two things happening here:
You are attempting to load an HTTPS URI over plain HTTP. This results in a 301 redirect that points you back to the original page over HTTPS. This indicates that the hosting server does not provide this resource over insecure HTTP.
Your HTTP implementation does not support redirects. You are making a request and delivering the first response. A full HTTP client would check for a 301 response and retry using the URI in the location header of the 301.
To fix this you will need to implement support for TLS/HTTPS and ideally HTTP redirects.
I would like to get the source html code of a website in C++.
I tried with libcurl and curlpp but I don't succeed to link and build the libs...
So, I found a sample code in the boost website for reading websites.
I tried, but I have the 301 error code (Moved Permanently).
If I go on my website ( https://www.fdj.fr/jeux/jeux-de-tirage/keno/resultats ) I have no problem, and the website appear to be OK.
Anyone have some ideas ?
Here is my code:
std::string strHost= "fdj.fr";
std::string strUrlPath = "https://www.fdj.fr/jeux/jeux-de-tirage/keno/resultats";
try
{
using boost::asio::ip::tcp;
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(strHost, "http");
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
tcp::resolver::iterator end;
// Try each endpoint until we successfully establish a connection.
tcp::socket socket(io_service);
boost::system::error_code error = boost::asio::error::host_not_found;
while (error && endpoint_iterator != end)
{
socket.close();
socket.connect(*endpoint_iterator++, error);
}
if (error)
throw boost::system::system_error(error);
// 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 " << strUrlPath << " HTTP/1.0\r\n";
request_stream << "Host: " << strHost << "\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.
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.
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";
}
I'm new to C++ and I'm just trying to implement a simple HTTP Client using Boost ASIO Sync Http Client; I copied the example from Boost's site, just modified it to return the response as string rather than writing to console.
My code is making a call and it's returning a response but it is partial - it cuts off after the 10th line... I'm puzzled can someone please help me?
Here is my code and if you have Boost set up, you should be able to just copy/paste and run it.
I'm on Windows 7, using Visual Studio 2010 with Boost 1.47.
Thanks in advance.
-serkan
#include <iostream>
#include <istream>
#include <ostream>
#include <string>
#include <boost/asio.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/assign/list_inserter.hpp>
#include <boost/date_time/gregorian/gregorian.hpp>
using boost::asio::ip::tcp;
typedef boost::gregorian::date Calendar;
std::string httpClient(std::string host, std::string path){
std::string res = "";
try{
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(host, "http");
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
tcp::resolver::iterator end;
// Try each endpoint until we successfully establish a connection.
tcp::socket socket(io_service);
boost::system::error_code error = boost::asio::error::host_not_found;
while(error && endpoint_iterator != end){
socket.close();
socket.connect(*endpoint_iterator++, error);
}
if(error){ throw boost::system::system_error(error); }
// 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 " << path << " HTTP/1.0\r\n";
request_stream << "Host: " << host << "\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.
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";
}
if(status_code != 200){
std::cout << "Response returned with status code " << status_code << "\n";
}
// Read the response headers, which are terminated by a blank line.
boost::asio::read_until(socket, response, "\r\n\r\n");
// Write whatever content we already have to output.
if(response.size() > 0){
std::ostringstream oss;
oss << &response;
res = oss.str();
}
// Read until EOF, writing data to output as we go.
while(boost::asio::read(socket, response, boost::asio::transfer_at_least(1), error)){
//std::cout << &response; // don't want to print just return
}
if(error != boost::asio::error::eof){ throw boost::system::system_error(error); }
}catch(std::exception& e){
std::cout << "Exception: " << e.what() << "\n";
}
return res;
}
int main(int argc, char* argv[]){
std::cout << httpClient("download.finance.yahoo.com", "/d/quotes.csv?s=aapl,aig,msft,jpm,WFC,BAC,C,GS,USB,AXP,MS,MET,BK,PNC,PRU,SPG,AFL,TRV,COF,STT,ACE,BBT,CME,SCHW&f=sl1d1t1");
return 0;
}
It should return:
"AAPL",384.62,"11/11/2011","4:00pm"
"AIG",23.85,"11/11/2011","4:01pm"
"MSFT",26.91,"11/11/2011","4:00pm"
"JPM",33.28,"11/11/2011","4:01pm"
"WFC",25.65,"11/11/2011","4:00pm"
"BAC",6.21,"11/11/2011","4:00pm"
"C",29.33,"11/11/2011","4:00pm"
"GS",101.66,"11/11/2011","4:00pm"
"USB",25.94,"11/11/2011","4:00pm"
"AXP",50.37,"11/11/2011","4:00pm"
"MS",16.36,"11/11/2011","4:00pm"
"MET",33.07,"11/11/2011","4:00pm"
"BK",21.51,"11/11/2011","4:00pm"
"PNC",53.87,"11/11/2011","4:01pm"
"PRU",54.05,"11/11/2011","4:01pm"
"SPG",127.97,"11/11/2011","4:02pm"
"AFL",44.87,"11/11/2011","4:01pm"
"TRV",58.43,"11/11/2011","4:04pm"
"COF",45.02,"11/11/2011","4:01pm"
"STT",41.24,"11/11/2011","4:02pm"
"ACE",71.24,"11/11/2011","4:01pm"
"BBT",23.58,"11/11/2011","4:00pm"
"CME",263.57,"11/11/2011","4:00pm"
"SCHW",12.36,"11/11/2011","4:00pm"
But it returns:
Date: Sat, 12 Nov 2011 21:34:23 GMT
P3P: policyref="http://p3p.yahoo.com/w3c/p3p.xml", CP="CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE GOV"
Cache-Control: private
Connection: close
Content-Type: application/octet-stream
"AAPL",384.62,"11/11/2011","4:00pm"
"AIG",23.85,"11/11/2011","4:01pm"
"MSFT",26.91,"11/11/2011","4:00pm"
"JPM",33.28,"11/11/2011","4:01pm"
"WFC",25.65,"11/11/
You have commented out the line
//std::cout << &response;
Now, I understand that you don't want the function to print out the result but to return it. However, the loop that contains that commented-out line reads out the rest of the response, and now you are just throwing it away. You need to capture it into your return-value variable. A simple fix is to replace the commented-out line with
std::ostringstream oss;
oss << &response;
res += oss.str();
But that's not the cleanest way to do it – you should probably just let the stuff accumulate in response and convert it into a string at the end.