7
\$\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?

Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked May 21, 2014 at 0:34
\$\endgroup\$
1
  • 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\$ Commented May 21, 2014 at 0:55

1 Answer 1

5
\$\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).

answered May 21, 2014 at 10:51
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.