2012-02-28 18 views
-3

私はLight HTTPdを使ってC++で書かれた動作中のFastCGIアプリケーションを持っていますが、getenv("QUERY_STRING")を使ってクエリ文字列を取得することはできません。私は、クエリ文字列要求を取り出し(またはnullのチェックを追加する)場合はすべてが正常に動作しますが、それに代わって、それは失敗します。getenv( "QUERY_STRING")がFastCGI C++プログラムで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を返すのですか?そして、それは何ですか私はそれを取得するのですか?

答えて

7

C/C++のリファレンスFastCGIライブラリには豊富な経験はありませんが、以前はWindows用のCGIライブラリとFastCGIライブラリの両方を実装していました。

基本的には、the FastCGI specificationに従って、CGI環境変数は、通常FastCGIライブラリによってデコードされるFCGI_PARAMSストリームを通過します。今、FastCGIは何が必要で何が必要でないかをあまり指定しておらず、規則ははCGIと基本的に同じと仮定しています。 CGI仕様のセクション4.1.7はQUERY_STRING環境変数については、次の言う:この変数を設定し

サーバーMUSTを。 Script-URIにクエリコンポーネントが含まれていない場合は、QUERY_STRINGにする必要があります。を空文字列("")としてください。

さて、これは基本的にあなたのFastCGIライブラリが(仕様に従っていないか、他のゲートウェイサーバ)FCGI_PARAMSストリームにQUERY_STRINGパラメータをデコードしていることを意味します。

リファレンスライブラリはCGIとFastCGIライブラリを同じプログラムで抽象化しようとし、マルチスレッドをサポートしているので、環境変数に結果が見つかる(競合条件がある)ことは強く疑います。

基本的に、これはgetenv()は常にNULLを返し、あなたがoperator<<を通じてstd::ostreamにヌルconst char*を渡している違法であることを意味します。 NULLはストリームの終わりを指定する特殊な値ではないため、おそらくアプリケーションがクラッシュします。


TL; DR: CGIではなく、FastCGIを使用しているため、プロセス環境を使用してQUERY_STRING値にアクセスすることはできません。リクエストのクエリ文字列にアクセスするための標準的な方法については、ライブラリのドキュメントを参照する必要があります。


編集:私はこのような状況にいくつかのより多くの情報を持っています。

documentation for FCGX_Accept_r() in fcgiapp.h

says`:

getenv(3)介し をアクセスするためのパラメータ・データ構造を作成する(environに割り当てられている場合)またはFCGX_GetParam によって及び*envpに割り当てます。 FCGX_Accept_r後、次を使用して

は、問題を修正します:

environ = request.envp; 

しかし、これは、マルチスレッドアプリケーション(environは、スレッドローカルストレージではありません)のために安全ではないので、私はあなたのことをお勧めします代わりに他の文書化された方法を使用してください:

const char * query_string = FCGX_GetParam("QUERY_STRING", request.envp); 
+0

これは実際にクエリ文字列にアクセスする方法を文書化したものです。 http://www.fastcgi.com/devkit/doc/fastcgi-prog-guide/ch2c.htm私がここに来る前に、私はたくさんのRTMをしていました。また、私はnullを確認してくれたことに感謝しました。 – user1202909

+0

@ user1202909:私の答えが更新されました。あなたのコードは、文書に記載されている前提条件を満たしていません。 –

+0

実際、FWIW、libstdC++はヌル 'char const *'のストリーミングをチェックします。まだUBです。もちろん –

関連する問題