0

I have the read the Boost documentation and manage to run a get request: https://www.boost.org/doc/libs/1_77_0/libs/beast/doc/html/beast/quick_start/http_client.html

However I unable to figure out how to make a post request. I have tried the following stackoverflow posts but none of them work for me:

Boost ASIO HTTP client POST

HTTP POST request using boost::asio

Boost asio custom HTTP server reading HTTP post requests

BOOST ASIO POST HTTP REQUEST -- headers and body

Would someone be able to provide a full example with post similar to the first link?

Thank you

Here is what I tried:

#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
#include <boost/beast/version.hpp>
#include <boost/asio/connect.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <cstdlib>
#include <iostream>
#include <string>

namespace beast = boost::beast;     // from <boost/beast.hpp>
namespace http = beast::http;       // from <boost/beast/http.hpp>
namespace net = boost::asio;        // from <boost/asio.hpp>
using tcp = net::ip::tcp;           // from <boost/asio/ip/tcp.hpp>

// Performs an HTTP GET and prints the response
int main(int argc, char** argv)
{
  try
  {
    // Check command line arguments.
    if(argc != 4 && argc != 5)
    {
      std::cerr <<
        "Usage: http-client-sync <host> <port> <target> [<HTTP version: 1.0 or 1.1(default)>]\n" <<
          "Example:\n" <<
            "    http-client-sync www.example.com 80 /\n" <<
              "    http-client-sync www.example.com 80 / 1.0\n";
      return EXIT_FAILURE;
    }
    auto const host = argv[1];
    auto const port = argv[2];
    auto const target = argv[3];
    int version = argc == 5 && !std::strcmp("1.0", argv[4]) ? 10 : 11;
    
    // The io_context is required for all I/O
    net::io_context ioc;
    
    // These objects perform our I/O
    tcp::resolver resolver(ioc);
    beast::tcp_stream stream(ioc);
    
    // Look up the domain name
    auto const results = resolver.resolve(host, port);
    
    // Make the connection on the IP address we get from a lookup
    stream.connect(results);
    
    // Set up an HTTP GET request message
    http::request<http::string_body> req{http::verb::post, target, version};
    req.set(http::field::host, host);
    req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
    
    std::string body = "a=4&b=3";
    req.body() = body;
    req.set(http::field::content_type, "application/x-www-form-urlencoded;charset=UTF-8");
    
    // Send the HTTP request to the remote host
    http::write(stream, req);
    
    // This buffer is used for reading and must be persisted
    beast::flat_buffer buffer;
    
    // Declare a container to hold the response
    http::response<http::dynamic_body> res;
    
    // Receive the HTTP response
    http::read(stream, buffer, res);
    
    // Write the message to standard out
    std::cout << res << std::endl;
    
    // Gracefully close the socket
    beast::error_code ec;
    stream.socket().shutdown(tcp::socket::shutdown_both, ec);
    
    // not_connected happens sometimes
    // so don't bother reporting it.
    //
    if(ec && ec != beast::errc::not_connected)
      throw beast::system_error{ec};
    
    // If we get here then the connection is closed gracefully
  }
  catch(std::exception const& e)
  {
    std::cerr << "Error: " << e.what() << std::endl;
    return EXIT_FAILURE;
  }
  return EXIT_SUCCESS;
}

In command line I run:

$ ./http-client-sync.o localhost 8000 /sum 1.0
Error: end of stream

It should return [7]

$ curl --data "a=4&b=3" "http://localhost:8000/sum"
[7]

I created a web api as described here: https://www.rplumber.io/

momo123
  • 93
  • 7
  • Can you please show us what did you try and it did not work? There are lots of way to do one thing but you may not get it fully so please share what did not work for you. – foragerDev Feb 20 '22 at 18:04
  • change `http::verb::get` to `http::verb::post` and set the body on `req`? – Alan Birtles Feb 20 '22 at 18:04
  • make sure `auto const results = resolver.resolve(host, port);` does not return empty range. – foragerDev Feb 20 '22 at 18:30
  • @foragerDev, thank you for feedback, it does not return an empty range. – momo123 Feb 20 '22 at 18:37
  • you need to do [`req.prepare_payload()`](https://www.boost.org/doc/libs/develop/libs/beast/doc/html/beast/ref/boost__beast__http__message/prepare_payload.html) before sending your request, I'm guessing your server is crashing when the input is not set which is why you get no result – Alan Birtles Feb 20 '22 at 19:39

0 Answers0