bug-cgicc
[Top][All Lists]
Advanced

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

RE: Cgicc & FastCGI ...


From: Steve McAndrewSmith
Subject: RE: Cgicc & FastCGI ...
Date: Thu, 28 Feb 2002 15:03:55 -0800 (PST)

On Thu, 28 Feb 2002, Stephen F. Booth wrote:

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

Yes, in the sense that a request-specific environment is necessary for any
significant CGI app.  No, in that it would then suffer from the same problems
as the reader function (see below).

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

Yes, that was going to be my first suggestion, i.e.
  typedef size_t (* reader_function_t)(void *, size_t, void *);

  CgiEnvironment( reader_function_t stream_reader, void *reader_data );
  Cgicc(reader_function_t stream_reader = NULL, void *reader_data = NULL );

  if(stream_reader == NULL) {
    ...
  } else {
    // user specified a reader function
    if((*stream_reader(reader_data))

The advantage to this method is that it's trivial to interface with an 
FastCGI stream (FCGX_Stream), i.e.:

  extern int FCGX_GetStr(char *str, int n, FCGX_Stream *stream);
  FCGX_Stream *Input;
  Cgicc CGI( (size_t (*)(void *, size_t, void *)) FCGX_GetStr, Input );

The disadvantage is that, to include environment access as well, four
arguments would have to be passed to Cgicc (and to CgiEnvironment, in turn),
and two of these pointers would have to be maintained (for reading the
environment).  Plus, it might not work so well for things other than FCGI.  
This is a C-style, non-OO solution, and since we're using C++ (we can't use
Cgicc without it), there're several preferable solutions - templated
argument(s), virtual function, function object, etc.  Which of these solutions
to use is largely a matter of taste.

> >   class cgicc::IO {
> >   public:
> >     virtual int read( void *Data, int Length ) { ... }
> >     virtual int write( void *Data, int Lenght ) { ... }
> >     virtual string env( const string &Name ) { ... }
> >   };
> 
> 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).

I was unable to find cgicc < 3.1, so you may have to post a code snippet to 
show how it was originally implemented.

> 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 hadn't thought of that.  However, I don't see how using a separate I/O class
would affect this.  That is, if I'm correct in my understanding that Cgicc and
CgiEnvironment implement the form data handling (i.e. input handling) while
HTML* and HTTP* handle generating HTML, orthogonally.  My solutions only
affects Cgicc (actually, CgiEnvironment, except for passing it the relevant
object).

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

Yes - each thread has exactly one cgicc instance, one FCGI request, and one
I/O object instance (although this may be contained in cgicc, in various
ways).

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

Exactly.

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

I don't see why they're two different issues, even with the two-tiered
philosophy.  This may be mangling your philosophy, but I see two modules:  
"I/O" and "HTML".  As a practical example, consider that, if one must override
the default functionality for input (to grab it from, say, an FCGI request),
they're probably going to have to override output as well (there's a reason
why "I/O" is a phrase - they go together).

This still puts no limits on *what* you can output, but I feel the library
should provide a simple, consistent interface to both.  You can just as easily
pass HTML to the ostream, or javascript, or TCL, or XHTML, or a raw-binary
JPEG. In fact, you might do more than one within a single Cgicc instance
(think "MIME multipart").  It would be useful to setup all I/O at creation
time, and then forget about it.

There's also the fact that it makes my life easier. ;-)  That is, if you don't
implement this, I (and everyone else who wants to run CGI/HTML over something
other than stdio) are going to have to provide an ostream-to-whatever wrapper,
to each application, for outputting stuff from the HTML module.  Since Cgicc
already (or will soon) handle the whatever-to-istream and whatever-to-
environment wrappers, why shouldn't it include output as well as input (and
save us all some headache)?

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

A good decision.  Don't think I disagree with you, just because I'm working on
a Cgicc wrapper class that uses QTL (I just prefer working with QTL
containers). :-)

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

Fair enough.  Thanks for getting back to me and letting me bend your ear (I 
love it when library maintainers, er, maintain their libraries).

For what it's worth, the amount of code we're talking about here is fairly
small.  My proposal would add two more virtual methods to CgiInput, "write()"
and "writeErr()", provide two ostreams in CgiEnvironment (with inline wrappers
in Cgicc), bound to std::streambuf derivatives in CgiEnvironment, which would
ie together the ostreams to the CgiIO instance.  Take a look at
libfcgi/fcgio.{h,cpp} for an example of how to use std::streambuf to override
stream functionality.

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

That looks great.

==============================================================================
Steve McAndrewsmith                             Drummer / Hacker / Minor Deity
------------------------------------------------------------------------------
Bungee jumping and skydiving are for wimps. If you want to experience true
gut-wrenching terror, have children.
                                -- Dusty Rhoades.
==============================================================================




reply via email to

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