Getting Request URI and Content in C++ FCGI

本文介绍如何使用FCGI在C++中创建一个简单的HTTP应用程序,该程序能够接收并处理HTTP请求,包括读取URI及POST内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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!

python基于django框架航空订票管理系统设计与实现mysql数据库(项目源码+文档说明),含有代码注释,新手也可看懂,个人手打98分项目,导师非常认可的高分项目,毕业设计、期末大作业和课程设计高分必看,下载下来,简单部署,就可以使用。该项目可以直接作为毕设、期末大作业使用,代码都在里面,系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值,项目都经过严格调试,确保可以运行! python基于django框架航空订票管理系统设计与实现mysql数据库(项目源码+文档说明)python基于django框架航空订票管理系统设计与实现mysql数据库(项目源码+文档说明)python基于django框架航空订票管理系统设计与实现mysql数据库(项目源码+文档说明)python基于django框架航空订票管理系统设计与实现mysql数据库(项目源码+文档说明)python基于django框架航空订票管理系统设计与实现mysql数据库(项目源码+文档说明)python基于django框架航空订票管理系统设计与实现mysql数据库(项目源码+文档说明)python基于django框架航空订票管理系统设计与实现mysql数据库(项目源码+文档说明)python基于django框架航空订票管理系统设计与实现mysql数据库(项目源码+文档说明)python基于django框架航空订票管理系统设计与实现mysql数据库(项目源码+文档说明)python基于django框架航空订票管理系统设计与实现mysql数据库(项目源码+文档说明)python基于django框架航空订票管理系统设计与实现mysql数据库(项目源码+文档说明)python基于django框架航空订票管理系统设计与实现mysql数据库(项目源码+文档说明)python基于django框架航空
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值