[FASTCGI] help needed...

Tom Bowden charles_thomas at mac.com
Sun Mar 13 16:17:13 EDT 2011


A lot of my example is cut-pasted from the real examples :)

The parts that confused me for a while included (and why I did my own  
example quotes):

   - assignment of streams to streambufs so that  you wouldn't have  
to do the PutStr() functions and really could go straight to stdout;
   - how to make the socket non-blocking so I can select on multiple  
sockets and STILL process input,  and
   - the difference between FCGI_* and FCGX_*.

Thankfully those were all areas that I could create cookie cutter  
routines for and forget.

In my experience those areas have always been complex - regardless of  
what you're programming in... so it didn't seem unusual that I had to  
deal with it.

And that is my ultimate metric: is it complex in the usual places.

Tom


On Mar 13, 2011, at 2:22 PM, David Birnbaum wrote:

> 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
> _______________________________________________
> 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