4V=j8^dZddlmZddlZddlmZddlmZddl m Z ddl m Z dd l mZdd lmZejrdd lmZdd lmZdd lmZGddeZGddeZefd%dZGddZGddZGdd ZGd!d"ZGd#d$ZdS)&a WSGI Protocol Linter ==================== This module provides a middleware that performs sanity checks on the behavior of the WSGI server and application. It checks that the :pep:`3333` WSGI spec is properly implemented. It also warns on some common HTTP errors such as non-empty responses for 304 status codes. .. autoclass:: LintMiddleware :copyright: 2007 Pallets :license: BSD-3-Clause ) annotationsN) TracebackType)urlparse)warn)Headers)is_entity_header) FileWrapper) StartResponse)WSGIApplication)WSGIEnvironmentceZdZdZdS) WSGIWarningz Warning class for WSGI warnings.N__name__ __module__ __qualname____doc__FC:\PYTHON\_runtimes\venv\Lib\site-packages\werkzeug/middleware/lint.pyrr!****rrceZdZdZdS) HTTPWarningz Warning class for HTTP warnings.Nrrrrrr%rrrcontextstrobjobjectneedtypereturnNonec t||ur9t|d|jdt|jdtddSdS)Nz requires z, got . stacklevel)r rrr)rrrs r check_typer()si Cyy  R RDM R R499;M R R R       rc6eZdZddZdd Zdd Zdd Zdd ZdS) InputStreamstream t.IO[bytes]r!r"c||_dSN_streamselfr+s r__init__zInputStream.__init__3  rargst.Anybytesct|dkrtdtdn*t|dkrtdtd|jj|S)NrzWSGI does not guarantee an EOF marker on the input stream, thus making calls to 'wsgi.input.read()' unsafe. Conforming servers may never return from this call.rr&z2Too many parameters passed to 'wsgi.input.read()'.)lenrrr0readr2r5s rr;zInputStream.read6s t99>> *      YY!^^ D     !t| $''rct|dkrtdtdn:t|dkrtdtdntd|jj|S)Nrz_Calls to 'wsgi.input.readline()' without arguments are unsafe. Use 'wsgi.input.read()' instead.rr&r9z~'wsgi.input.readline()' was called with a size hint. WSGI does not support this, although it's available on all major servers.z5Too many arguments passed to 'wsgi.input.readline()'.)r:rr TypeErrorr0readliner<s rr?zInputStream.readlineGs t99>> 0       YY!^^ O      STT T$t|$d++rt.Iterator[bytes]c t|jS#t$r)tdtdtdcYSwxYw)Nz'wsgi.input' is not iterable.rr&r)iterr0r>rrr2s r__iter__zInputStream.__iter__ZsW  %% %    0+! L L L L88OOO s0A A cftdtd|jdS)Nz(The application closed the input stream!rr&rrr0closerCs rrGzInputStream.closea3 7QRSSSS rN)r+r,r!r")r5r6r!r7)r!r@r!r")rrrr3r;r?rDrGrrrr*r*2sx((((",,,,&rr*c6eZdZddZddZdd Zdd Zdd ZdS) ErrorStreamr+ t.IO[str]r!r"c||_dSr.r/r1s rr3zErrorStream.__init__gr4rsrcftd|t|j|dS)Nzwsgi.error.write())r(rr0writer2rNs rrPzErrorStream.writejs1'C000 1rc8|jdSr.)r0flushrCs rrSzErrorStream.flushns rseqt.Iterable[str]c:|D]}||dSr.)rP)r2rTlines r writelineszErrorStream.writelinesqs0  D JJt      rcftdtd|jdS)Nz(The application closed the error stream!rr&rFrCs rrGzErrorStream.closeurHrN)r+rLr!r")rNrr!r"rI)rTrUr!r")rrrr3rPrSrXrGrrrrKrKfsxrrKceZdZd dZd d Zd S) GuardedWriterPt.Callable[[bytes], object]chunks list[int]r!r"c"||_||_dSr.)_write_chunks)r2rPr]s rr3zGuardedWrite.__init__{s  rrNr7ctd|t|||jt |dS)Nzwrite())r(r7r`raappendr:rQs r__call__zGuardedWrite.__call__sE9a''' A CFF#####rN)rPr\r]r^r!r")rNr7r!r")rrrr3rdrrrr[r[zs<$$$$$$rr[c6eZdZdd Zdd Zdd Zdd ZddZdS)GuardedIteratoriteratort.Iterable[bytes] headers_settuple[int, Headers]r]r^r!r"cp||_t|j|_d|_||_||_dS)NF) _iteratorrB__next___nextclosedrir])r2rgrir]s rr3zGuardedIterator.__init__s5 "(^^,  & rc|Sr.rrCs rrDzGuardedIterator.__iter__s rr7c |jrtdtd|}|jstdtdt d|t |jt||S)Nz Iterated over closed 'app_iter'.rr&z8The application returned before it started the response.zapplication iterator items) rorrrnrir(r7r]rcr:)r2rvs rrmzGuardedIterator.__next__s ; P 3[Q O O O O ZZ\\  J     /U;;; 3r77### rcd|_t|jdr|j|jr|j\}}t |j}|dt}|dkrg|D]G\}}| }|dvr*t|rtd|dtd H|rtd td dSdSd |cxkrd ksn|dkr@|dkrt|dtd |rt|dtd dSdS|!||krtdtd dSdSdSdS)NTrGzcontent-length)r i0)expireszcontent-locationzEntity header z found in 304 response.rr&z#304 responses must not have a body.drz- responses must have an empty content length.z responses must not have a body.zGContent-Length and the number of bytes sent to the client do not match.)rohasattrrlrGrisumr]getintlowerr rrr)r2 status_codeheaders bytes_sentcontent_lengthkey_values rrGzGuardedIterator.closes$ 4>7 + + # N " " "  ) #'#3 KT[))J$[[)9[DDNc!!#*  KC))++C"AAAFVGGAKSKKK''( =##$  ))))c))))[C-?-?!Q&&&UUU##$ &HHH##$  +*0L0L, I) ) F,+0L0Lrcj|js+ tdtddS#t$rYdSwxYwdS)Nz4Iterator was garbage collected before it was closed.rr&)rorr ExceptionrCs r__del__zGuardedIterator.__del__si{  J        s " 00N)rgrhrirjr]r^r!r")r!rf)r!r7rI)rrrr3rDrmrGrrrrrfrfsy    "////b      rrfcBeZdZdZddZdd ZddZddZd dZd!dZ dS)"LintMiddlewareaWarns about common errors in the WSGI and HTTP behavior of the server and wrapped application. Some of the issues it checks are: - invalid status codes - non-bytes sent to the WSGI server - strings returned from the WSGI application - non-empty conditional responses - unquoted etags - relative URLs in the Location header - unsafe calls to wsgi.input - unclosed iterators Error information is emitted using the :mod:`warnings` module. :param app: The WSGI application to wrap. .. code-block:: python from werkzeug.middleware.lint import LintMiddleware app = LintMiddleware(app) appr r!r"c||_dSr.)r)r2rs rr3zLintMiddleware.__init__s renvironr ct|turtdtddD]!}||vrtd|dtd"|dd krtd td|d d }|d d }|r&|ddkrtd|td|r(|ddkrtd|tddSdSdS)Nz/WSGI environment is not a standard Python dict.r&) REQUEST_METHOD SERVER_NAME SERVER_PORT wsgi.version wsgi.input wsgi.errorszwsgi.multithreadzwsgi.multiprocessz wsgi.run_oncezRequired environment key z not foundr%r)r9rz"Environ is not a WSGI 1.0 environ. SCRIPT_NAME PATH_INFOr/z+'SCRIPT_NAME' does not start with a slash: z)'PATH_INFO' does not start with a slash: )r dictrrrz)r2rr script_name path_infos r check_environzLintMiddleware.check_environsc == $ $ A        C'!!AAAA  > "f , , 5{q Q Q Q Qkk-44 KK R00  ;q>S00 MkMM      1,, IIII        ,,rstatusrr~list[tuple[str, str]]exc_info?None | tuple[type[BaseException], BaseException, TracebackType]rjc,td|t|ddd}t|dks|st dt dt|dks |ddkrt d |d t dt|}|d krt d t dt|turt d t d|D]}t|tust|dkrt dt d|\}}t|tust|turt dt d| dkrt dt d|,t|tst dt dt|} || || fS)Nrr9rr%z!Status code must be three digits.r&r zInvalid value for status zJ. Valid status strings are three digits, a space and a status explanation.ruzStatus code < 100 detected.zHeader list is not a list.rz#Header items must be 2-item tuples.z'Header keys and values must be strings.zFThe status header is not supported due to conflicts with the CGI spec.zInvalid value for exc_info.)r(rsplitr: isdecimalrrr{r listtupler| isinstancer check_headers) r2rr~rstatus_code_strr}itemnamevalue headers_objs rcheck_start_responsez#LintMiddleware.check_start_response)s. 8VS))) ,,tQ//2   1 $ $O,E,E,G,G $ 4ka P P P P v;;??fQi3.. =F===     /**    .  J J J J == $ $ -{q I I I I  DDzz&&#d))q..:KTUVVVVKD%Dzz$$U 3(>(>={WXzz||x''4    8U(C(C  .  J J J Jg&&  ;'''K''rrc|d}||dr6|drtdtd|dd}|dd|d dcxkrd ksntd td|d }|-t |jstd tddSdSdS)Netag)zW/w/rz)Weak etag indicator should be upper case.rr&rr9"zUnquoted etag emitted.locationz+Absolute URLs required for location header.)rz startswithrrrnetloc)r2r~rrs rrzLintMiddleware.check_headers]s{{6""  |,, ??4((C##$ ABBx!HRSS 0000S0000-{qIIII;;z**  H%%, A    rapp_iterrhcbt|trtdtddSdS)NzThe application returned a string. The response will send one character at a time to the client, which will kill performance. Return a list or iterable instead.r%r&)rrrr)r2rs rcheck_iteratorzLintMiddleware.check_iteratorxsL h $ $  6         rr5r6kwargscZt|dkrtdtd|rtdtd|d}|d|t |d|d<t |d|d<t |d <ggdfd }|tj d|} |t|tj tttfS)NrzA WSGI app takes two arguments.r&z+A WSGI app does not take keyword arguments.rr9rrzwsgi.file_wrapperr5r6rr!t.Callable[[bytes], None]cpt|dvr(tdt|dtd|rtdtd|d}|d}t|d kr|dnd}|||dd<t |||S) N>rr%zInvalid number of arguments: z, expected 2 or 3.rr&z1'start_response' does not take keyword arguments.rr9r%)r:rrrr[) r5rrr~rr]rir2start_responses rchecking_start_responsez8LintMiddleware.__call__..checking_start_responses4yy&&QCIIQQQ   G  q'F-1!WGt99>>Qt "66vwQQKNvw I I6RR Rrr )r5r6rr6r!r)r:rrrr*rKr rtcastrrfrr{r) r2r5rrrrr]rirs ` @@@rrdzLintMiddleware.__call__sY t99>> 2KA N N N N   ={WX    $(7(,Q 7### +GL,A B B !,W]-C!D!D (3#$#%  S S S S S S S S S488GQVO=T%U%UVV H%%% afU3<0+>>   rN)rr r!r")rr r!r")rrr~rrrr!rj)r~rr!r")rrhr!r")r5r6rr6r!rh) rrrrr3rrrrrdrrrrrs,****X2(2(2(2(h65 5 5 5 5 5 rr)rrrrrr r!r") r __future__rtypingrtypesr urllib.parserwarningsrdatastructuresrhttpr wsgir TYPE_CHECKING_typeshed.wsgir r r Warningrrrr(r*rKr[rfrrrrrs3  #"""""!!!!!!$$$$$$######?/,,,,,,............+++++'++++++++'+++8;     11111111h($$$$$$$$[[[[[[[[|T T T T T T T T T T r