Почему getenv ("QUERY_STRING") возвращает ноль в программе FastCGI C ++? - PullRequest
0 голосов
/ 29 февраля 2012

Итак, у меня есть работающее приложение FastCGI, написанное на C ++ с использованием Light HTTPd, однако я не могу получить строку запроса, используя getenv("QUERY_STRING"). Все работает нормально, если я возьму запрос строки запроса (или добавлю проверку на ноль), но с этим на месте это не удается:

#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") возвращает ноль? И что должен сделать, чтобы получить его?

1 Ответ

7 голосов
/ 29 февраля 2012

У меня нет большого опыта работы со справочной библиотекой FastCGI для C / C ++, но в прошлом я реализовывал библиотеки CGI и FastCGI для Windows, поэтому может помочь следующее.

В основном, согласно спецификации FastCGI , переменные среды CGI передаются через поток FCGI_PARAMS, которые обычно декодируются библиотекой FastCGI. Теперь FastCGI не определяет многое о том, что требуется, а что нет, и предполагается, что правила в основном такие же, как и для CGI . В разделе 4.1.7 спецификации CGI говорится о переменной среды 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 . Вам необходимо прочитать документацию библиотеки для стандартного способа доступа к строке запроса.


Редактировать : У меня есть еще информация об этой ситуации.

Документация для FCGX_Accept_r() в 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);
...