Home | Libraries | People | FAQ | More |
TODO: FastCGI Quickstart
FastCGI is a protocol that was designed with efficiency in mind. One of the key features of FastCGI is that it allows a CGI-like program to serve multiple requests and outlive the lifetime of any one request. The application communicates with the server using TCP sockets [4] and the data is binary-encoded, which can be parsed quickly.
For a full introduction on FastCGI, see the FastCGI White Paper.
This library supports FastCGI on both linux and Windows. Windows support is currently limited to external FastCGI handlers only.
The following example is generated from the linked source file.
#include <iostream> // for std::cerr #include <string> #include <boost/config/warning_disable.hpp> #include <boost/spirit/include/qi.hpp> #include <boost/spirit/include/phoenix_operator.hpp> #include <boost/cgi/fcgi.hpp> namespace fcgi = boost::fcgi; namespace client { namespace qi = boost::spirit::qi; namespace ascii = boost::spirit::ascii; /////////////////////////////////////////////////////////////////////////// // Our calculator grammar /////////////////////////////////////////////////////////////////////////// template <typename Iterator> struct calculator : qi::grammar<Iterator, float(), ascii::space_type> { calculator() : calculator::base_type(expression) { using qi::_val; using qi::_1; using qi::float_; expression = term [_val = _1] >> *( ('+' >> term [_val += _1]) | ('-' >> term [_val -= _1]) ) ; term = factor [_val = _1] >> *( ('*' >> factor [_val *= _1]) | ('/' >> factor [_val /= _1]) ) ; factor = float_ [_val = _1] | '(' >> expression [_val = _1] >> ')' | ('-' >> factor [_val = -_1]) | ('+' >> factor [_val = _1]) ; } qi::rule<Iterator, float(), ascii::space_type> expression, term, factor; }; } // namespace client int handle_request(fcgi::request& req) { req.load(fcgi::parse_all); fcgi::response resp; if (req.form.count("expression")) { resp<< "<fieldset><legend>Result</legend><pre>"; using boost::spirit::ascii::space; typedef std::string::const_iterator iterator_type; typedef client::calculator<iterator_type> calculator; calculator calc; // Our grammar std::string str ( req.form["expression"] ); float result; if (!str.empty()) { std::string::const_iterator iter = str.begin(); std::string::const_iterator end = str.end(); bool r = phrase_parse(iter, end, calc, space, result); if (r && iter == end) { resp << "-------------------------\n"; resp << "Parsing succeeded\n"; resp << "result = " << result << '\n'; resp << "-------------------------\n"; } else { std::string rest(iter, end); resp << "-------------------------\n"; resp << "Parsing failed\n"; resp << "stopped at: \": " << rest << "\"\n"; resp << "-------------------------\n"; } } else { resp<< "No expression found."; } resp<< "</pre></fieldset>"; } resp<< "<form method='post' id=''>" << " Expression: <input type='text' name='expression' value='" << req.form["expression"] << "'><br />" << " <input type='submit' value='Calculate!'>" << "</form>" << fcgi::content_type("text/html"); return fcgi::commit(req, resp); } int main(int, char**) { fcgi::service service; fcgi::acceptor acceptor(service); int status; do { status = acceptor.accept(&handle_request); if (status) std::cerr << "Request handled with error. Exit code: " << status << std::endl; } while (!status); return status; }
A catch-all header is available which includes all of the headers you should need for FastCGI.
For the sake of clarity we alias the
|
||||||||||||||||||||||
The following code is taken straight from the calc3 example in Boost.Spirit.
The only difference is to use
|
||||||||||||||||||||||
The first thing to do is write a handler function which takes a request and a response and does all request-specific work. Later, we will look at writing the code that calls this function.
|
||||||||||||||||||||||
A FastCGI request is not loaded or parsed by default.
|
||||||||||||||||||||||
Now that the request has been loaded, we can access all of the request
data. The request data is available using
A FastCGI request has several types of variables available. These are listed
in the table below, assuming that
|
||||||||||||||||||||||
The
As you can see, the
Writing to a
Not only does buffering help with network latency issues, but being able
to cancel the response and send another at any time is almost essential
when an error can crop up at any time. A When sending a response that is large relative to the amount of memory available to the system, you may need to write unbuffered.
|
||||||||||||||||||||||
Finally, send the response back and close the request.
|
||||||||||||||||||||||
We now have a request handler in all of it's contrived glory.
The program's
|
||||||||||||||||||||||
A Service handles asynchronous operations and some of the protocol-specific bits.
|
||||||||||||||||||||||
An
|
||||||||||||||||||||||
Keep accepting requests until the handler returns an error.
|
||||||||||||||||||||||
The function boost::function<int (boost::fcgi::request&)>
ie. A function that takes a reference to a
|
[4] This library currently only supports TCP sockets. The FastCGI protocol allows for "any reliable transport" and adding support for named pipes on Windows and UNIX sockets on linux is on the TODO list.
[5]
The data is stored internally in a single fusion::vector<>
[6] Not with plain CGI though, of course.