Exemplo n.º 1
0
/// Handle one request.
int handle_request(fcgi::request& req)
{
  boost::system::error_code ec;
  
  //
  // Load in the request data so we can access it easily.
  //
  req.load(fcgi::parse_all);

  //
  // Construct a `response` object (makes writing/sending responses easier).
  //
  fcgi::response resp;

  //
  // Responses in CGI programs require at least a 'Content-type' header. The
  // library provides helpers for several common headers:
  //
  resp<< fcgi::content_type("text/html");

  resp<< "Hello W!"
      << req.get["kevin"];

  resp<< "Response content-length == "
      << resp.content_length(); // the content-length (returns std::size_t)

  return fcgi::commit(req, resp);
} 
Exemplo n.º 2
0
/*<
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.
>*/
int handle_request(fcgi::request& req)
{
    /*<
    A FastCGI request is not loaded or parsed by default.
    >*/
    req.load(fcgi::parse_all);
    /*<
    Now that the request has been loaded, we can access all of the request data.
    The request data is available using `std::map<>`-like public members of a
    `fcgi::request`.[footnote
    The data is stored internally in a single `fusion::vector<>`
    ]

    A FastCGI request has several types of variables available. These are listed
    in the table below, assuming that `req` is an instance of `fcgi::request`:

    [table
      [[Source] [Variable] [Description]]
      [
        [Environment] [`req.env`] [The environment of a FastCGI request contains
        most of the information you will need to handle a request. There is a basic
        set of common environment variables that you can expect to be set by most
        HTTP servers around. A list of them is available on the __TODO__ (link)
        variables page.]
      ]
      [
        [GET] [`req.get`] [The variables passed in the query string of an HTTP GET
        request. The `get_data` map is multivalued and mimics a `std::multimap<>`.]
      ]
      [
        [POST] [`req.post`] [The HTTP POST data that is sent in an HTTP request's
        body. For file uploads, only the filename is stored in this map. As with
        `get`, the `post_data` map is multivalued and mimics a `std::multimap<>`.]
      ]
      [
        [Cookies] [`req.cookies`] [Cookies are sent in the HTTP_COOKIE environment
        variable. These can store limited amounts session information on the
        client's machine, such as database session ids or tracking information. As
        with `get`, the `cookie_data` map is multivalued and mimics a
        `std::multimap<>`.]
      ]
      [
        [File Uploads] [`req.uploads`] [File uploads, sent in an HTTP POST where
        the body is MIME-encoded as multipart/form-data. Uploaded files are read
        onto the server's file system. The value of an upload variable is the path
        of the file. The `upload_data` map is also multivalued.]
      ]
      [
        [Form] [`req.form`] [The form variables are either the GET variables or
        the POST variables, depending on the request method of the request.]
      ]
    ]
    >*/

    fcgi::response resp;/*<
The `response` class provides a streaming interface for writing replies. You
can write to the request object directly, but for now we're going to use the
`response`, which works well for most situations.

As you can see, the `response` is decoupled from the rest of the library. The
advantages of using it over any other custom container are separate handling
of the response body and headers, and a [funcref
boost::cgi::common::response::send send()] function which wraps the whole
response and writes it out to the client who instigated the request.

Writing to a `response` is buffered. If an error occurs, you can `clear()` the
response and send an error message instead. Buffered writing may not always
suit your use-case (eg. returning large files), but when memory is not at a
real premium, buffering the response is highly preferable.

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 `cgi::response` is not tied to a
request, so the same response can be reused across multiple requests.[footnote
Not with plain CGI though, of course.]

When sending a response that is large relative to the amount of memory
available to the system, you may need to write unbuffered.
>*/

    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");
    /*<
    Finally, send the response back and close the request.
    >*/
    return fcgi::commit(req, resp);
}
Exemplo n.º 3
0
/**
 * Handle one request.
 */
int handle_request(fcgi::request &req) {
    boost::system::error_code ec;

    //
    // Load in the request data so we can access it easily.
    //
    req.load(fcgi::parse_all);

    //
    // Construct a `response` object (makes writing/sending responses easier).
    //
    fcgi::response resp;

    //
    // Responses in CGI programs require at least a 'Content-type' header. The
    // library provides helpers for several common headers:
    //
    resp << fcgi::content_type("text/html");

    // You can also stream text to a response.
    // All of this just prints out the form
    resp << "<html>"
            "<head>"
            "<title>FastCGI Echo Example</title>"
            "<style type=\"text/css\">"
        << gCSS_text
        << "</style>"
            "<head>"
            "<body>"
            "Request ID = " << req.id() << "<br />"
            "Process ID = " << getpid() << "<br />"
            "<form method=post enctype=\"multipart/form-data\">"
            "<input type=text name=name value='"
        << req.post.pick("name", "") << "' />"
            "<br />"
            "<input type=text name=hello value='"
        << req.post.pick("hello", "") << "' />"
            "<br />"
            "<input type=file name=user_file />"
            "<input type=hidden name=cmd value=multipart_test />"
            "<br />"
            "<input type=submit value=submit />"
            "</form><p />";

    // Show the request data in a formatted table.
    format_map(resp, req, req.env, "Environment Variables");
    format_map(resp, req, req.get, "GET Variables");
    format_map(resp, req, req.post, "POST Variables");
    format_map(resp, req, req.uploads, "File Uploads");
    format_map(resp, req, req.cookies, "Cookie Variables");

    // Print the buffer containing the POST data and the FastCGI params.
    resp << "<pre>";
    resp << std::string(req.post_buffer().begin(), req.post_buffer().end());
    resp << "</pre>";

    //
    // Response headers can be added at any time before send/flushing it:
    //
    resp << "Response content-length == "
    << resp.content_length(); // the content-length (returns std::size_t)

    // This function finishes up. The optional third argument
    // is the program status (default: 0).
    return fcgi::commit(req, resp);
}