2 * A simple FastCGI application example in C++.
4 * $Id: echo-cpp.cpp,v 1.10 2002/02/25 00:46:17 robs Exp $
6 * Copyright (c) 2001 Rob Saccoccio and Chelsea Networks
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 extern char ** environ
;
41 #include "fcgi_config.h" // HAVE_IOSTREAM_WITHASSIGN_STREAMBUF
45 // Maximum number of bytes allowed to be read from stdin
46 static const unsigned long STDIN_MAX
= 1000000;
48 static void penv(const char * const * envp
)
51 for ( ; *envp
; ++envp
)
53 cout
<< *envp
<< "\n";
58 static long gstdin(FCGX_Request
* request
, char ** content
)
60 char * clenstr
= FCGX_GetParam("CONTENT_LENGTH", request
->envp
);
61 unsigned long clen
= STDIN_MAX
;
65 clen
= strtol(clenstr
, &clenstr
, 10);
68 cerr
<< "can't parse \"CONTENT_LENGTH="
69 << FCGX_GetParam("CONTENT_LENGTH", request
->envp
)
74 // *always* put a cap on the amount of data that will be read
75 if (clen
> STDIN_MAX
) clen
= STDIN_MAX
;
77 *content
= new char[clen
];
79 cin
.read(*content
, clen
);
84 // *never* read stdin when CONTENT_LENGTH is missing or unparsable
89 // Chew up any remaining stdin - this shouldn't be necessary
90 // but is because mod_fastcgi doesn't handle it correctly.
92 // ignore() doesn't set the eof bit in some versions of glibc++
93 // so use gcount() instead of eof()...
94 do cin
.ignore(1024); while (cin
.gcount() == 1024);
104 streambuf
* cin_streambuf
= cin
.rdbuf();
105 streambuf
* cout_streambuf
= cout
.rdbuf();
106 streambuf
* cerr_streambuf
= cerr
.rdbuf();
108 FCGX_Request request
;
111 FCGX_InitRequest(&request
, 0, 0);
113 while (FCGX_Accept_r(&request
) == 0)
115 // Note that the default bufsize (0) will cause the use of iostream
116 // methods that require positioning (such as peek(), seek(),
117 // unget() and putback()) to fail (in favour of more efficient IO).
118 fcgi_streambuf
cin_fcgi_streambuf(request
.in
);
119 fcgi_streambuf
cout_fcgi_streambuf(request
.out
);
120 fcgi_streambuf
cerr_fcgi_streambuf(request
.err
);
122 #if HAVE_IOSTREAM_WITHASSIGN_STREAMBUF
123 cin
= &cin_fcgi_streambuf
;
124 cout
= &cout_fcgi_streambuf
;
125 cerr
= &cerr_fcgi_streambuf
;
127 cin
.rdbuf(&cin_fcgi_streambuf
);
128 cout
.rdbuf(&cout_fcgi_streambuf
);
129 cerr
.rdbuf(&cerr_fcgi_streambuf
);
132 // Although FastCGI supports writing before reading,
133 // many http clients (browsers) don't support it (so
134 // the connection deadlocks until a timeout expires!).
136 unsigned long clen
= gstdin(&request
, &content
);
138 cout
<< "Content-type: text/html\r\n"
140 "<TITLE>echo-cpp</TITLE>\n"
141 "<H1>echo-cpp</H1>\n"
142 "<H4>PID: " << pid
<< "</H4>\n"
143 "<H4>Request Number: " << ++count
<< "</H4>\n";
145 cout
<< "<H4>Request Environment</H4>\n";
148 cout
<< "<H4>Process/Initial Environment</H4>\n";
151 cout
<< "<H4>Standard Input - " << clen
;
152 if (clen
== STDIN_MAX
) cout
<< " (STDIN_MAX)";
153 cout
<< " bytes</H4>\n";
154 if (clen
) cout
.write(content
, clen
);
156 if (content
) delete []content
;
158 // If the output streambufs had non-zero bufsizes and
159 // were constructed outside of the accept loop (i.e.
160 // their destructor won't be called here), they would
161 // have to be flushed here.
164 #if HAVE_IOSTREAM_WITHASSIGN_STREAMBUF
166 cout
= cout_streambuf
;
167 cerr
= cerr_streambuf
;
169 cin
.rdbuf(cin_streambuf
);
170 cout
.rdbuf(cout_streambuf
);
171 cerr
.rdbuf(cerr_streambuf
);