为什么getenv("QUERY_STRING")在FastCGI C++程序中返回null?

use*_*909 -3 c++ fastcgi lighttpd

所以我使用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"
Run Code Online (Sandbox Code Playgroud)

....

 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);
Run Code Online (Sandbox Code Playgroud)

...

    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");
 }
Run Code Online (Sandbox Code Playgroud)

我已经验证我在请求中传递了一个查询字符串,那么为什么getenv("QUERY_STRING")返回null?我应该怎么做才能找回它?

And*_*ron 7

我没有丰富的C/C++参考FastCGI库经验,但我过去已经为Windows实现了CGI和FastCGI库,所以以下内容可能有所帮助.

基本上,根据FastCGI规范,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并且您将null传递const char*std::ostreamthrough operator<<是非法的.这可能NULL会使您的应用程序崩溃,因为它不是指定流结束的特殊值.


TL; DR:您无法QUERY_STRING通过流程环境访问该值,因为您使用的是FastCGI,而不是CGI.您需要阅读库的文档,以获取访问请求的查询字符串的标准方法.


编辑:我有更多关于这种情况的信息.

in文档说FCGX_Accept_r()fcgiapp.h `:

创建要通过getenv(3)(如果已分配environ)或由其FCGX_GetParam 分配的参数数据结构*envp.

使用以下后面FCGX_Accept_r将解决问题:

environ = request.envp;
Run Code Online (Sandbox Code Playgroud)

但是,对于多线程应用程序(environ不在线程本地存储中)这是不安全的,因此我建议您使用其他记录的方法:

const char * query_string = FCGX_GetParam("QUERY_STRING", request.envp);
Run Code Online (Sandbox Code Playgroud)

  • @ user1202909:你知道......你问了一个问题,我们试图提供帮助并要求提供更多信息,而你所做的就是*反击*(首先是抵制,然后是侮辱).我是如何解决你的问题的,*你告诉我,我应该做些不同的事情*.老实说,我真的不明白.无论如何,不​​要期待我将来的帮助. (2认同)