Re: help needed...
Tom Bowden <[email protected]> Fri, 11 Mar 2011 20:12:42 -0600
| Newsgroups | gmane.comp.web.fastcgi.devel |
|---|---|
| Message-ID | <[email protected]> |
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(), ¶m_name, ¶m_value, ¶m_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-xGejAJT2w6xVgU18Zptdi0EOCMrvLtNR@public.gmane.org
> http://mailman.pins.net/mailman/listinfo.cgi/fastcgi-developers