8

I've been trying to get this to work for a couple of days however I keep getting a 400 error from the server.

Basically, what I'm trying to do is send a http POST request to a server that requires a JSON request body with a couple of properties.

These are the libs I'm currently using

UPDATED --- 7/23/13 10:00am just noticed I'm using TCP instead of HTTP not sure how much this will effect an HTTP call but i can't find any examples of clients using pure HTTP with BOOST::ASIO

#include <iostream>
#include <istream>
#include <ostream>
#include <string>
#include <boost/asio.hpp>

#include <sstream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>

using boost::property_tree::ptree; using boost::property_tree::read_json; using boost::property_tree::write_json;

using boost::asio::ip::tcp;

SET UP CODE

    // Get a list of endpoints corresponding to the server name.
tcp::resolver resolver(io_service);
tcp::resolver::query query(part1, "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);

JSON BODY

ptree root, info;
root.put ("some value", "8");
root.put ( "message", "value value: value!");
info.put("placeholder", "value");
info.put("value", "daf!");
info.put("module", "value");
root.put_child("exception", info);

std::ostringstream buf; 
write_json (buf, root, false);
std::string json = buf.str();

HEADER AND CONNECTION REQUEST

request_stream << "POST /title/ HTTP/1.1 \r\n";
request_stream << "Host:" << some_host << "\r\n";
request_stream << "User-Agent: C/1.0";
request_stream << "Content-Type: application/json; charset=utf-8 \r\n";
request_stream << json << "\r\n";
request_stream << "Accept: */*\r\n";    
request_stream << "Connection: close\r\n\r\n";

// Send the request.
boost::asio::write(socket, request);

I put place holder values however if you see anything that doesn't work in my code that jumps out please let me know I have no idea why i keep getting a 400, bad request.

info about the rig

C++

WIN7

VISUAL STUDIO

progrenhard
  • 2,333
  • 2
  • 14
  • 14
  • Before sending the whole request, print in to some log or console and see if it's correct. – Igor R. Jul 23 '13 at 08:57
  • Are you writing `json` between header fields? – Galimov Albert Jul 23 '13 at 14:05
  • this is where the json file is being inputed `request_stream << json << "\r\n";` I've been looking at the request_stream buffer through a debugger along with the request buffer. Everything seems correct in terms of content however there are some weird spaces you think that could have a impact? – progrenhard Jul 23 '13 at 16:31
  • 1
    "TCP instead of HTTP"? HTTP is an application level protocol over TCP. http://en.wikipedia.org/wiki/HTTP – Igor R. Jul 23 '13 at 17:05
  • ill add another layer to the question is boost::asio the proper library im using to deliver HTTP requests with a header and body? – progrenhard Jul 23 '13 at 20:21
  • 2
    Yes, it is. However, if you don't want to implement HTTP protocol by yourself, you can utilize cpp-netlib (http://cpp-netlib.org/), which already implements HTTP on the top of Asio. – Igor R. Jul 24 '13 at 08:17
  • I've already looked into that library a little and i couldn't find any support for body's it's seems as if they only do headers. It's sort of weird that C++ doesn't have a easy portable solution for this yet. There must be something for now, i'm checking out libcurl. Unless someone can point me to a solution with BOOST. – progrenhard Jul 24 '13 at 16:15
  • @progenhard : Did you get any solution ? It would be helpful if you could post an answer – Girish Nair Oct 16 '13 at 12:21
  • @GirishNair I will post a solution sometimes thursday. I used a combination of libraries curl and jansson – progrenhard Oct 21 '13 at 17:35

1 Answers1

17

Although this question is very old I would like to post this answer for users who are facing similar problem for http POST.

The server is sending you HTTP 400 means "BAD REQUEST". It is because the way you are forming your request is bit wrong.

The following is the correct way to send the POST request containing JSON data.

#include<string>  //for length()

request_stream << "POST /title/ HTTP/1.1 \r\n";
request_stream << "Host:" << some_host << "\r\n";
request_stream << "User-Agent: C/1.0\r\n";
request_stream << "Content-Type: application/json; charset=utf-8 \r\n";
request_stream << "Accept: */*\r\n";
request_stream << "Content-Length: " << json.length() << "\r\n";    
request_stream << "Connection: close\r\n\r\n";  //NOTE THE Double line feed
request_stream << json;

Whenever you are sending any data(json,string etc) with your POST request, make sure:

(1) Content-Length: is accurate.

(2) that you put the Data at the end of your request with a line gap.

(3) and for that (2nd point) to happen you MUST provide double line feed (i.e. \r\n\r\n) in the last header of your header request. This tells the header that HTTP request content is over and now it(server) will get the data.

If you don't do this then the server fails to understand that where the header is ending ? and where the data is beginning ? So, it keeps waiting for the promised data (it hangs).

Disclaimer: Feel free to edit for inaccuracies, if any.

Oen44
  • 3,156
  • 1
  • 22
  • 31
K.K
  • 401
  • 5
  • 22