bug-cgicc
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: Cgicc & FastCGI ...


From: Stephen F. Booth
Subject: RE: Cgicc & FastCGI ...
Date: Thu, 28 Feb 2002 16:41:17 -0500

Hi Steve,

You're the second person that has pointed out the inadequacies of
cgicc's current FastCGI capabilities.  I'll make comments after the
relevant text of your message.

> In order to use Cgicc, however, I need to be able to do per-thread/-
> request
> redirection of standard I/O and the environment from the FCGI request
to
> Cgicc.  While the newly added reader function pointer argument to
> Cgicc/CgiEnvironment makes it possible to redirect standard input, it
must
> go
> through a global function which would have no (easy) way to determine
> which
> thread/request was being serviced.  Since the environment is read
through
> getenv(), there's also no way to access the request-specific
environment
> (without a race condition).  Finally, it's assumed that the calling
> function
> handles output, but that would require an ostream-to-FCGI_Stream
wrapper.

A thought before I delve more deeply: would simply changing the
implementation of the safeGetEnv function (in CgiUtils.cpp) solve part
of the problem with accessing the request-specific environment?  

Another quick thought- would passing a "context object" (probably a
void*) to the reader function help you with anything?

> I have a solution which I think can solve all three issues - function
> objects,
> i.e.:
> 
>   class cgicc::IO {
>   public:
>     virtual int read( void *Data, int Length ) { ... }
>     virtual int write( void *Data, int Lenght ) { ... }
>     virtual string env( const string &Name ) { ... }
>   };
> 
> I propose that Cgicc (and CgiEnvironment, in turn) use an instance of
this
> object for all I/O.  The default functionality would be to use
> stdio/getenv(),
> and could be trivially overridden for use with FastCGI (or anything
else).

It's funny you mention using a cgicc I/O class, because this is how
things used to be (in pre-3.0 versions of cgicc if memory serves).  The
reason I removed the class was because I wanted people to be able to use
the form data handling portion of the library separately from the
html-generation portion of the library.  I felt that the way web content
was presented (HTML 1,2,3,4 and now XHTML) was evolving very quickly,
probably more quickly than I could keep up with in the library
implementation.  However, the way form data is handled has remained
unchanged for quite a while.  I chose to split these two parts so people
could use whatever they wanted to generate output: an xml generator or
whatever, but still use the main functionality (in my opinion) which is
the form data handling routines.  I've even tossed around the idea of
splitting cgicc into two separate libraries, one for data handling and
one for output generation.  But I'm digressing.
 
> As far as output goes, I suggest that it would be more correct (and
more
> useful, in these cases) to have Cgicc provide an ostream for
outputting
> tags
> and text, i.e.:
> 
>   class FastCGIIO : public cgicc::IO { ... }
>   cgicc::Cgicc Req( FastCGIIO() );
>   Req << h1( "Foo!" ) << getElement( "bar" ) << endl;
> 
> An ostream, either inherited or return from type-cast, would be called
and
> in
> turn call the appropriate functions in cgicc::IO.  This output design
> would be
> completely compatible (and even interchangeable) with the current
design.

I'm not sure if I agree this way is more correct- but I understand where
you're coming from.  Help me to understand your design a little bit
better- in your multithreaded application in which you have one FastCGI
instance with its single data structure, do you have (or want) a single
instance of the Cgicc class or one instance per thread?  From your
suggestion it seems to me that you would have one instance of Cgicc per
thread, and along with each of those objects you have the associated
input/output object.  In essence, when you create a Cgicc object you
associate with it a stream of some sort which it is expected to use for
all of its input and output, which in our definition includes
environment variables as well as stream I/O.

I approach this (with my two-tiered library philosophy mentioned above)
as two separate issues.  I can certainly see a strong argument to allow
the user to specify where the input data should come from (POST/GET data
and environment variables) but I'm not convinced that it should be
Cgicc's responsibility for maintaining an output class.  That is why I
decided to use the C++ STL string classes and basic data types, because
I figured it would give everyone a common baseline to work from.

Now with all that said I suppose I need to hear what you've got to say
on the subject.  I'm pretty firm in my not wanting Cgicc to have to
maintain an internal stream for output, but I could be convinced.  Where
input is concerned, I think it would be nice to add the flexibility you
mentioned.  I'm envisioning a class similar to the one you proposed to
replace the simple stream reader function that I have currently.

class cgicc::CgiInput {
        virtual std::string getenv(std::string varname);
        virtual std::size_t read(void *data, std::size_t len);
};

A pointer to an object of this type would be passed to the Cgicc
constructor, and a value of NULL would cause the library to use stdin
and getenv as it does now.

Anyway, please let me know what you think.


-Stephen





reply via email to

[Prev in Thread] Current Thread [Next in Thread]