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?
1 Answer 1
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).
std::string
and then simply usingc_str
? Are there some forms of restrictions or something? \$\endgroup\$