
    %h8                    J   S r SSKJr  SSKrSSKJr  SSKJr  SSK	J
r
  SSKJr  SS	KJr  SS
KJr  \R"                  (       a  SSKJr  SSKJr  SSKJr   " S S\5      r " S S\5      r\4SS jjr " S S5      r " S S5      r " S S5      r " S S5      r " S S5      rg)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)WSGIEnvironmentc                      \ rS rSrSrSrg)WSGIWarning!   z Warning class for WSGI warnings. N__name__
__module____qualname____firstlineno____doc____static_attributes__r       P/var/www/auris/envauris/lib/python3.13/site-packages/werkzeug/middleware/lint.pyr   r   !       *r   r   c                      \ rS rSrSrSrg)HTTPWarning%   z Warning class for HTTP warnings.r   Nr   r   r   r   r   r   %   r   r   r   c           	         [        U5      ULa9  [        U < SUR                  < S[        U5      R                  < S3[        SS9  g g )Nz
 requires z, got .   
stacklevel)typer   r   r   )contextobjneeds      r   
check_typer(   )   sH    CykDMM#4F49;M;M:PPQR	
 r   c                  F    \ rS rSrS	S jrS
S jrS
S jrSS jrSS jrSr	g)InputStream2   c                    Xl         g N_streamselfstreams     r   __init__InputStream.__init__3       r   c                    [        U5      S:X  a  [        S[        SS9  O[        U5      S:w  a  [        S[        SS9  U R                  R                  " U6 $ )Nr   zWSGI 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.r   r"      z2Too many parameters passed to 'wsgi.input.read()'.)lenr   r   r/   readr1   argss     r   r9   InputStream.read6   sW    t9>*  Y!^D
 ||  $''r   c                    [        U5      S:X  a  [        S[        SS9  O*[        U5      S:X  a  [        S[        SS9  O[        S5      eU R                  R
                  " U6 $ )Nr   z_Calls to 'wsgi.input.readline()' without arguments are unsafe. Use 'wsgi.input.read()' instead.r   r"   r7   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()'.)r8   r   r   	TypeErrorr/   readliner:   s     r   r?   InputStream.readlineG   sd    t9>0	 Y!^O	 STT||$$d++r   c                     [        U R                  5      $ ! [         a    [        S[        SS9  [        S5      s $ f = f)Nz'wsgi.input' is not iterable.r   r"   r   )iterr/   r>   r   r   r1   s    r   __iter__InputStream.__iter__Z   s;    	%% 	0+!L8O	s    $>>c                V    [        S[        SS9  U R                  R                  5         g )Nz(The application closed the input stream!r   r"   r   r   r/   closerC   s    r   rH   InputStream.closea        7QRSr   r.   N)r2   zt.IO[bytes]returnNone)r;   t.AnyrK   bytes)rK   zt.Iterator[bytes]rK   rL   )
r   r   r   r   r3   r9   r?   rD   rH   r   r   r   r   r*   r*   2   s    (",&r   r*   c                  F    \ rS rSrS	S jrS
S jrSS jrSS jrSS jrSr	g)ErrorStreamf   c                    Xl         g r-   r.   r0   s     r   r3   ErrorStream.__init__g   r5   r   c                \    [        SU[        5        U R                  R                  U5        g )Nzwsgi.error.write())r(   strr/   writer1   ss     r   rW   ErrorStream.writej   s!    'C01r   c                8    U R                   R                  5         g r-   )r/   flushrC   s    r   r\   ErrorStream.flushn   s    r   c                8    U H  nU R                  U5        M     g r-   )rW   )r1   seqlines      r   
writelinesErrorStream.writelinesq   s    DJJt r   c                V    [        S[        SS9  U R                  R                  5         g )Nz(The application closed the error stream!r   r"   rG   rC   s    r   rH   ErrorStream.closeu   rJ   r   r.   N)r2   z	t.IO[str]rK   rL   )rY   rV   rK   rL   rO   )r_   zt.Iterable[str]rK   rL   )
r   r   r   r   r3   rW   r\   ra   rH   r   r   r   r   rQ   rQ   f   s    r   rQ   c                  (    \ rS rSrSS jrSS jrSrg)GuardedWritez   c                    Xl         X l        g r-   )_write_chunks)r1   rW   chunkss      r   r3   GuardedWrite.__init__{   s    r   c                    [        SU[        5        U R                  U5        U R                  R	                  [        U5      5        g )Nzwrite())r(   rN   ri   rj   appendr8   rX   s     r   __call__GuardedWrite.__call__   s/    9a'ACF#r   )rj   ri   N)rW   zt.Callable[[bytes], object]rk   	list[int]rK   rL   )rY   rN   rK   rL   )r   r   r   r   r3   ro   r   r   r   r   rf   rf   z   s    $r   rf   c                  V    \ rS rSr        S	S jrS
S jrSS jrSS jrSS jrSr	g)GuardedIterator   c                j    Xl         [        U5      R                  U l        SU l        X l        X0l        g )NF)	_iteratorrB   __next___nextclosedheaders_setrk   )r1   iteratorrz   rk   s       r   r3   GuardedIterator.__init__   s,     "(^,,
&r   c                    U $ r-   r   rC   s    r   rD   GuardedIterator.__iter__   s    r   c                   U R                   (       a  [        S[        SS9  U R                  5       nU R                  (       d  [        S[        SS9  [        SU[        5        U R                  R                  [        U5      5        U$ )Nz Iterated over closed 'app_iter'.r   r"   z8The application returned before it started the response.zapplication iterator items)
ry   r   r   rx   rz   r(   rN   rk   rn   r8   )r1   rvs     r   rw   GuardedIterator.__next__   se    ;;3[QOZZ\J 	/U;3r7#	r   c                   SU l         [        U R                  S5      (       a  U R                  R                  5         U R                  (       Ga   U R                  u  p[        U R                  5      nUR                  S[        S9nUS:X  aa  U HC  u  pVUR                  5       nUS;  d  M  [        U5      (       d  M/  [        SU< S3[        S	S
9  ME     U(       a  [        S[        S	S
9  g g SUs=::  a  S:  d  O  US:X  a3  US:w  a  [        U S3[        S	S
9  U(       a  [        U S3[        S	S
9  g g Ub  XC:w  a  [        S[        S	S
9  g g g g )NTrH   zcontent-length)r$   i0  )expireszcontent-locationzEntity header z found in 304 response.r   r"   z#304 responses must not have a body.d         r   z- 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.)ry   hasattrrv   rH   rz   sumrk   getintlowerr	   r   r   r   )r1   status_codeheaders
bytes_sentcontent_lengthkey_values          r   rH   GuardedIterator.close   s`   4>>7++NN  "#'#3#3 KT[[)J$[[)9[DNc!#*KC))+C"AAFVG G ,SG3JK''( $+ =##$  )c)[C-?!Q&&-'TU##$
 &-'GH##$   +0L, 	 1M+G r   c                h    U R                   (       d   [        S[        SS9  g g ! [         a     g f = f)Nz4Iterator was garbage collected before it was closed.r   r"   )ry   r   r   	ExceptionrC   s    r   __del__GuardedIterator.__del__   s8    {{J    s   $ 
11)rv   rx   rk   ry   rz   N)r{   t.Iterable[bytes]rz   tuple[int, Headers]rk   rq   rK   rL   )rK   rs   )rK   rN   rO   )
r   r   r   r   r3   rD   rw   rH   r   r   r   r   r   rs   rs      sB    
#
 )
 	

 

"/b	r   rs   c                  d    \ rS rSrSrSS jrSS jr        SS jrSS jrSS jr	SS jr
S	rg
)LintMiddleware   a`  Warns 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)
c                    Xl         g r-   app)r1   r   s     r   r3   LintMiddleware.__init__   s    r   c                   [        U5      [        La  [        S[        SS9  S H  nX!;  d  M
  [        SU< S3[        SS9  M      US   S	:w  a  [        S
[        SS9  UR	                  SS5      nUR	                  SS5      nU(       a  US   S:w  a  [        SU< 3[        SS9  U(       a  US   S:w  a  [        SU< 3[        SS9  g g g )Nz/WSGI environment is not a standard Python dict.   r"   )	REQUEST_METHODSERVER_NAMESERVER_PORTwsgi.version
wsgi.inputwsgi.errorszwsgi.multithreadzwsgi.multiprocesszwsgi.run_oncezRequired environment key z
 not foundr!   r   )r7   r   z"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$   dictr   r   r   )r1   environr   script_name	path_infos        r   check_environLintMiddleware.check_environ   s    =$A


C !/wjA 

" >"f,5{qQkk-4KKR0	;q>S0=k_M 1,;I=I -9r   c                D   [        SU[        5        UR                  S S5      S   n[        U5      S:w  d  UR	                  5       (       d  [        S[        SS9  [        U5      S:  d	  US   S:w  a  [        S	U< S
3[        SS9  [        U5      nUS:  a  [        S[        SS9  [        U5      [        La  [        S[        SS9  U H  n[        U5      [        Ld  [        U5      S:w  a  [        S[        SS9  Uu  px[        U5      [        Ld  [        U5      [        La  [        S[        SS9  UR                  5       S:X  d  M  [        S[        SS9  M     Ub$  [        U[        5      (       d  [        S[        SS9  [        U5      n	U R                  U	5        XY4$ )Nstatusr7   r   r!   z!Status code must be three digits.r"   r    zInvalid value for status zJ. Valid status strings are three digits, a space and a status explanation.r   zStatus code < 100 detected.zHeader list is not a list.r   z#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.zInvalid value for exc_info.)r(   rV   splitr8   	isdecimalr   r   r   r$   listtupler   
isinstancer   check_headers)
r1   r   r   exc_infostatus_code_strr   itemnamevalueheaders_objs
             r   check_start_response#LintMiddleware.check_start_response)  s}    	8VS) ,,tQ/21$O,E,E,G,G4kaPv;?fQi3.+F: 6= =	 /*.J=$-{qIDDz&#d)q.:KTUVKDDz$U3(>={WX zz|x'4 	   
8U(C(C.Jg&;'''r   c                r   UR                  S5      nUbd  UR                  S5      (       a*  UR                  S5      (       a  [        S[        SS9  USS  nUS S US	S  s=:X  a  S
:X  d  O  [        S[        SS9  UR                  S5      nUb+  [	        U5      R
                  (       d  [        S[        SS9  g g g )Netag)zW/w/r   z)Weak etag indicator should be upper case.r   r"   r   r7   "zUnquoted etag emitted.locationz+Absolute URLs required for location header.)r   
startswithr   r   r   netloc)r1   r   r   r   s       r   r   LintMiddleware.check_headers]  s    {{6"|,,??4((C##$ ABx!HRS	0S0-{qI;;z*H%,,A  -  r   c                N    [        U[        5      (       a  [        S[        SS9  g g )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"   )r   rV   r   r   )r1   app_iters     r   check_iteratorLintMiddleware.check_iteratorx  s)    h$$6  %r   c                  ^ ^^^ [        U5      S:w  a  [        S[        SS9  U(       a  [        S[        SS9  US   nUS   mT R                  U5        [	        US   5      US'   [        US   5      US'   [        US	'   / m/ m      SUUU U4S
 jjnT R                  U[        R                  " SU5      5      nT R                  U5        [        U[        R                  " [        [        [        4   T5      T5      $ )Nr   zA WSGI app takes two arguments.r"   z+A WSGI app does not take keyword arguments.r   r7   r   r   zwsgi.file_wrapperc                   > [        U 5      S;  a  [        S[        U 5       S3[        SS9  U(       a  [        S[        SS9  U S   nU S   n[        U 5      S	:X  a  U S   OS nTR                  X#U5      TS S & [	        T" X#U5      T5      $ )
N>   r   r!   zInvalid number of arguments: z, expected 2 or 3.r   r"   z1'start_response' does not take keyword arguments.r   r7   r!   )r8   r   r   r   rf   )	r;   kwargsr   r   r   rk   rz   r1   start_responses	        r   checking_start_response8LintMiddleware.__call__.<locals>.checking_start_response  s     4y&3CI;>PQ  G  q'F-1!WG t9>Qt  "66vQKNv I6RRr   r   )r;   rM   r   rM   rK   zt.Callable[[bytes], None])r8   r   r   r   r*   rQ   r
   r   tcastr   rs   r   r   r   )	r1   r;   r   r   r   r   rk   rz   r   s	   `     @@@r   ro   LintMiddleware.__call__  s
   t9>2KAN={WX $(7(,Q7# +GL,A B!,W]-C!D (3#$#%	S	S$)	S&	S 	S4 88GQVVO=T%UVH%affU3<0+>
 	
r   r   N)r   r   rK   rL   )r   r   rK   rL   )r   rV   r   zlist[tuple[str, str]]r   z?None | tuple[type[BaseException], BaseException, TracebackType]rK   r   )r   r   rK   rL   )r   r   rK   rL   )r;   rM   r   rM   rK   r   )r   r   r   r   r   r3   r   r   r   r   ro   r   r   r   r   r   r      sN    ,*X2(2( '2( T	2(
 
2(h65
r   r   )r%   rV   r&   objectr'   r$   rK   rL   ) r   
__future__r   typingr   typesr   urllib.parser   warningsr   datastructuresr   httpr	   wsgir
   TYPE_CHECKING_typeshed.wsgir   r   r   Warningr   r   rV   r(   r*   rQ   rf   rs   r   r   r   r   <module>r      s    #   !  $ # ??,..+' ++' + 8; 
1 1h ($ $[ [|T
 T
r   