Read HTTP POST data with QTcpSocket



  • Hi,

    I need to read HTTP POST data coming from a client request, but I don't really know how to.

    Could someone help please!



  • Read the data (read connected to the readyRead signal) and parse it. You might want to use a library like http-parser https://github.com/ry/http-parser.



  • Well I am not really looking to use http parser at this moment. All i want is to be able to read the message body.

    Suppose I submit the following form:

    @<form method="POST" action="http://localhost:8090">
    <input type="text" name="username"/>
    <input type="submit" value="Go">
    </form>@

    now at the server instance I need to fetch the name-value pair contained in the encoded message.

    for this do I need a http parser?



  • Yes. You need to code an HTTP server.



  • I have the following code block that is executed on every incoming request

    @QTcpSocket socket = (QTcpSocket)sender();
    if(socket->canReadLine()){
    QStringList tokens = QString(socket->readLine()).split(QRegExp("[ \r\n][ \r\n]*"));
    if(tokens[0]=="GET"){
    QTextStream os(socket);
    os.setAutoDetectUnicode(true);
    os << "HTTP/1.0 200 Ok\r\n"
    "Content-Type: text/html; charset="utf-8"\r\n"
    "\r\n"
    "<h3>Base10 application server</h3><br/>Page Responded on: "
    << QDateTime::currentDateTime().toString() << "\n";
    socket->close();
    if(socket->state()==QTcpSocket::UnconnectedState)
    delete socket;
    }
    }@

    as you can see on line 3 I am able to if its a GET or POST request, if GET i can fetch params from the URL itself, however I can't figure out how to read POST data in this context.



  • Well I found a solution (a workaround rather). I can do @socket->readAll()@ and convert the read data block to associative arrays.

    Is there a better way of achieving this? m sure there is...



  • readAll reads the all the data that has arrived so far. It does NOT wait for everything to arrive at the socket. If the first packet only contains "GE", the signal is emitted and readAll just returns "GE", not the complete "GET /abc/def HTTP/1.1" line, the same holds for the workload of a POST request.

    You will have to consider this and collect the data, until you know the headers are in completely. It's more than a few readLines or readAlls.

    For the POST data, you will have to parse the the encoded strings. There are at least two variants:

    • url encoded data like in a GET request
    • multipart/form data

    I suggest reading the respective RFCs for the details.



  • Thank you Volker for stopping by, I actually got the idea of converting the message into associative array after reading the RFCs. But I missed the obvious point that the message may not have arrived in its entirety at first read. So I guess I'll have to set up a watch dog and read the message once it has arrived fully.



  • Doing HTTP parsing by hand is probably calling for troubles. Much better to use a library for that (f.i. the aforementioned http-parser, which allows you to add data in chunks and will call your callbacks when something interesting happens, like a full header was decoded).



  • [quote author="nilotpal" date="1313514417"]Thank you Volker for stopping by, I actually got the idea of converting the message into associative array after reading the RFCs. But I missed the obvious point that the message may not have arrived in its entirety at first read. So I guess I'll have to set up a watch dog and read the message once it has arrived fully. [/quote]

    You don't know that from the socket. The TCP connection may not necessarily closed once the request has been sent completely (keep alive connections).

    The watchdog is not needed, IMHO. As soon as there is new data availabel, you'll be notified by the signals.


Log in to reply