o k`@sLdZdZdZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl Z z ddl Z ddl Z dZWneyIddlZ ddlZ dZYnwee dsRde _d gZdZd ZdZdZd Zd Zd ZdZdZdZd ZdZ dZ!dZ"e"Z#dZ$dZ%dZ&d Z'd Z(dZ)dZ*d Z+d Z,dZ-dZ.dZ/dZ0dZ1dZ2dZ3e4e2Z5e4e3Z6 ddl7Z7dZ8dZ9ddZ:Gddde;ZGd$d%d%e;Z?Gd&d'd'e;Z@d. 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". zAllan Saddi z$Revision: 2025 $NTFSHUT_WR WSGIServer FCGI_MAX_CONNS FCGI_MAX_REQSFCGI_MPXS_CONNSz!BBHHBxz!HB5xz!LB3xz!B7xz /tmp/fcgi.logcCspt|krdSz+ttddd}|dtdd|fWdWdS1s*wYWdSYdS)Nazutf-8)encodingz %sfcgi: %s r)DEBUGopenDEBUGLOGwritetimectime)levelmsgfr0/usr/lib/python3/dist-packages/trac/web/_fcgi.py_debugws &r c@sbeZdZdZddZddZddZdd d Zdd d ZdddZ ddZ ddZ e Z ddZ d S) InputStreamz File-like object representing FastCGI input streams (FCGI_STDIN and FCGI_DATA). Supports the minimum methods required by WSGI spec. cCs2||_|jj|_d|_g|_d|_d|_d|_dS)NrF) _connserverinputStreamShrinkThreshold_shrinkThreshold_buf_bufList_pos_avail_eof)selfconnrrr__init__s  zInputStream.__init__cCsJ|j|jkr!|j|jd|_|j|j8_d|_|jdks#JdSdS)z6Gets rid of already read data (since we can't rewind).Nr)r)r&r'r*r,rrr _shrinkBuffers zInputStream._shrinkBuffercCs|jdS)z(Waits for more data to become available.N)r# process_inputr/rrr _waitForDatazInputStream._waitForDatacCs|j|jkr |jr dS |dks|j|j|kr$|jr|j}n |q |j|} |jr;|jd|j7_g|_|j|j|}||_||S)Nr"Tr)r)r*r+r2r(r'joinr0)r,nnewPosrrrrreads$ zInputStream.readNcCs|j|jkr |jr dS |jr|jd|j7_g|_|jd|j}|dkr5|jr0|j}n |q |d} |durJ|j||krJ|j|}|j|j|}||_||S)Nr"T rr) r)r*r+r(r'r5findr2r0)r,lengthir7r8rrrreadlines, zInputStream.readlinercCsTd}g}|}|r(|||t|7}d|kr!|kr" |S|}|s |S)Nr)r>appendlen)r,sizehinttotallineslinerrr readliness  zInputStream.readlinescCs|SNrr/rrr__iter__szInputStream.__iter__cCs|}|st|SrF)r> StopIteration)r,r8rrr__next__szInputStream.__next__cCs0|sd|_dS|j||jt|7_dSNT)r+r(r?r*r@r,datarrradd_datas  zInputStream.add_datar4rFr)__name__ __module__ __qualname____doc__r.r0r2r9r>rErGrInextrMrrrrr!s      r!csPeZdZdZfddZddZdfdd Zdfd d Zfd d ZZ S)MultiplexedInputStreamz 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. cs$t|t}t||_dSrFsuperr. threadingRLock Condition_lock)r,r-lock __class__rrr.s zMultiplexedInputStream.__init__cCs|jdSrF)r[waitr/rrrr2r3z#MultiplexedInputStream._waitForDatar4c0|jz t|W|jS|jwrF)r[acquirerWr9release)r,r6r]rrr9   zMultiplexedInputStream.readNcr`rF)r[rarWr>rb)r,r<r]rrr>rczMultiplexedInputStream.readlinecs>|jzt||jW|jdS|jwrF)r[rarWrMnotifyrbrKr]rrrMs   zMultiplexedInputStream.add_datarNrF) rPrQrRrSr.r2r9r>rM __classcell__rrr]rrUs  rUc@sBeZdZdZdddZddZddZd d Zd d Zd dZ dS) OutputStreamz 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! FcCs.||_||_||_||_g|_d|_d|_dSNF)r#_req_type _bufferedr( dataWrittenclosed)r,r-reqtypebufferedrrrr.'s zOutputStream.__init__cCspt|}|r6t||jjjt}t|j|jj}||_ |d||_ |j |||d}||8}|sdSdSrF) r@minrhr$maxwriteFCGI_HEADER_LENRecordri requestId contentLength contentDatar# writeRecord)r,rLr<toWriterecrrr_write0s   zOutputStream._writecCs<|jrJ|s dSd|_|jr|j|dS||dSrJ)rlrkrjr(r?rzrKrrrr=s zOutputStream.writecCs"|jrJ|D]}||qdSrF)rlrr,rCrDrrr writelinesJs  zOutputStream.writelinescCs*|jrd|j}g|_||dSdS)Nr")rjr5r(rzrKrrrflushPs  zOutputStream.flushcCsB|js|jr|t|j|jj}|j|d|_dSdSdS)z/Sends end-of-stream notification, if necessary.TN) rlrkr}rsrirhrtr#rwr,ryrrrcloseXs   zOutputStream.closeNF) rPrQrRrSr.rzrr|r}rrrrrrf!s     rfc@0eZdZdZddZddZddZdd Zd S) TeeOutputStreamzq Simple wrapper around two or more output file-like objects that copies written data to all streams. cCs ||_dSrF) _streamList)r, streamListrrrr.e zTeeOutputStream.__init__cCs|jD]}||qdSrF)rr)r,rLrrrrrhs  zTeeOutputStream.writecC|D]}||qdSrFrr{rrrr|l zTeeOutputStream.writelinescCs|jD]}|qdSrF)rr})r,rrrrr}ps  zTeeOutputStream.flushN)rPrQrRrSr.rr|r}rrrrr`s  rc@r) StdoutWrapperzN Wrapper for sys.stdout so we know if data has actually been written. cCs||_d|_dSrg)_filerk)r,stdoutrrrr.x zStdoutWrapper.__init__cCs|rd|_|j|dSrJ)rkrrrKrrrr|szStdoutWrapper.writecCrrFrr{rrrr|rzStdoutWrapper.writelinescCs t|j|SrF)getattrr)r,namerrr __getattr__s zStdoutWrapper.__getattr__N)rPrQrRrSr.rr|rrrrrrts  rcCst||}|d@rtd|||ddd@}|d7}n|d7}t||}|d@rBtd|||ddd@}|d7}n|d7}||||}||7}||||}||7}|||ffS)zv Decodes a name/value pair. The number of bytes decoded as well as the name/value pair are returned. !Lrrir)ordstructunpack)spos nameLength valueLengthrvaluerrr decode_pairs       rcCsht|}|dkr t|}ntd|dB}t|}|dkr$|t|7}n |td|dB7}|||S)zI Encodes a name/value pair. The encoded string is returned. rrl)r@chrrpack)rrrrrrrr encode_pairs  rc@sFeZdZdZeefddZeddZddZ edd Z d d Z d S) rszD A FastCGI Record. Used for encoding/decoding records. cCs(t|_||_||_d|_d|_d|_dS)Nrr")FCGI_VERSION_1versionrnrtru paddingLengthrv)r,rnrtrrrr.s  zRecord.__init__c Csg}d}|rGz||}Wn#tjy0}z|dtjkr+t|gggWYd}~qd}~ww|s4n||t|}||7}||8}|sd||fS)z Attempts to receive length bytes from a socket, blocking if necessary. (Socket may be blocking or non-blocking.) rNr") recvsocketerrorerrnoEAGAINselectr?r@r5)sockr<dataListrecvLenrLedataLenrrr_recvalls(  zRecord._recvallcCsz ||t\}}Wnt|tkrttt|\|_|_|_|_ |_ t dd| |j|j|j f|j rRz |||j \|_ }Wnt||j krRt|j rez |||j WdStdS)z'Read and decode a Record from a socket.Tr z sz1Server._installSignalHandlers..)r;SIGHUPSIGINTSIGTERM_oldSIGs _hupHandler _intHandlerr/rrr_installSignalHandlers s zServer._installSignalHandlerscCs |jD] \}}t||qdSrF)rCr;)r,signumrrrr_restoreSignalHandlersszServer._restoreSignalHandlerscCsd|_d|_dS)NTF) _hupReceivedrr,rGframerrrrDrzServer._hupHandlercCs d|_dSrg)rrJrrrrErzServer._intHandlerrc Cs\tjd}|durttdd|d}|}d|_d|_| |jrzt |ggg|\}}}Wnt j yP}z|dt j krKWYd}~q$d}~ww|rz|\}}Wntj yy}z|dt j t jfvrtWYd}~q$d}~ww|rt|d ks|d|vr|q$||||} t| jd ||js'||||jS) z The main loop. Exits on SIGHUP, SIGINT, SIGTERM. Returns True if SIGHUP was received, False otherwise. FCGI_WEB_SERVER_ADDRSNcSs|SrF)strip)r>rrr%szServer.run..,TFrrr)rrrlistmapsplitr:rrIrFrrrEINTRacceptrrr@rrrrr_mainloopPeriodicrHr) r,timeoutweb_server_addrsrr8rr clientSockrr-rrrrsL     z Server.runcCsdS)zi Called with just about each iteration of the main loop. Meant to be overridden. Nrr/rrrrUSszServer._mainloopPeriodiccCs|jr d|_||_dSdS)z Protected convenience method for subclasses to force an exit. Not really thread-safe, which is why it isn't public. FN)rrI)r,reloadrrr_exitZs z Server._exitcCst|jjd)z Default handler, which just raises an exception. Unless a handler is passed at initialization time, this must be implemented by a subclass. z.handler)NotImplementedErrorr^rPrrrrrcszServer.handlercCs&ddl}|jd|tdS)zt Called by Request if an exception occurs within the handler. May and should be overridden. rNzContent-Type: text/html )cgitbrrhtmlrexc_info)r,rmr\rrrrks  z Server.error)NrNNF)rr)rPrQrRrSrrrr-r%r.r:rrFrHrDrErrUrZrrrrrrrs&  =4 5  rcs6eZdZdZ  d fdd ZddZdd ZZS) rz| FastCGI server that supports the Web Server Gateway Interface. See . NTc sLd|vr|d=tjdi||duri}||_||_||_t|_dS)a  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. rNr)rWr. applicationr multithreadedr allocate_lock _app_lock)r,r_rr`kwr]rrr.ys zWSGIServer.__init__c sjtkr tdfSj}||jd|d<j|d<|jdur$j}nt t jjf}||d<t t  o:t o:|j|d<d|d <t t |d <|d d d vrWd|d<n|dd dkrfd|d<nd|d<||ggdfdddfdd }|js|jzYz0|||zD]}|r|qsd Wtdrn tdrwwWntjy}z|dtjkrтWYd}~nd}~wwW|js|jtdfS|js|jww)zSpecial handler for WSGI.r)rrz wsgi.version wsgi.inputN wsgi.errorszwsgi.multithreadTzwsgi.multiprocessz wsgi.run_onceHTTPSr")yeson1httpszwsgi.url_schemeHTTP_X_FORWARDED_PROTOhttpcst|tus JdsJdsf\}}dd<d}|D]\}}|dkr.d}nq |sMdurMztdkrG|dtt|fWnYd|}|D]}|d |7}qS|d 7}j|j|jdS) Nzwrite() argument must be stringzwrite() before start_response()Fzcontent-lengthTrzContent-Lengthz Status: %s z%s: %s z )rnrlowerr@r?rrr})rLstatusresponseHeadersfoundrrr) headers_sent headers_setrmresultrrrs4        z!WSGIServer.handler..writecs|rz r |dWd}n d}wrJdt|tus Jdt|dks*Jdt|dds6Jd|ddks@Jd t|tusJJd  |D]\}}t|tus[Jd t|tuseJd qM||gdd<S)NrzHeaders already set!zStatus must be a stringrz$Status must be at least 4 charactersrz#Status must begin with 3-digit code z#Status must have a space after codezHeaders must be a listTzHeader names must be stringszHeader values must be strings)rnrr@intrP)rnresponse_headersr^rval)rqrrrrrstart_responses$   z*WSGIServer.handler..start_responserrF)rrFCGI_UNKNOWN_ROLErupdaterrrrrr isinstancerrr`rrm _sanitizeEnvrbrar_hasattrrrrrrrbr)r,rmrrrxrLrr)rqrrrmrsrrrsz               zWSGIServer.handlercCs\d|vrd|d<d|vrd|d<dD]\}}||vr+|dd|jj|f|||<qdS)z7Ensure certain values are present, if required by WSGI. SCRIPT_NAMEr" PATH_INFO))REQUEST_METHODGET) SERVER_NAME localhost) SERVER_PORT80)SERVER_PROTOCOLzHTTP/1.0rez/%s: missing FastCGI param %s required by WSGI! N)rr^rP)r,rrdefaultrrrr|s   zWSGIServer._sanitizeEnvrJ)rPrQrRrSr.rr|rerrr]rrtsq__main__ccsddl}|ddgdVt|D]}d||||fVq|j|d|dd }|jr1d V|jD] }d|j|jfVq4d VdS) z(Probably not the most efficient example.rNz200 OK)z Content-Typez text/htmls\Hello World!

Hello World!

s rdr)fprkeep_blank_valuess's
%s%s
Form data
)cgisortedescape FieldStoragerPrr)rrxrrformfieldrrrtest_apps$      rrO)MrS __author__ __version__rrrr;rrrrrrrXrr dummy_threaddummy_threadingr}r__all__r%rrrrrrrrrrrrrr FCGI_MAXTYPErrrFCGI_AUTHORIZER FCGI_FILTERrrFCGI_OVERLOADEDryrrrrrrrcalcsizerr rrrr objectr!rUrfrrrrrsrrrr rrrPrrrrrrs     v*? m0DVp !