6
\$\begingroup\$

I am working on a socket HTTP post request. Here is one method that I come up with. It looks dirty and is in C instead of C++.

bool SendBasicInfo(USER* user, SOCKET sock)
{
    char FormBuffer[1024];

    char DataType1[] = "a=";
    char DataType2[] = "&b=";
    char DataType3[] = "&c=";

    char FormAction[] = "/g/g.php";

    // get: length of the actual content
    int ContentLength = (int)strlen(user->user_id) + (int)strlen(user->pcname) + (int)strlen(user->username) + strlen(DataType1) + strlen(DataType2) + strlen(DataType3);
    char ContentLengthBuffer[sizeof(ContentLength)];
    sprintf_s(ContentLengthBuffer, "%d", ContentLength);

    // header
    strcpy_s(FormBuffer, "POST ");
    strcat_s(FormBuffer, FormAction);
    strcat_s(FormBuffer, " HTTP/1.1\n");
    strcat_s(FormBuffer, "Content-Type: application/x-www-form-urlencoded\n");
    strcat_s(FormBuffer, "Host: \n");
    strcat_s(FormBuffer, "Content-Length: ");
    strcat_s(FormBuffer, ContentLengthBuffer); // size of actual content
    strcat_s(FormBuffer, "\n\n");

    // actual content
    strcat_s(FormBuffer, DataType1);
    strcat_s(FormBuffer, user->user_id);
    strcat_s(FormBuffer, DataType2);
    strcat_s(FormBuffer, user->pcname);
    strcat_s(FormBuffer, DataType3);
    strcat_s(FormBuffer, user->username);

    std::cout << FormBuffer << std::endl;

    return ( send(sock, FormBuffer, strlen(FormBuffer), NULL) >= (int)strlen(FormBuffer) );
}

The idea here is to send a message like this one:

POST /g/g.php HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Host: 
Content-Length: 31

a=123&b=computername&c=username

This was working fine, but it just seems hard-coded and wrong. How can I make the size of FormBuffer to be dynamic instead of 1024?

\$\endgroup\$
  • 2
    \$\begingroup\$ Is there any reason you're using C strings instead of using std::string and then simply using c_str? Are there some forms of restrictions or something? \$\endgroup\$ – Corbin May 21 '14 at 0:55
4
\$\begingroup\$

This was working fine, but it just seems hard-coded and wrong.

It's a monolythic monster. It works, but if you have the time, you could benefit from re-writing it (using c++ alternatives).

How can I make the size of FormBuffer to be dynamic instead of 1024?

Like so (C++):

bool SendBasicInfo(USER* user, SOCKET sock)
{
    std::ostringstream FormBuffer; // <<< here

    char DataType1[] = "a=";
    char DataType2[] = "&b=";
    char DataType3[] = "&c=";

    char FormAction[] = "/g/g.php";

    // get: length of the actual content
    auto ContentLength = strlen(user->user_id) + 
        strlen(user->pcname) + 
        strlen(user->username) +
        strlen(DataType1) +
        strlen(DataType2) +
        strlen(DataType3);

    // header
    FormBuffer << "POST " << FormAction << " HTTP/1.1\n";
    FormBuffer << "Content-Type: application/x-www-form-urlencoded\n";
    FormBuffer << "Host: \n";
    FormBuffer << "Content-Length: " << std::to_string(ContentLength) << "\n\n";

    // actual content
    FormBuffer << DataType1 << user->user_id;
    FormBuffer << DataType2 << user->pcname;
    FormBuffer << DataType3 << user->username;

    const auto str = FormBuffer.str();

    std::cout << str << std::endl;

    return ( send(sock, str.data(), str.size(), NULL) >= str.size() );
}

Otherwise (if you want to write C code), you will have to iterate over the entire data once and compute it's resulting size, then allocate memory for the result, then iterate again over the data to create the buffer contents, then sent to socket and remember the result in a variable, then free the allocated memory, then deturn the stored result. If it sounds ugly, that's because it is :D.

Edit: The HTTP standard states that you should send \r\n at the end of header lines, not \n. It may not matter much in effect though, because both servers and clients are mandated to receive and parse both variants - as developers tend not to respect this rule (I may be remembering it wrong though).

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.