所以我使用Light HTTPd编写了一个用C ++编写的FastCGI应用程序,但是我无法使用getenv("QUERY_STRING")
检索查询字符串。如果我取出查询字符串请求(或添加一个null的检查),一切正常,但有了它就失败了:
#include <stdlib.h>
#ifdef _WIN32
#include <process.h>
#else
#include <unistd.h>
extern char ** environ;
#endif
#include "fcgio.h"
#include "fcgi_config.h" // HAVE_IOSTREAM_WITHASSIGN_STREAMBUF
#include "redisclient.h"
...
while (FCGX_Accept_r(&request) == 0)
{
fcgi_streambuf cin_fcgi_streambuf(request.in);
fcgi_streambuf cout_fcgi_streambuf(request.out);
fcgi_streambuf cerr_fcgi_streambuf(request.err);
...
cout << "Content-type: text/html\r\n"
"\r\n"
"<TITLE>^_^</TITLE>\n"
"<H1>echo-cfpp</H1>\n"
"<H4>PID: " << pid << "</H4>\n"
"<H4>Request Number: " << ++count << "</H4>\n";
// If I make this conditional on getenv("QUERY_STRING") not returning null,
// then the program behaves reliably.
cout <<getenv("QUERY_STRING");
}
我已经验证我在请求中传递了一个查询字符串,那么为什么getenv(“QUERY_STRING”)返回null? 应该我要做什么来检索它?
答案 0 :(得分:7)
我对C / C ++的FastCGI参考库没有丰富的经验,但过去我已经为Windows实现了CGI和FastCGI库,所以以下内容可能有所帮助。
基本上,根据the FastCGI specification,CGI环境变量通过FCGI_PARAMS
流传递,这些流通常由FastCGI库解码。现在,FastCGI没有详细说明需要什么和不需要什么,并且假设规则与CGI 基本相同。 CGI规范部分4.1.7说明了QUERY_STRING
环境变量的以下内容:
服务器必须设置此变量;如果
Script-URI
不包含查询组件,则QUERY_STRING
必须被定义为空字符串(""
)。
现在,这基本上意味着您的FastCGI库正在解码QUERY_STRING
流中的FCGI_PARAMS
参数(否则网关服务器不遵循规范)。
由于参考库试图在同一程序中抽象CGI和FastCGI库并支持多线程,我强烈怀疑你会在环境变量中找到结果(或者会出现竞争条件)。
基本上,这意味着getenv()
始终返回NULL
,并且您将空const char*
传递给std::ostream
到operator<<
是非法的。这可能会使您的应用程序崩溃,因为NULL
不是指定流结束的特殊值。
<强> TL; DR 强>:
您无法通过流程环境访问QUERY_STRING
值,因为您使用的是FastCGI,而不是CGI 。您需要阅读库的文档,以获取访问请求的查询字符串的标准方法。
编辑:我已经了解了有关此情况的更多信息。
documentation for FCGX_Accept_r()
in fcgiapp.h
说':
创建要访问的参数数据结构 通过
getenv(3)
(,如果已分配到environ
)或FCGX_GetParam
并将其分配给*envp
。
在FCGX_Accept_r
之后使用以下内容可以解决问题:
environ = request.envp;
但是,对于多线程应用程序来说这是不安全的(environ
不在线程本地存储中),所以我建议您使用其他记录的方法:
const char * query_string = FCGX_GetParam("QUERY_STRING", request.envp);