U a6@sdZddlZddlmZddlmZddlmZddl m Z ddl m Z dd l mZejr~dd lmZdd lmZdd lmZGd ddeZGdddeZefeeejddddZGdddZGdddZGdddZGdddZGdddZdS)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 N) TracebackType)urlparse)warn)Headers)is_entity_header) FileWrapper) StartResponse)WSGIApplication)WSGIEnvironmentc@seZdZdZdS) WSGIWarningz Warning class for WSGI warnings.N__name__ __module__ __qualname____doc__rrYC:\Users\vtejo\AppData\Local\Temp\pip-unpacked-wheel-1tps7o9u\werkzeug\middleware\lint.pyr sr c@seZdZdZdS) HTTPWarningz Warning class for HTTP warnings.Nr rrrrr"sr)contextobjneedreturncCs8t||k r4t|d|jdt|jdtdddS)Nz requires z, got . stacklevel)typerrr )rrrrrr check_type&s  rc@sdeZdZejddddZejedddZejeddd Z ej ed d d Z dd d dZ dS) InputStreamNstreamrcCs ||_dSN_streamselfr!rrr__init__0szInputStream.__init__)argsrcGsBt|dkrtdtddnt|dkr6tdtdd|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.rrz2Too many parameters passed to 'wsgi.input.read()'.)lenrr r$readr&r(rrrr+3s  zInputStream.readcGsLt|dkrtdtddn$t|dkr8tdtddntd|jj|S)Nrz_Calls to 'wsgi.input.readline()' without arguments are unsafe. Use 'wsgi.input.read()' instead.rrr)z~'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 TypeErrorr$readliner,rrrr.Ds  zInputStream.readlinercCs<z t|jWStk r6tdtddtdYSXdS)Nz'wsgi.input' is not iterable.rrr)iterr$r-rr r&rrr__iter__Ws  zInputStream.__iter__cCstdtdd|jdS)Nz(The application closed the input stream!rrrr r$closer1rrrr4^szInputStream.close) rrrtBinaryIOr'Anybytesr+r.Iteratorr2r4rrrrr/s rc@s`eZdZejddddZeddddZddd d Zej edd d d Z ddddZ dS) ErrorStreamNr cCs ||_dSr"r#r%rrrr'dszErrorStream.__init__srcCstd|t|j|dS)Nzwsgi.error.write())rstrr$writer&r<rrrr>gs zErrorStream.writer/cCs|jdSr")r$flushr1rrrr@kszErrorStream.flush)seqrcCs|D]}||qdSr")r>)r&rAlinerrr writelinesnszErrorStream.writelinescCstdtdd|jdS)Nz(The application closed the error stream!rrr3r1rrrr4rszErrorStream.close) rrrr5TextIOr'r=r>r@IterablerCr4rrrrr:cs r:c@s@eZdZejegdfejeddddZeddddZ dS) GuardedWriteN)r>chunksrcCs||_||_dSr")_write_chunks)r&r>rGrrrr'xszGuardedWrite.__init__r;cCs*td|t|||jt|dS)Nzwrite())rr8rHrIappendr*r?rrr__call__|s  zGuardedWrite.__call__) rrrr5Callabler8Listintr'rKrrrrrFws$rFc@sneZdZejeejeefej eddddZ ddddZ eddd Z ddd d Z ddd d ZdS)GuardedIteratorN)iterator headers_setrGrcCs(||_t|j|_d|_||_||_dS)NF) _iteratorr0__next___nextclosedrQrG)r&rPrQrGrrrr's  zGuardedIterator.__init__r/cCs|Sr"rr1rrrr2szGuardedIterator.__iter__cCsP|jrtdtdd|}|js0tdtddtd|t|jt ||S)Nz Iterated over closed 'app_iter'.rrz8The application returned before it started the response.zapplication iterator items) rUrr rTrQrr8rGrJr*)r&rvrrrrSs zGuardedIterator.__next__cCsd|_t|jdr|j|jr|j\}}t|j}|jdtd}|dkr|D]2\}}| }|dkrPt |rPt d|dt qP|rt d t nfd |krd ksn|d kr|d krt |dt |rt |dt n|dk r||krt dt dS)NTr4zcontent-length)ri0)expireszcontent-locationzEntity header z found in 304 response.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.)rUhasattrrRr4rQsumrGgetrNlowerrrrr )r& status_codeheadersZ bytes_sentcontent_lengthkey_valuerrrr4s@        zGuardedIterator.closecCs.|js*ztdtWntk r(YnXdS)Nz4Iterator was garbage collected before it was closed.)rUrr Exceptionr1rrr__del__szGuardedIterator.__del__)rrrr5rEr8TuplerNrrMr'r2rSr4rerrrrrOs  %rOc@seZdZdZdddddZdddd d Zeejej eefej ej ej e e e fej eefd d d ZeddddZejeddddZejejejedddZdS)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) r N)apprcCs ||_dSr")rh)r&rhrrrr'szLintMiddleware.__init__r )environrcCst|tk rtdtdddD]"}||krtd|dtddq|dd kr\td tdd|d d }|d d }|r|ddkrtd|tdd|r|ddkrtd|tdddS)Nz/WSGI environment is not a standard Python dict.r) REQUEST_METHODZ SERVER_NAMEZ SERVER_PORT wsgi.version wsgi.input wsgi.errorszwsgi.multithreadzwsgi.multiprocessz wsgi.run_oncezRequired environment key z not foundrrl)r)rz"Environ is not a WSGI 1.0 environ.Z SCRIPT_NAMEZ PATH_INFOr/z+'SCRIPT_NAME' does not start with a slash: z)'PATH_INFO' does not start with a slash: )rdictrr r])r&rirb script_nameZ path_inforrr check_environs:      zLintMiddleware.check_environ)statusr`exc_inforc Cs\td|t|ddd}t|dks0|s>tdtddt|dksV|ddkrltd |d tddt|}|d krtd tddt|t k rtd tdd|D]t}t|t k st|dkrtdtdd|\}}t|tk st|tk rtdtdd| dkrtdtddq|dk rBt |t sBtdtddt |}||||fS)Nrtr)rrz!Status code must be three digits.rrj zInvalid value for status zJ. Valid status strings are three digits, a space and a status explanation.rXzStatus 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.)rr=splitr*isdigitrr rNrlisttupler^ isinstancer check_headers) r&rtr`ruZstatus_code_strr_itemnamevaluerrrcheck_start_responsesH     z#LintMiddleware.check_start_response)r`rcCs|d}|dk rt|dr@|dr4tdtdd|dd}|dd|d dkrdd kstntd tdd|d }|dk rt|jstd tdddS)Netag)zW/w/rz)Weak etag indicator should be upper case.rjrrr)"zUnquoted etag emitted.locationz+Absolute URLs required for location header.)r] startswithrrrnetloc)r&r`rrrrrr|Ns(    &  zLintMiddleware.check_headers)app_iterrcCst|trtdtdddS)NzThe application returned a bytestring. The response will send one character at a time to the client, which will kill performance. Return a list or iterable instead.rr)r{r8rr )r&rrrrcheck_iteratoris  zLintMiddleware.check_iteratorr(kwargsrcst|dkrtdtdd|r,tdtdd|d}|d|t|d|d<t|d|d<t|d <ggtjtjtj t gdfd fd d } |t d |} |t|t tjttfS)NrzA WSGI app takes two arguments.rz+A WSGI app does not take keyword arguments.rr)rmrnzwsgi.file_wrapperrcst|dkr&tdt|dtdd|r4tdt|d}|d}t|d krX|dnd}|||dd<t|||S) N>rrzInvalid number of arguments: z, expected 2 or 3.rrz1'start_response' does not take keyword arguments.rr)r)r*rr rrF)r(rrtr`rurGrQr&Zstart_responserrchecking_start_responses  z8LintMiddleware.__call__..checking_start_responser )r*rr rsrr:rr5r7rLr8rhcastrrOrfrNr)r&r(rrirrrrrrKss6   zLintMiddleware.__call__)rrrrr'rsr=r5rMrfOptionalType BaseExceptionrrNrrr|rEr8rr7rKrrrrrgs. 6 rg) rtypingr5typesr urllib.parserwarningsrZdatastructuresrhttprZwsgir TYPE_CHECKINGZ_typeshed.wsgir r r Warningr rr=objectrrrr:rFrOrgrrrrs&          4 P