FastCGI - Getting Request URI and Content in C++ FCGI

注:该博文转自 Getting Request URI and Content in C++ FCGI,由于网上FastCGI相关的资料较少,故转载存档。原文章创作于2012年,原文中部分链接资料已经失效,现已更正,方便之后查阅。如有侵权,请联系删除。
Previously I had mentioned how to create a simple hello world application in c++ with fcgi. However this simple application doesn’t allow for any inputs. This post we’ll show how retrieve the request uri accessed as well as the POST body content.

Getting the URI and POST content

Looking at the previous app, the output was a very simple hello, world. We will add functionality which spits back out the path that we hit the server with. Our desired functionality looks like:

> curl -d "Chris" http://localhost/foobar
<html>
  <head>
    <title>Hello, world!</title>
  </head>
  <body>
    <h1>Hello Chris from /foobar !</h1>
  </body>
</html>

Notice that we respond with Hello <post content> from <request uri>. In order to do this we will have to capture the request uri and the post content. Let’s start off with the easier one which is the request uri. The request uri is buried within the FCGX_Request’s environment parameters. We can extract it using the FCGX_GetParam function like so:

const char * uri = FCGX_GetParam("REQUEST_URI", request.envp);

Note how we get the param ‘REQUEST_URI’ as named in our nginx configuration.

The slightly trickier part is getting the request content. We will write a helper function to do this for us. We start by determining the CONTENT_LENGTH of the response. If missing we assume it to be 0 since it is not safe to read from the fcgi request if it is missing. We limit the content length to ensure we don’t run out of memory and set it to an arbitrary high value (STDIN_MAX). If we can’t parse the content length we will just assume the max number of bytes.

This starts the function off with:

string get_request_content(const FCGX_Request & request) {
    char * content_length_str = FCGX_GetParam("CONTENT_LENGTH",
                                               request.envp);
    unsigned long content_length = STDIN_MAX;

    if (content_length_str) {
        content_length = strtol(content_length_str,
                                &content_length_str,
                                10);

        if (*content_length_str) {
            cerr << "Can't Parse 'CONTENT_LENGTH='"
                 << FCGX_GetParam("CONTENT_LENGTH", request.envp)
                 << "'. Consuming stdin up to " << STDIN_MAX << endl;
        }

        if (content_length > STDIN_MAX) {
            content_length = STDIN_MAX;
        }
    } else {
        // Do not read from stdin if CONTENT_LENGTH is missing
        content_length = 0;
    }
    ...
}

Now we have the content length we may actually read from standard input, up to the content_length number of characters.

...
    char * content_buffer = new char[content_length];
    cin.read(content_buffer, content_length);
    content_length = cin.gcount();
...

As a caveat of mod_fastcgi (currently not being used but nevertheless it can’t hurt to be a bit defensive) is that we need to consume the rest of stdin for the request because it doesn’t handle the request correctly otherwise.

...
    // ignore() doesn't set the eof bit in some versions of glibc++
    // so use gcount() instead of eof()...
    do cin.ignore(1024); while (cin.gcount() == 1024);

Finally we can package up the content into a string and free the allocated memory for our content_buffer.

...
    string content(content_buffer, content_length);
    delete [] content_buffer;
    return content;

End Result

Adding some simple changes to call this function and get the uri we end up with a fcgi program that takes http input! Download final version here (main_v2.cpp)
To run this code we recompile with main_v2.cpp and spawn the fcgi process again (link).
If we use curl to post to the site we get:

> curl -d "chris" http://localhost/foobar
<html>
  <head>
    <title>Hello, World!</title>
  </head>
  <body>
    <h1>Hello chris from /foobar !</h1>
  </body>
</html>

And a simple fcgi app in c++ is done!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值