
    d6              	       l   d Z ddlZddlmZ ddlmZ ddlmZ ddl	m
Z
 ddlmZ dd	lmZ ej        rdd
lmZ ddlmZ ddlmZ  G d de          Z G d de          Zefdededej        ddfdZ G d d          Z G d d          Z G d d          Z G d d          Z G d d          ZdS ) 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                       e Zd ZdZdS )WSGIWarningz Warning class for WSGI warnings.N__name__
__module____qualname____doc__     8lib/python3.11/site-packages/werkzeug/middleware/lint.pyr   r              ****r   r   c                       e Zd ZdZdS )HTTPWarningz Warning class for HTTP warnings.Nr   r   r   r   r   r   "   r   r   r   contextobjneedreturnc           	          t          |          |ur9t          | d|j        dt          |          j        dt          d           d S d S )Nz
 requires z, got .   
stacklevel)typer   r   r   )r   r   r   s      r   
check_typer$   &   sm    Cyy 
RRDMRR499;MRRR	
 	
 	
 	
 	
 	

 
r   c                       e Zd Zdej        e         ddfdZdej        defdZdej        defdZ	dej
        e         fdZd
d	ZdS )InputStreamstreamr   Nc                     || _         d S N_streamselfr'   s     r   __init__zInputStream.__init__0       r   argsc                     t          |          dk    rt          dt          d           n*t          |          dk    rt          dt          d            | j        j        | S )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r-   r0   s     r   r4   zInputStream.read3   s    t99> 	*      YY!^ 	D   
 !t| $''r   c                     t          |          dk    rt          dt          d           n:t          |          dk    rt          dt          d           nt          d           | j        j        | S )Nr   z_Calls to 'wsgi.input.readline()' without arguments are unsafe. Use 'wsgi.input.read()' instead.r   r!   r2   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()'.)r3   r   r   	TypeErrorr+   readliner5   s     r   r8   zInputStream.readlineD   s    t99> 	U0	     YY!^ 	UO	     STTT$t|$d++r   c                     	 t          | j                  S # t          $ r) t          dt          d           t          d          cY S w xY w)Nz'wsgi.input' is not iterable.r   r!   r   )iterr+   r7   r   r   r-   s    r   __iter__zInputStream.__iter__W   sW    	%%% 	 	 	0+!LLLL88OOO	s    0A	A	c                 f    t          dt          d           | j                                         d S )Nz(The application closed the input stream!r   r!   r   r   r+   closer;   s    r   r?   zInputStream.close^   3    7QRSSSSr   r   N)r   r   r   tIObytesr.   Anyr4   r8   Iteratorr<   r?   r   r   r   r&   r&   /   s        qtE{ t    (!% (E ( ( ( (",ae , , , , ,&!*U+         r   r&   c                   z    e Zd Zdej        e         ddfdZdeddfdZddZdej	        e         ddfd	Z
dd
ZdS )ErrorStreamr'   r   Nc                     || _         d S r)   r*   r,   s     r   r.   zErrorStream.__init__d   r/   r   sc                 f    t          d|t                     | j                            |           d S )Nzwsgi.error.write())r$   strr+   writer-   rJ   s     r   rM   zErrorStream.writeg   s1    'C0001r   c                 8    | j                                          d S r)   )r+   flushr;   s    r   rP   zErrorStream.flushk   s    r   seqc                 :    |D ]}|                      |           d S r)   )rM   )r-   rQ   lines      r   
writelineszErrorStream.writelinesn   s0     	 	DJJt	 	r   c                 f    t          dt          d           | j                                         d S )Nz(The application closed the error stream!r   r!   r>   r;   s    r   r?   zErrorStream.closer   r@   r   rA   )r   r   r   rB   rC   rL   r.   rM   rP   IterablerT   r?   r   r   r   rH   rH   c   s        qtCy T    s t       ajo $         r   rH   c                   d    e Zd Zdej        egef         dej        e         ddfdZ	deddfdZ
dS )GuardedWriterM   chunksr   Nc                 "    || _         || _        d S r)   )_write_chunks)r-   rM   rY   s      r   r.   zGuardedWrite.__init__x   s    r   rJ   c                     t          d|t                     |                     |           | j                            t          |                     d S )Nzwrite())r$   rD   r[   r\   appendr3   rN   s     r   __call__zGuardedWrite.__call__|   sE    9a'''ACFF#####r   )r   r   r   rB   CallablerD   objectListintr.   r_   r   r   r   rX   rX   w   ss        aj%&9 16#; SW    $% $D $ $ $ $ $ $r   rX   c                       e Zd Zdej        e         dej        eef         dej	        e         ddfdZ
ddZdefdZdd	Zdd
ZdS )GuardedIteratoriteratorheaders_setrY   r   Nc                 p    || _         t          |          j        | _        d| _        || _        || _        d S )NF)	_iteratorr:   __next___nextclosedrg   rY   )r-   rf   rg   rY   s       r   r.   zGuardedIterator.__init__   s5     "(^^,
&r   c                     | S r)   r   r;   s    r   r<   zGuardedIterator.__iter__   s    r   c                     | j         rt          dt          d           |                                 }| j        st          dt          d           t          d|t                     | j                            t          |                     |S )Nz Iterated over closed 'app_iter'.r   r!   z8The application returned before it started the response.zapplication iterator items)
rl   r   r   rk   rg   r$   rD   rY   r^   r3   )r-   rvs     r   rj   zGuardedIterator.__next__   s    ; 	P3[QOOOOZZ\\ 	J    	/U;;;3r77###	r   c                    d| _         t          | j        d          r| j                                         | j        r| j        \  }}t          | j                  }|                    dt                    }|dk    rc|D ]E\  }}|	                                }|dvr(t          |          rt          d|dt                     F|rt          d	t                     d S d S d
|cxk    rdk     sn |dk    r<|dk    rt          | dt                     |rt          | dt                     d S d S |||k    rt          dt                     d S d S d S d S )NTr?   zcontent-length)r#   i0  )expireszcontent-locationzEntity header z found in 304 response.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.)rl   hasattrri   r?   rg   sumrY   getrc   lowerr   r   r   r   )r-   status_codeheaders
bytes_sentcontent_lengthkey_values          r   r?   zGuardedIterator.close   s   4>7++ 	#N  """ 	#'#3 KT[))J$[[)9[DDNc! #*  KC))++C"AA FVG G  KSKKK[    M>LLLLLM M    c    [C-? !Q& &UUU#    XKIII;WWWWWX X *0L ,    3	 	0   r   c                 f    | j         s)	 t          dt                     d S # t          $ r Y d S w xY wd S )Nz4Iterator was garbage collected before it was closed.)rl   r   r   	Exceptionr;   s    r   __del__zGuardedIterator.__del__   s`    { 	JK        	 	s     
..)r   re   rA   )r   r   r   rB   rV   rD   Tuplerc   r   rb   r.   r<   rj   r?   r   r   r   r   re   re      s        
*U#
 WS'\*
 s	

 

 
 
 
   %    "# # # #J     r   re   c            
       @   e Zd ZdZddZdd	Zd
edej        ej	        eef                  dej
        ej	        ej        e         eef                  dej	        eef         fdZdeddfdZdej        e         ddfdZdej        dej        dej        e         fdZdS )LintMiddlewarea  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)
    appr   r   Nc                     || _         d S r)   )r   )r-   r   s     r   r.   zLintMiddleware.__init__   s    r   environr   c                    t          |          t          urt          dt          d           dD ]!}||vrt          d|dt          d           "|d         d	k    rt          d
t          d           |                    dd          }|                    dd          }|r&|d         dk    rt          d|t          d           |r(|d         dk    rt          d|t          d           d S d S d S )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   )r2   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   rw   )r-   r   r}   script_name	path_infos        r   check_environzLintMiddleware.check_environ   sr   ==$ 	A   


 	 	C '! AAAA    
 >"f, 	R5{qQQQQkk-44KKR00	 	;q>S0 	MkMM     	1, 	IIII     	 	 	 	r   statusrz   exc_infoc                 ,   t          d|t                     |                    d d          d         }t          |          dk    s|                                st          dt          d           t          |          dk     s|d         dk    rt          d	|d
t          d           t          |          }|dk     rt          dt          d           t          |          t          urt          dt          d           |D ]}t          |          t          ust          |          dk    rt          dt          d           |\  }}t          |          t          ust          |          t          urt          dt          d           |                                dk    rt          dt          d           |,t          |t                    st          dt          d           t          |          }|                     |           ||fS )Nr   r2   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.rr   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$   rL   splitr3   	isdecimalr   r   rc   r#   listtuplerx   
isinstancer   check_headers)	r-   r   rz   r   status_code_strry   itemnamevalues	            r   check_start_responsez#LintMiddleware.check_start_response  sR    	8VS))) ,,tQ//21$ 	QO,E,E,G,G 	Q4kaPPPPv;;? 	fQi3. 	=F = = =	    /** 	K.JJJJ==$ 	J-{qIIII 	 	DDzz& W#d))q. W:KTUVVVVKD%Dzz$ U3(> ={WX    zz||x' 4 	     	K
8U(C(C 	K.JJJJ'""7###G##r   c                    |                     d          }||                    d          r6|                    d          rt          dt          d           |dd          }|d d         |d	d          cxk    rd
k    sn t          dt          d           |                     d          }|-t	          |          j        st          dt          d           d S d S d S )Netag)zW/w/r   z)Weak etag indicator should be upper case.r   r!   r   r2   "zUnquoted etag emitted.locationz+Absolute URLs required for location header.)rw   
startswithr   r   r   netloc)r-   rz   r   r   s       r   r   zLintMiddleware.check_headersN  s:   {{6"" 	J|,,  ??4(( C##$    ABBx!HRSS	 J J J JS J J J J-{qIIII;;z** 	H%%, A      	 	 r   app_iterc                 b    t          |t                    rt          dt          d           d S d S )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.r    r!   )r   rD   r   r   )r-   r   s     r   check_iteratorzLintMiddleware.check_iteratori  sL    h&& 	6      	 	r   r0   kwargsc                     t          |          dk    rt          dt          d           |rt          dt          d           |d         }|d                              |           t	          |d                   |d<   t          |d                   |d<   t          |d	<   g g d
t          j        dt          j        dt          j	        t          gd f         f fd}                     |t          j        d|                    }                     |           t          |t          j        t          j        t           t"          f                             S )Nr   zA WSGI app takes two arguments.r!   z+A WSGI app does not take keyword arguments.r   r2   r   r   zwsgi.file_wrapperr0   r   r   c                  l   t          |           dvr(t          dt          |            dt          d           |rt          dt                     | d         }| d         }t          |           d	k    r| d         nd }                    |||          d d <   t	           |||                    S )
N>   r   r    zInvalid number of arguments: z, expected 2 or 3.r   r!   z1'start_response' does not take keyword arguments.r   r2   r    )r3   r   r   r   rX   )	r0   r   r   rz   r   rY   rg   r-   start_responses	        r   checking_start_responsez8LintMiddleware.__call__.<locals>.checking_start_response  s     4yy& QCIIQQQ      WH+VVVq'F15aG  IIN4a  "66vwQQKNvw I I6RRRr   r
   )r3   r   r   r   r&   rH   r	   rB   rE   r`   rD   r   castr   re   r   rc   r   )	r-   r0   r   r   r   r   rY   rg   r   s	   `     @@@r   r_   zLintMiddleware.__call__s  s   t99> 	O2KANNNN 	={WX    &*!W*.q'7### +GL,A B B!,W]-C!D!D (3#$%' 	S5	S$%E	SZ&	S 	S 	S 	S 	S 	S 	S 	S 	S, 88GQVO=T%U%UVVH%%%afQWS'\2K@@&
 
 	
r   )r   r   r   N)r   r   r   N)r   r   r   r   r.   r   rL   rB   rb   r   OptionalTypeBaseExceptionr   rc   r   r   r   rV   rD   r   rE   r_   r   r   r   r   r      s=        ,   * * * *X4$4$ S)*4$ *GAF=)=-GH
	4$ 
g	4$ 4$ 4$ 4$lW     6qz%'8 T    1
ae 1
qu 1
E9J 1
 1
 1
 1
 1
 1
r   r   ) r   typingrB   typesr   urllib.parser   warningsr   datastructuresr   httpr   wsgir	   TYPE_CHECKING_typeshed.wsgir
   r   r   Warningr   r   rL   ra   r   r$   r&   rH   rX   re   r   r   r   r   <module>r      s?              ! ! ! ! ! !       $ $ $ $ $ $ # # # # # #      ? /,,,,,,............+ + + + +' + + ++ + + + +' + + + := 
 
 
& 
 
 
 
 
 
1 1 1 1 1 1 1 1h       ($ $ $ $ $ $ $ $M M M M M M M M`R
 R
 R
 R
 R
 R
 R
 R
 R
 R
r   