Sunday 9 January 2011

[C++] Performing a HTTP POST request on a distant server with Pion Network Library

The Pion Network Library is a great library to add a web server to your application. Sadly it is not very documented and it is sometimes hard to find how to do some really simple things.

Here is an example on how perform a HTTP POST on a distant server.

Performing a HTTP POST request is not a complicated task, even without using any library. However, if you already use the Pion Network Library as a web server in your application, it would be ridiculous not to use this library to perform the POST.

class PostDataExample
{
public:
    PostDataExample(const std::string& _hostName, unsigned int _port, const std::string& _resource)
    void post(int _id);
    
private:
    std::string m_hostName;
    unsigned int m_port;
    std::string m_resource;
    PionOneToOneScheduler m_scheduler;
}

The PostDataExample class only contains a method that will post an id on a server page. I will not detail the constructor implementation, it will, as everybody expects, copy the parameters in the members. It might not be a good idea to set the host name, port and resource as private members of our class but it will be enough for the example.
Notice also the presence of the scheduler that is necessary to create the TCP connection with the server.

Now, let's see the post method implementation :
void PostDataExample::post(int _id)
{
    // Connect to remote server.
    boost::system::error_code error_code;
    pion::net::TCPConnection tcpConnection(m_scheduler.getIOService());
    error_code = tcpConnection.connect(m_hostName, m_destPort);
    if (error_code)
    {
        std::cerr << "Error during connection to distant server: "
          << error_code.message();
        return;
    }

    // Create the request.
    std::stringstream requestStream;
    requestStream << "id="<< _id;

    // Send HTTP request.
    pion::net::HTTPRequest httpRequest(m_destResource);
    httpRequest.setMethod("POST");
    httpRequest.addHeader("Host", m_hostName);
    httpRequest.addHeader("Content-Type", "application/x-www-form-urlencoded");
    httpRequest.setContent(requestStream.str());
    httpRequest.send(tcpConnection, error_code);

    if (error_code)
    {
 std::cerr << "Error while trying to post enOcean data to distant server: "
            << error_code.message();
        return;
    }

    // receive HTTP response
    pion::net::HTTPResponse httpResponse(httpRequest);
    httpResponse.receive(tcpConnection, error_code);
    if (error_code)
    {
        std::cerr << "Error while trying to read response from distant server: %s"
            << error_code.message();
    }
    else
    {
        std::cerr << "Receive response from distant server: "
          << httpResponse.getStatusMessage();
    }
}

The code is pretty straight forward so I wont explain every detail. I just want to highlight two points. First of all, don't forget to add the host name to the request or the server will not understand the request. Secondly, if you get a server response it does not mean your request is correct, just that the server received it and respond to you. For example, if you remove the host name you will get an error message.

No comments:

Post a Comment