m CMc@sdZdZdZdkZdkZdkZdkZdkZdk Z dk Z dk Z dk Z ydk Z dkZeZWn+ej odkZ dkZeZnXee dp de _ndgZdZdZdZdZd Zd Zd Zd Zd Z dZ!dZ"dZ#dZ$dZ%e%Z&dZ'dZ(dZ)d Z*d Z+dZ,dZ-d Z.d Z/dZ0dZ1dZ2dZ3dZ4dZ5dZ6ei7e5Z8ei7e6Z9e:o"dk;Z;dZ<dZ=dZ>nde?fdYZ@de@fdYZAde?fd YZBd!e?fd"YZCd#e?fd$YZDdd%ZEd&ZFd'e?fd(YZGd)e?fd*YZHd+eHfd,YZId-e?fd.YZJd/eJfd0YZKd1e?fd2YZLdeLfd3YZMeNd4jod5ZOeMeOiPndS(6s fcgi - a FastCGI/WSGI gateway. For more information about FastCGI, see . For more information about the Web Server Gateway Interface, see . Example usage: #!/usr/bin/env python from myapplication import app # Assume app is your WSGI application object from fcgi import WSGIServer WSGIServer(app).run() See the documentation for WSGIServer/Server for more information. On most platforms, fcgi will fallback to regular CGI behavior if run in a non-FastCGI context. If you want to force CGI behavior, set the environment variable FCGI_FORCE_CGI to "Y" or "y". sAllan Saddi s $Revision$NtSHUT_WRit WSGIServeriiiiiiiii i i tFCGI_MAX_CONNSt FCGI_MAX_REQStFCGI_MPXS_CONNSs!BBHHBxs!HB5xs!LB3xs!B7xs /tmp/fcgi.logcCsdt|jodSnyAttd}|idtidd!|f|i WnnXdS(Ntas %sfcgi: %s ii( tDEBUGtleveltopentDEBUGLOGtftwritettimetctimetmsgtclose(RRR ((tE/home/camdpams_www/Products_Activation/gluon/contrib/gateways/fcgi.pyt_debugs $t InputStreamcBshtZdZdZdZdZddZedZddZ d Z d Z d Z RS( s File-like object representing FastCGI input streams (FCGI_STDIN and FCGI_DATA). Supports the minimum methods required by WSGI spec. cCsI||_|ii|_d|_g|_d|_d|_ t |_ dS(Nti( tconntselft_conntservertinputStreamShrinkThresholdt_shrinkThresholdt_buft_bufListt_post_availtFalset_eof(RR((Rt__init__s     cCs`|i|ijoI|i|i|_|i|i8_d|_|idjptndS(s6Gets rid of already read data (since we can't rewind).iN(RRRRRtAssertionError(R((Rt _shrinkBuffers  cCs|iidS(s(Waits for more data to become available.N(RRt process_input(R((Rt _waitForDatasicCs|i|ijo|iodSnxgto_|djp|i|i|jo)|io|i}Pq|iq(q(|i|}Pq(W|io(|i di |i7_ g|_n|i |i|!}||_|i |S(NRi( RRRRtTruetntnewPosR$RRtjointrR"(RR&R)R'((Rtreads&$        cCs|i|ijo|iodSnxto|io(|idi|i7_g|_n|iid|i}|djo)|io|i}Pq|i q(q(|d}Pq(W|dj o)|i||jo|i|}qn|i|i|!}||_|i|S(NRs ii(RRRRR%RRR(tfindtiR'R$tlengthtNoneR)R"(RR-R,R)R'((Rtreadlines.          icCswd}g}|i}xX|oP|i||t|7}d|jo |jnoPn|i}qW|S(Ni(ttotaltlinesRR/tlinetappendtlentsizehint(RR5R1R2R0((Rt readliness  cCs|S(N(R(R((Rt__iter__scCs!|i}|p tn|S(N(RR/R)t StopIteration(RR)((Rtnexts  cCs=|p t|_n&|ii||it|7_dS(N(tdataR%RRRR3RR4(RR:((Rtadd_datas ( t__name__t __module__t__doc__R R"R$R*R.R/R6R7R9R;(((RRs      tMultiplexedInputStreamcBsAtZdZdZdZddZedZdZRS(s A version of InputStream meant to be used with MultiplexedConnections. Assumes the MultiplexedConnection (the producer) and the Request (the consumer) are running in different threads. cCs8tt|i|ti}ti||_ dS(N( tsuperR?RR Rt threadingtRLocktlockt Conditiont_lock(RRRC((RR s cCs|iidS(N(RREtwait(R((RR$sicCs<|iiztt|i|SWd|iiXdS(N(RREtacquireR@R?R*R&trelease(RR&((RR*s  cCs<|iiztt|i|SWd|iiXdS(N(RRERGR@R?R/R-RH(RR-((RR/s  cCsI|iiz'tt|i||iiWd|iiXdS(N( RRERGR@R?R;R:tnotifyRH(RR:((RR;"s  ( R<R=R>R R$R*R.R/R;(((RR?s    t OutputStreamcBsGtZdZedZdZdZdZdZdZ RS(s FastCGI output stream (FCGI_STDOUT/FCGI_STDERR). By default, calls to write() or writelines() immediately result in Records being sent back to the server. Buffering should be done in a higher level! cCsC||_||_||_||_g|_ t |_ t |_ dS(N( RRRtreqt_reqttypet_typetbufferedt _bufferedRRt dataWrittentclosed(RRRKRMRO((RR 0s      cCst|}xz|ort||iiit}t |i |ii }||_|| |_|ii|||}||8}qWdS(N(R4R:R-tminRRLRtmaxwritetFCGI_HEADER_LENttoWritetRecordRNt requestIdtrect contentLengtht contentDataRt writeRecord(RR:RVR-RY((Rt_write9s    cCsY|i pt|pdSnt|_|io|ii|n|i |dS(N( RRRR!R:R%RQRPRR3R](RR:((RR Fs  cCs4|i ptx|D]}|i|qWdS(N(RRRR!R1R2R (RR1R2((Rt writelinesSscCs:|io,di|i}g|_|i|ndS(NR(RRPR(RR:R](RR:((RtflushYs  cCsX|i oI|io?|it|i|ii}|i i |t |_ndS(s/Sends end-of-stream notification, if necessary.N( RRRRQR_RWRNRLRXRYRR\R%(RRY((RRas  ( R<R=R>RR R]R R^R_R(((RRJ*s   tTeeOutputStreamcBs2tZdZdZdZdZdZRS(sq Simple wrapper around two or more output file-like objects that copies written data to all streams. cCs ||_dS(N(t streamListRt _streamList(RRa((RR nscCs%x|iD]}|i|q WdS(N(RRbR R R:(RR:R ((RR qs cCs"x|D]}|i|qWdS(N(R1R2RR (RR1R2((RR^uscCs"x|iD]}|iq WdS(N(RRbR R_(RR ((RR_ys (R<R=R>R R R^R_(((RR`is    t StdoutWrappercBs2tZdZdZdZdZdZRS(sN Wrapper for sys.stdout so we know if data has actually been written. cCs||_t|_dS(N(tstdoutRt_fileRRQ(RRd((RR s cCs(|o t|_n|ii|dS(N(R:R%RRQReR (RR:((RR s cCs"x|D]}|i|qWdS(N(R1R2RR (RR1R2((RR^scCst|i|S(N(tgetattrRRetname(RRg((Rt __getattr__s(R<R=R>R R R^Rh(((RRc}s    cCst||}|d@o3tid|||d!dd@}|d7}n |d7}t||}|d@o3tid|||d!dd@}|d7}n |d7}||||!}||7}||||!}||7}|||ffS(sv Decodes a name/value pair. The number of bytes decoded as well as the name/value pair are returned. is!LiiiiN( tordtstpost nameLengthtstructtunpackt valueLengthRgtvalue(RjRkRpRlRoRg((Rt decode_pairs  %  %   cCst|}|djot|}ntid|dB}t|}|djo|t|7}n|tid|dB7}|||S(sI Encodes a name/value pair. The encoded string is returned. is!LlN( R4RgRltchrRjRmtpackRpRo(RgRpRjRlRo((Rt encode_pairs    RWcBsYtZdZeedZdZeeZdZdZ ee Z dZ RS(sD A FastCGI Record. Used for encoding/decoding records. cCs:t|_||_||_d|_d|_d|_dS(NiR(tFCGI_VERSION_1RtversionRMRXRZt paddingLengthR[(RRMRX((RR s      cCsg}d}x|oy|i|}WnLtij o=}|dt i jot i |gggqqxnX|pPn|i |t |}||7}||8}qWdi||fS(s Attempts to receive length bytes from a socket, blocking if necessary. (Socket may be blocking or non-blocking.) iRN(tdataListtrecvLenR-tsocktrecvR:tsocketterrorteterrnotEAGAINtselectR3R4tdataLenR((RzR-RR~RxRyR:((Rt_recvalls&   cCs=y|i|t\}}Wn tnX|tjo tntit |\|_ |_ |_ |_ |_to0tdd|i|i |i |i fn|i oPy"|i||i \|_}Wn tnX||i jo tqn|io+y|i||iWq9tq9XndS(s'Read and decode a Record from a socket.i s<read: fd = %d, type = %d, requestId = %d, contentLength = %dN(RRRzRUtheaderR-tEOFErrorRmRnt FCGI_HeaderRvRMRXRZRwt __debug__RtfilenoR[(RRzRR-((RR*s.   00    cCst|}x|ozy|i|}WnLtij o=}|dt i jot i g|ggqqxnX||}||8}qWdS(sY Writes data to a socket and does not return until all the data is sent. iN( R4R:R-RztsendtsentR|R}R~RRR(RzR:R~R-R((Rt_sendall s  cCs|i d@|_to0tdd|i|i|i|ifnt i t |i |i|i|i|i}|i|||io|i||in|io|i|d|indS(s&Encode and write a Record to a socket.ii s=write: fd = %d, type = %d, requestId = %d, contentLength = %dtN(RRZRwRRRzRRMRXRmRsRRvRRR[(RRzR((RR s0    ( R<R=R>tFCGI_UNKNOWN_TYPEtFCGI_NULL_REQUEST_IDR Rt staticmethodR*RR (((RRWs    "  tRequestcBs8tZdZdZdZdedZdZRS(s8 Represents a single FastCGI request. These objects are passed to your handler and is the main interface between your handler and the fcgi module. The methods should not be called by your handler. However, server, params, stdin, stdout, stderr, and data are free for your handler's use. cCsp||_|i|_h|_|||_t||t|_ t||t dt |_ |||_ dS(NRO(RRRRtparamstinputStreamClasststdinRJt FCGI_STDOUTRdt FCGI_STDERRR%tstderrR:(RRR((RR 7s   cCsy|ii|\}}WnUtid|i|ii|i i p|ii |nt d}}nXt otdd||fn|i|i||dS(s<Runs the handler, flushes the streams, and ends the request.tfileiis#protocolStatus = %d, appStatus = %dN(RRthandlertprotocolStatust appStatust tracebackt print_excRR_RdRQR}tFCGI_REQUEST_COMPLETERRt_flusht_end(RRR((RtrunAs   lcCs|ii|||dS(N(RRt end_requestRR(RRR((RRSscCs|ii|iidS(N(RRdRR(R((RRVs (R<R=R>R RRRR(((RR.s  t CGIRequestcBs/tZdZdZdedZdZRS(s4A normal CGI request disguised as a FastCGI request.cCs|d|_t|_d|_t|_||_tt i |_ t i |_ tt i|_t i|_ti|_dS(Nii(RRXtFCGI_RESPONDERtroletflagsRtabortedRtdicttostenvironRtsysRRcRdRtStringIOR:(RR((RR \s       lcCsti|dS(N(RtexitR(RRR((RRjscCsdS(N((R((RRms(R<R=R>R RRR(((RRZs  t ConnectioncBstZdZeZeZdZdZdZ dZ dZ de e dZdZd Zd Zd Zd Zd ZdZdZRS(s A Connection with the web server. Each Connection is associated with a single socket (which is connected to the web server) and is responsible for handling all the FastCGI message processing for that socket. cCs(||_||_||_h|_dS(N(RzRt_socktaddrt_addrRt _requests(RRzRR((RR |s   cCsy|iitiWn dSnXyXxQtoIti|iggg\}}}| p|ii d oPq+q+WWnnX|ii dS(sClose the Connection's socket.Ni( RRtshutdownR|RR%RR)twR~R{R(RR~R)R((Rt_cleanupSockets$cCst|_xp|ioey|iWq tj oPq titifj o%}|dt i joPnq Xq W|i dS(s&Begin processing data from the socket.iN( R%Rt _keepGoingR#RRR}R|R~RtEBADFR(RR~((RRs   cCs{xb|ioWy+ti|igggd\}}}Wntj o tnX|oPqqW|ipdSnt }|i |i|i t jo|i|n|i tjo|i|n|i tjo|i|n|i tjo|i|nd|i tjo|i|nC|i tjo|i|n"|itjo|i|ndS(s?Attempt to read a single Record from the socket and process it.f1.0N(RRRRR)RR~t ValueErrorRRWRYR*RMtFCGI_GET_VALUESt_do_get_valuestFCGI_BEGIN_REQUESTt_do_begin_requesttFCGI_ABORT_REQUESTt_do_abort_requestt FCGI_PARAMSt _do_paramst FCGI_STDINt _do_stdint FCGI_DATAt_do_dataRXRt_do_unknown_type(RR~R)RRY((RR#s6 +    cCs|i|idS(s/ Write a Record to the socket. N(RYR RR(RRY((RR\slcCstt|i}tit|||_ t |_ |i||o|i|i=ntotdd|in|it@ o"|i o|it|_ndS(s  End a Request. Called by Request objects. An FCGI_END_REQUEST Record is sent to the web server. If the web server no longer requires the connection, the socket is closed, thereby ending this Connection (run() returns). isend_request: flags = %dN(RWtFCGI_END_REQUESTRKRXRYRmRstFCGI_EndRequestBodyRRR[tFCGI_EndRequestBody_LENRZRR\tremoveRRRRtFCGI_KEEP_CONNRRR(RRKRRRRY((RRs      cCstt}d}xw||ijoft|i|\}\}}|i i i |}|dj o"|it|t|7_qqWt|i|_|i|dS(s6Handle an FCGI_GET_VALUES request from the web server.iN(RWtFCGI_GET_VALUES_RESULTtoutrecRktinrecRZRqR[RgRpRRt capabilitytgettcapR.RttstrR4R\(RRRRRkRpRg((RRs  'cCstit|i\}}|ii ||i }|i |||_ |_|_t |_|i o'|io|i|dtdt n||i|i tt}tit|i|_t |_ |i t dS(s4Handle an unknown request type. Respond accordingly.N(RWRRRmRstFCGI_UnknownTypeBodyRRMR[tFCGI_UnknownTypeBody_LENRZRR\RY(RRR((RR-s   (R<R=R>RRRRR RRR#R\RR%RRRRRRRRR(((RRqs"     %       tMultiplexedConnectioncBs}tZdZeZeZdZdZdZ de edZ dZ dZ dZd Zd Zd ZRS( s[ A version of Connection capable of handling multiple requests simultaneously. cCs>tt|i|||ti}ti ||_ dS(N( R@RRR RzRRRARBRCRDRE(RRzRRRC((RR <s cCsP|iix|io|iiqW|iitt|idS(N( RRERGRRFRHR@RR(R((RRFs    cCs6|iiz|i|iWd|iiXdS(N(RRERGRYR RRH(RRY((RR\Os  lcCsR|iiz0tt|i|||||ii Wd|ii XdS(N( RRERGR@RRRKRRRRIRH(RRKRRR((RRYs cCs<|iiztt|i|Wd|iiXdS(N(RRERGR@RRRRH(RR((RRds  cCs<|iiztt|i|Wd|iiXdS(N(RRERGR@RRRRH(RR((RRks  cCsti|ifdS(N(tthreadtstart_new_threadRKR(RRK((RRrscCs<|iiztt|i|Wd|iiXdS(N(RRERGR@RRRRH(RR((RRus  cCs<|iiztt|i|Wd|iiXdS(N(RRERGR@RRRRH(RR((RR|s  cCs<|iiztt|i|Wd|iiXdS(N(RRERGR@RRRRH(RR((RRs  (R<R=R>R%RR?RR RR\RRRRRRRR(((RR4s       tServercBstZdZeZeZddZedeee dZ dZ dZ dZ dZdZd Zd d Zd Ze d ZdZdZRS(s The FastCGI server. Waits for connections from the web server, processing each request. If run in a normal CGI context, it will instead instantiate a CGIRequest and run the handler through there. ii c Cs|dj o ||_n||_toy#dk}|i|id}Wnt j o d}nX|}|ot |_ |d9}n t|_ ht|<t|<t|odpd<|_n.t|_ htd<td<td<|_||_||_dS(s^ handler, if present, must reference a function or method that takes one argument: a Request object. If handler is not specified at creation time, Server *must* be subclassed. (The handler method below is abstract.) maxwrite is the maximum number of bytes (per Record) to write to the server. I've noticed mod_fastcgi has a relatively small receive buffer (8K or so). bindAddress, if present, must either be a string or a 2-tuple. If present, run() will open its own listening socket. You would use this if you wanted to run your application as an 'external' FastCGI app. (i.e. the webserver would no longer be responsible for starting your app) If a string, it will be interpreted as a filename and a UNIX socket will be opened. If a tuple, the first element, a string, is the interface name/IP to bind to, and the second element (an int) is the port number. Set multiplexed to True if you want to handle multiple requests per connection. Some FastCGI backends (namely mod_fastcgi) don't multiplex requests at all, so by default this is off (which saves on thread creation/locking overhead). If threads aren't available, this keyword is ignored; it's not possible to multiplex requests at all. Niidii(RR.RRTtthread_availabletresourcet getrlimitt RLIMIT_NOFILEtmaxConnst ImportErrortmaxReqst multiplexedRt_connectionClassRRRRRt bindAddresst _bindAddresstumaskt_umask( RRRTRRRRRR((RR s(       6 $ cCs#|idjot}tittiti }y|i WnQti j oB}|dtijo t}q|dtijoqnX| p%tiiddiido*|i|}|itidqn2d}t|itjoltititi }yti |iWnt!j onX|i"dj oti#|i"}qnlt|it$jpt%t&|idjpt%tititi }|i'ti(ti)d|i*|i|i+ti,|dj oti#|n|S(NitFCGI_FORCE_CGItNtYii(-RRR.R%tisFCGIR|tfromfdtFCGI_LISTENSOCK_FILENOtAF_INETt SOCK_STREAMRzt getpeernameR}R~RtENOTSOCKRtENOTCONNRRRtuppert startswithtcgirequest_classRKRRRtoldUmaskRMRtAF_UNIXtunlinktOSErrorRRttupleR!R4t setsockoptt SOL_SOCKETt SO_REUSEADDRtbindtlistent SOMAXCONN(RRRKR~RRz((Rt _setupSocketsB   -  cCs|idS(sCloses the main socket.N(RzR(RRz((RR scCsg}tititifD]}||ti|fq~|_titi|i titi|i titi|i dS(N( t_[1]tsignaltSIGHUPtSIGINTtSIGTERMtxt getsignalRt_oldSIGst _hupHandlert _intHandler(RRR ((Rt_installSignalHandlerssEcCs.x'|iD]\}}ti||q WdS(N(RR tsignumRR(RRR((Rt_restoreSignalHandlerss cCst|_t|_dS(N(R%Rt _hupReceivedRR(RRtframe((RR s cCs t|_dS(N(RRR(RRR((RR  sf1.0c Cstiid}|dj otd|id}n|i}t |_ t |_ |ixA|i o6y(ti|ggg|\}}}Wn6tij o'}|dtijoqinnX|oy|i\}} Wn?tij o0}|dtitifjoqinnX|o5t| djp| d|jo|iqin|i|| |}t i!|i"fn|i#qiW|i$|i%||i S(s The main loop. Exits on SIGHUP, SIGINT, SIGTERM. Returns True if SIGHUP was received, False otherwise. tFCGI_WEB_SERVER_ADDRScCs |iS(N(R tstrip(R ((Rt*st,iiN(&RRRtweb_server_addrsR.tmaptsplitRRRzR%RRRRRttimeoutR)RR~R}RtEINTRtacceptt clientSockRR|RR4RRRRRRt_mainloopPeriodicRR( RRRRRRzR)RR~R((RR#sB       (+   cCsdS(si Called with just about each iteration of the main loop. Meant to be overridden. N((R((RRXscCs$|iot|_||_ndS(s Protected convenience method for subclasses to force an exit. Not really thread-safe, which is why it isn't public. N(RRRtreloadR(RR((Rt_exit_s  cCst|iiddS(s Default handler, which just raises an exception. Unless a handler is passed at initialization time, this must be implemented by a subclass. s.handlerN(tNotImplementedErrorRt __class__R<(RRK((RRhscCs0dk}|iid|itidS(st Called by Request if an exception occurs within the handler. May and should be overridden. NsContent-Type: text/html (tcgitbRKRdR thtmlRtexc_info(RRKR#((RR}ps (R<R=R>RRRRRR.RR RRRRR R RRR RR}(((RRs  = 4      5  cBs/tZdZeedZdZdZRS(s| FastCGI server that supports the Web Server Gateway Interface. See . cKsv|ido |d=ntt|i||djo h}n||_||_||_ t i |_ dS(s  environ, if present, must be a dictionary-like object. Its contents will be copied into application's environ. Useful for passing application-specific variables. Set multithreaded to False if your application is not MT-safe. RN( tkwthas_keyR@RRR RR.t applicationt multithreadedRt allocate_lockt _app_lock(RR(RR)R&((RR ~s      c s>itjotdfSni} | i|id| d<i| d<|i djo i } nt t i i f} | | dR+RGR(R:thasattrRR|R}R~RtEPIPERHR( RRKR2R3R>R8R R:R~RR((RKR R2R8R3RRsZ     %     cCs|idpd|dR.R%R RRB(((RRys  pt__main__ccsdk}|ddgdV|i}|ix*|D]"}d||i|| fVq:W|id|dd |d d }|i od Vnx%|i D]}d|i|i fVqWd VdS(s(Probably not the most efficient example.Ns200 OKs Content-Types text/htmls\Hello World!

Hello World!

s tfps wsgi.inputRtkeep_blank_valuesis's
%s%s
Form data
(s Content-Types text/html( tcgiR>RtkeystnamestsortRgtescapet FieldStoragetformR<tfieldRp(RR>RRRgRXRYRT((Rttest_apps"       (QR>t __author__t __version__RRRRmt cStringIORRR|RRRRAR%RRt dummy_threadtdummy_threadingRRCRt__all__RRURuRRRRRRRRRRRt FCGI_MAXTYPERRRtFCGI_AUTHORIZERt FCGI_FILTERRRtFCGI_OVERLOADEDR?RRRRRRRtcalcsizeRRRR RR RtobjectRR?RJR`RcRqRtRWRRRRRRR<RZR(CRRaRRdRRbRJRtRRcRRRRRRRRmR`RRURRRR`RZRRR\RRRRRRR[RRRR RRRRWRRRcRRR|RRR?RRRR?RRARRuR RRRRRq((Rt?/s                   t*?  m,V