I need to create a c++ cgi app the accepts post data. I will be accepting a json object. How to I get the payload?
I can get the get data using the below
int main() {
bool DEBUG = true;
cout << "content-type: text/html" << endl << endl;
//WHAT GOES HERE FOR POST
json=?????
//THIS IS A GET
query_string = getenv("QUERY_STRING");
}
If the method type is POST (you may also want to check this) then the POST-data is written to stdin. You can therefore use standard methods like this:
// Do not skip whitespace, more configuration may also be needed.
cin >> noskipws;
// Copy all data from cin, using iterators.
istream_iterator<char> begin(cin);
istream_iterator<char> end;
string json(begin, end);
// Use the JSON data somehow.
cout << "JSON was " << json << endl;
This will read all data from cin into json until an EOF occurs.
Assuming apache:
The documentation is found here:
You will find it near the bottom but the post data is provided over stdin.
#include <iostream>
#include <string>
#include <sstream>
int main()
{
bool DEBUG = true;
std::cout << "content-type: text/html\n\n"; // prefer \n\n to std::endl
// you probably don't want to flush immediately.
std::stringstream post;
post << std::cin.rdbuf();
std::cout << "Got: " << post.str() << "\n";
}
Related
I'm implementing a simple program using text files. Users can register/login accounts that are saved to a txt file.
One of the options is to post a message to a "Post board" that will store the user's name followed by all their posts.
For example:
Leo: Hello
Tony: Bye
I'm able to successfully read the text file and output the message to the console but the username is not displaying, only the message.
For refrence I have a postMessage() function that uses getline() to concatante the username using
ofstream << getUsername() + ": " + string::message.
I have quite a bit of code so I cannot share all of it, however, here are the pieces in question.
public:
char postMessage(User& currentUser, bool loggedIn) { //Will post a message to the board. Passes a User object.
if (loggedIn == false) {
std::cout << "You must be logged in to post!" << std::endl;
userLoginRegisterPrompt();
return 0;
}
char messageState; //Code to verify if message was posted.
std::string message; //Actual message string
std::cout << "Enter your text: " << std::endl;
std::cin.ignore(); //Clears string buffer.
getline(std::cin,message);
std::ofstream post("C:/Users/19097/Desktop/Programs/Registration/Registration/UserPosts/-Posts.txt", std::ios::app); //File with user posts.
post << currentUser.getUserName() << ": " << message << std::endl;
logAction(currentUser.getUserID(), "Made a post");
}
Here is the loadPosts() method to read from the text file and display it to console.
static bool loadPosts() { //Will be for viewing the post history.
std::ifstream post("C:/Users/19097/Desktop/Programs/Registration/Registration/UserPosts/-Posts.txt");
std::string line;
if (!post) {
std::cout << "No board exists!" << std::endl;
return false;
}
while (post >> line) {
getline(post, line);
std::cout << line << std::endl;
}
}
This is what some of the posts read like in the actual txt file.
This is what shows on the console when using loadPosts()
Is there a way to implicitly flush data to an output stream?
#include <iostream>
#include <fstream>
using namespace std;
#define log logstream
int main()
{
ofstream logstream("test.log");
log << "Test1" << 123 << endl; // explicitly flushed
log << "Test2" << 123; // ?
// Test2 not written, yet...
cout << "Check log file..." << endl;
int tmp;
cin >> tmp;
}
I would like to be able to log without specifying the << endl manipulator every time.
You may use std::unitbuf.
log << std::unitbuf;
And then flush would be done at each insertion.
I hope I explain this right.. but I need my C++ program to display an HTML website. The code that I have right now only displays the text. How do I make it so it is actually displayed like a website (using HTML code)? I am going to use the .exe file uploaded to a server to display the page.
#include <iostream>
using namespace std;
int main()
{
cout << "Content-type: text/plain\n\n";
cout << "<h2>My first CGI program</h2>\n";
cout << "<h1>This is a test</h1>\n";
cout << "<h3>Why is this not working</h3>\n";
return 0;
}
Your HTTP response needs the status line, and you should change the mime type to text/html:
cout << "HTTP/1.1 200 OK\n";
cout << "Content-Type: text/html\n\n";
cout << "<h2>My first CGI program</h2>\n";
cout << "<h1>This is a test</h1>\n";
cout << "<h3>Why is this not working</h3>\n";
Problematic code:
#include <array>
#include <iostream>
#include <cstring>
int main(int argc, char *argv[])
{
using namespace std;
cout << "Read from file:" << endl;
while (!cin.eof())
{
array<char, 16> l_array;
cin.read(l_array.data(), l_array.size());
cout.write(l_array.data(), cin.gcount());
}
cout << endl;
cout << "Read from keyboard:" << endl;
cin.rdbuf(cout.rdbuf());
while (!cin.eof())
{
array<char, 64> l_array;
memset(l_array.data(), 0, l_array.size());
cin.read(l_array.data(), l_array.size());
cout << "===== DATA =====" << endl;
cout << l_array.data() << endl;
cout << "================" << endl;
}
}
This is how i run my program:
./application < file.txt
I can read data from pipe without problems but when i want to read it again it is still asociated with pipe. I have no idea how to switch it back. I have found 'rdbuf' function which can change it, but I have no idea how to use it.
I only found examples when you stard with keyboard switch to file and back to keyboard.
Like here: http://www.cplusplus.com/reference/iostream/ios/rdbuf/
But i don't have streambuf remembered so I can't do it like they did. I want to write program which can read most of data from file, and ask only when something is missing or just to ask user in runtime about permision or something. All inside console under linux.
#EDIT
Thank you for help, I post solution
class RedirectCinToConsole
{
protected:
std::ifstream m_console;
std::streambuf *m_oldCin;
bool m_success;
public:
RedirectCinToConsole() :
m_oldCin(0),
m_success(false)
{
m_console.open("/dev/tty");
if (m_console.is_open())
{
m_success = true;
m_oldCin = std::cin.rdbuf(m_console.rdbuf());
}
}
virtual ~RedirectCinToConsole()
{
if (m_oldCin)
{
std::cin.rdbuf(m_oldCin);
}
m_console.close();
}
operator bool () const { return m_success; }
};
int main()
{
RedirectCinToConsole l_redirect;
if (l_redirect)
{
std::string l_helloWorld;
std::cin >> l_helloWorld;
std::cin.ignore();
std::cout << l_helloWorld;
}
return 0;
}
It occurs to me that, regardless of the proposed solutions, the easiest
solution (and probably the best) would be to do things the opposite:
don't redirect the input, but pass the filename to the program, and let
it open an std::ifstream to read it, keeping std::cin free for
interactive input.
Ben Voigt has suggested the standard Unix solution, but on thinking
about it, it seems the above is more natural; it is certainly easier and
more portable.
Perhaps you should use fstream to create your own stream and either ask for a file name or take the file name as a command-line parameter. This will leave cin available for other input operations.
Try opening /dev/tty. This will be your process's associated console, if there is any. If your process was started from a daemon, it could fail.
I have a code like this
int main()
{
std::stringstream oss;
std::cerr.rdbuf( oss.rdbuf() );
std::cerr << "this goes to cerr";
std::cout << "[" << oss.str() << "]";
}
But i get the output of the program as
[this goes to cerr]Segmentation fault
How does the program segfault?
This is because you do not restore the buffer of cerr before your program exits. Do it like this:
#include <iostream>
#include <sstream>
int main()
{
std::stringstream oss;
std::streambuf* old = std::cerr.rdbuf( oss.rdbuf() );
std::cerr << "this goes to cerr";
std::cout << "[" << oss.str() << "]";
std::cerr.rdbuf(old);
}
See this answer of mine for a solution that is exception safe.
The other answer correctly address the how does this program segfault part of your question. However, I feel that the real question Redirecting stderr to stdout using string stream.. deserves a better answer:
You may simplify the whole shebang and make it scale and perform a infitely better better by just aliasing cerr to cout:
#include <iostream>
int main()
{
std::cerr.rdbuf(std::cout.rdbuf());
std::cerr << "this goes to cerr";
}
If you really want to be explicit:
std::cerr.copyfmt(std::cout);
std::cerr.clear(std::cout.rdstate());
std::cerr.rdbuf(std::cout.rdbuf());
You can verify that the text is actually received on stdout when run