[FASTCGI] help needed...

David Birnbaum davidb at chelsea.net
Sun Mar 13 15:22:20 EDT 2011


Tom,

I think you have it right.

I pretty much use FastCGI exclusively within the Perl paradigm, so I 
can't comment about the C portion, but yes, you have to use the FastCGI 
routines to read the environment and read/write to the streams.  I 
thought there were some examples in the Dev kit, but your examples look 
great too.

Cheers,

David.

-----

On 3/13/11 6:39 AM, Tom Bowden wrote:
> Of course -- I am operating under the assumption that the way I am 
> using FastCGI is right; and that my understanding of its architecture 
> is correct...  neither of which may be true statements - but at least 
> it works for me :)
>
>
> Tom
>
>
> On Mar 11, 2011, at 8:12 PM, Tom Bowden wrote:
>
>> Speaking as a recent convert (of about a year or so) I would 
>> certainly hope that you don't lose hope with FastCgi.
>>
>> At first blush -- it isn't stdout that you're supposed to write to...
>>
>> Some tips/pointers that I have gleaned from this newsgroup and the 
>> examples in the code -- along with how I use fastcgi:
>>
>> I have applications that must select on sockets from postgres, 
>> inotifyd, and fastcgi -- so I can't use fcgi_* .  So I use the 
>> thread-safe version of FCGX functions.
>> I also have to play around a lot with headers -- to pass cookies, 
>> custom status codes, etc.  So I create a number of ostringstream 
>> objects, write to them - and then dump them out as I need to with 
>> FCGX_PutStr().
>>
>> What helped me the most -- with the paradigm of fastcgi -- is that 
>> I'm not really receiving from stdin and stdout (anonymous pipes 
>> associated with program).  Instead I am talking with sockets that are 
>> hidden by the API.
>> Here's some snippets.. FWIW.  If more complete examples are needed I 
>> can post them.,...  but perhaps this is enough.
>>
>>
>>
>> In my startup of an object that communicates:
>> void IDOTicket::startup()
>> {
>>         FCGX_Init();
>>         FCGX_InitRequest(&_request, 0, 0);
>>         fcntl(FCGI_LISTENSOCK_FILENO, F_SETFL, O_NONBLOCK);
>>         _cin_streambuf = cin.rdbuf();
>>         _cout_streambuf = cout.rdbuf();
>>         _cerr_streambuf = cerr.rdbuf();
>>
>> }
>>
>> When I receive notification that there is a request to process:
>>
>> int IDOTicket::process_fastcgi_environment(Json::Value& pc)
>> {
>>         int fcgx_method = FCGX_UNDEFINED;
>>         if (FCGX_Accept_r(&_request) != 0) {
>>             .. do stuff here ..
>> }
>>
>>
>>
>>
>> When I read from the socket:
>>
>> long IDOTicket::read_xml_request(std::string& content_string)
>> {
>>         char * clenstr = FCGX_GetParam("CONTENT_LENGTH", _request.envp);
>>         unsigned long clen = STDIN_MAX;
>>         if (clenstr) {
>>           clen = strtol(clenstr, &clenstr, 10);
>>           if (*clenstr) {
>>             clen = STDIN_MAX;
>>           }
>>
>>           // *always* put a cap on the amount of data that will be read
>>           if (clen > STDIN_MAX) {
>>             clen = STDIN_MAX;
>>           }
>>
>>           content_string.resize( clen );
>>           std::string input_str;
>>           FCGX_GetStr((char*)content_string.data(), clen, _request.in);
>>           _ticket_interface_object->input(xmlParseMemory( 
>> content_string.c_str(), content_string.size()));
>>
>>         } else {
>>           // *never* read stdin when CONTENT_LENGTH is missing or 
>> unparsable
>>           content_string.empty();
>>           clen = 0;
>>         }
>>
>>         // Chew up any remaining stdin - this shouldn't be necessary
>>         // but is because mod_fastcgi doesn't handle it correctly.
>>         // 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);
>>
>>         if ( content_string.empty() ) {
>>           return 0L;
>>         } else {
>>           return content_string.size();
>>         }
>> }
>>
>> WHEN I READ An environmental variable passed from apache, created by 
>> the fastcgi manager, and then consumed in my app:
>>
>>         char* const* envp = _request.envp;
>>
>>         for ( envp = _request.envp; *envp; ++envp) {
>>           Json::Value p_context = Json::Value(objectValue);
>>           std::string name;
>>           std::string value;
>>           if ( IDOPattern( PCRE_POST_REQUEST_METHOD)->PartialMatch( 
>> (*envp),&name, &value ) ) {
>>             fcgx_method = FCGX_POST;
>>           } else if ( IDOPattern( 
>> PCRE_GET_REQUEST_METHOD)->PartialMatch( (*envp),&name, &value ) ) {
>>             fcgx_method = FCGX_GET;
>>           } else if ( IDOPattern( PCRE_QUERY_STRING)->PartialMatch( 
>> (*envp), &name, &value) ) {
>>             std::string param_name;
>>             std::string param_value;
>>             std::string param_post;
>>             while ( IDOPattern( PCRE_SERIALIZED_FORM)->PartialMatch( 
>> value.c_str(), &param_name, &param_value, &param_post) ) {
>>               p_context[HAS_NAME_OF] = param_name;
>>               p_context[HAS_TYPE_OF] = param_name;
>>               p_context[HAS_VALUE_OF] = param_value;
>>               pc.append(p_context);
>>               value = param_post;
>>             }
>>           }
>>         }
>>
>>
>>
>> WHEN I am writing to the socket:
>>
>>           if ( data_stream.str().size() < 1 ) {
>>             http_stream << "Content-Length: " << 
>> content_stream.str().size() << std::endl;
>>           } else {
>>             content_stream << data_stream.str() << std::endl;
>>             http_stream << "Content-Length: " << 
>> content_stream.str().size() << std::endl;
>>           }
>>           header_stream << std::endl;
>>
>>           if ( http_stream.str().size() > 0) {
>>             FCGX_PutStr(http_stream.str().c_str(), 
>> http_stream.str().size(), _request.out);
>>           }
>>           if ( header_stream.str().size() > 0) {
>>             FCGX_PutStr(header_stream.str().c_str(), 
>> header_stream.str().size(), _request.out);
>>           }
>>           if ( content_stream.str().size() > 0) {
>>             FCGX_PutStr(content_stream.str().c_str(), 
>> content_stream.str().size(), _request.out);
>>           }
>>         }
>>
>>
>> When I am finished with the socket/call of a single request:
>>
>>         FCGX_Finish_r(&_request);
>>
>>
>>
>> AS FOR LINKING:
>>
>> Snippets from my Makefile
>>
>> INCS += -I/usr/include/fastcgi
>>
>> LIBS +=-lxslt
>> LIBS +=-lfcgi++
>> LIBS +=  $(PCRE_LIB_OPS) -lpcrecpp $(CURL_LIB_OPS) 
>> $(READLINE_LIB_OPS)  \
>>         -L/usr/lib -lpthread -lm -ldl -lxml2 -lz
>>
>>
>> On Mar 11, 2011, at 7:35 AM, Majed Al-Dolaimi wrote:
>>
>>> Hi guys,
>>> I am a bit disappointed in the FastCGI documentation, as many other 
>>> people are. However I am not losing hope with it.
>>>
>>> 1 - I installed the apache mod_fcgid  from SUSE website and it seems 
>>> to be working..
>>> 2 - I configured, compiled the fcgi-(*-*).tar.gz and added the libs 
>>> to the /usr/lib.
>>> 3 - Added the -Ifcgi++ (or -Ifcgi ) library to my Makefile... my 
>>> compiler is not complaining
>>> 4 - Added the FCGI_Accept() loop to my main routing in my c++ app...
>>>
>>> RESULTS: When I run the whole thing ...
>>> 5 - my app runs (it shows on the process monitor as a sleeping 
>>> process) and does not stop immediately which fine and dandy
>>> 6 - I only get a blank page in the browser. Even an error message 
>>> from my WWW server does not show up.
>>> I tried flushing the std::cout as well as writing to stdout file 
>>> descrptier then flush it... nothing shows up on the browser screen..
>>>
>>>  What I could not understand is making sure the linker searches for 
>>> the BSD socket library. Since the ldconfig did not complain, I 
>>> assumed it found it, right?
>>>
>>> Your help will pay back to fastcgi... so please help me out..
>>>
>>> Majed Dolaimi
>>> C++/ web developer
>>> _______________________________________________
>>> FastCGI-developers mailing list
>>> FastCGI-developers at mailman.fastcgi.com
>>> http://mailman.pins.net/mailman/listinfo.cgi/fastcgi-developers
>>
>
> _______________________________________________
> FastCGI-developers mailing list
> FastCGI-developers at mailman.fastcgi.com
> http://mailman.pins.net/mailman/listinfo.cgi/fastcgi-developers


More information about the FastCGI-developers mailing list