[FASTCGI] help needed...

Tom Bowden charles_thomas at mac.com
Sun Mar 13 06:39:18 EDT 2011


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
>



More information about the FastCGI-developers mailing list