
    5 f\6                    ^   d Z ddlm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%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
    )annotationsN)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__     N/var/www/equiseq/venv/lib/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strobjobjectneedt.TypereturnNonec           	         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)   (   si    CyyRRDMRR499;MRRR	
 	
 	
 	
 	
 	
 r   c                  6    e Zd ZddZdd	Zdd
ZddZddZdS )InputStreamstreamt.IO[bytes]r!   r"   c                    || _         d S N_streamselfr,   s     r   __init__zInputStream.__init__2       r   argst.Anybytesc                    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   r1   readr3   r6   s     r   r<   zInputStream.read5   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&   r:   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;   r   r   	TypeErrorr1   readliner=   s     r   r@   zInputStream.readlineF   s    t99>>0	     YY!^^O	     STTT$t|$d++r   t.Iterator[bytes]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   )iterr1   r?   r   r   r3   s    r   __iter__zInputStream.__iter__Y   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   r1   closerD   s    r   rH   zInputStream.close`   3    7QRSSSSr   N)r,   r-   r!   r"   )r6   r7   r!   r8   )r!   rA   r!   r"   )r   r   r   r4   r<   r@   rE   rH   r   r   r   r+   r+   1   sx           ( ( ( (", , , ,&        r   r+   c                  6    e Zd ZddZddZdd	ZddZddZdS )ErrorStreamr,   	t.IO[str]r!   r"   c                    || _         d S r/   r0   r2   s     r   r4   zErrorStream.__init__f   r5   r   sr   c                f    t          d|t                     | j                            |           d S )Nzwsgi.error.write())r)   r   r1   writer3   rO   s     r   rQ   zErrorStream.writei   s1    'C0001r   c                8    | j                                          d S r/   )r1   flushrD   s    r   rT   zErrorStream.flushm   s    r   seqt.Iterable[str]c                :    |D ]}|                      |           d S r/   )rQ   )r3   rU   lines      r   
writelineszErrorStream.writelinesp   s0     	 	DJJt	 	r   c                f    t          dt          d           | j                                         d S )Nz(The application closed the error stream!r   r&   rG   rD   s    r   rH   zErrorStream.closet   rI   r   N)r,   rM   r!   r"   )rO   r   r!   r"   rJ   )rU   rV   r!   r"   )r   r   r   r4   rQ   rT   rY   rH   r   r   r   rL   rL   e   sx                         r   rL   c                      e Zd ZddZdd
ZdS )GuardedWriterQ   t.Callable[[bytes], object]chunks	list[int]r!   r"   c                "    || _         || _        d S r/   )_write_chunks)r3   rQ   r^   s      r   r4   zGuardedWrite.__init__z   s    r   rO   r8   c                    t          d|t                     |                     |           | j                            t          |                     d S )Nzwrite())r)   r8   ra   rb   appendr;   rR   s     r   __call__zGuardedWrite.__call__~   sE    9a'''ACFF#####r   N)rQ   r]   r^   r_   r!   r"   )rO   r8   r!   r"   )r   r   r   r4   re   r   r   r   r\   r\   y   s<           $ $ $ $ $ $r   r\   c                  6    e Zd Zdd	Zdd
ZddZddZddZdS )GuardedIteratoriteratort.Iterable[bytes]headers_settuple[int, Headers]r^   r_   r!   r"   c                p    || _         t          |          j        | _        d| _        || _        || _        d S )NF)	_iteratorrC   __next___nextclosedrj   r^   )r3   rh   rj   r^   s       r   r4   zGuardedIterator.__init__   s5     "(^^,
&r   c                    | S r/   r   rD   s    r   rE   zGuardedIterator.__iter__   s    r   r8   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)
rp   r   r   ro   rj   r)   r8   r^   rd   r;   )r3   rvs     r   rn   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 )NTrH   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.)rp   hasattrrm   rH   rj   sumr^   getintlowerr	   r   r   r   )r3   status_codeheaders
bytes_sentcontent_lengthkey_values          r   rH   zGuardedIterator.close   s   4>7++ 	#N  """ 	#'#3 KT[))J$[[)9[DDNc!!#*  KC))++C"AAAFVG GA 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+*0L0L,    3	 	0 ,+0L0Lr   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.)rp   r   r   	ExceptionrD   s    r   __del__zGuardedIterator.__del__   s`    { 	JK        	 	s     
..N)rh   ri   rj   rk   r^   r_   r!   r"   )r!   rg   )r!   r8   rJ   )r   r   r   r4   rE   rn   rH   r   r   r   r   rg   rg      sy        
 
 
 
      "# # # #J     r   rg   c                  B    e Zd ZdZddZdd	ZddZddZd dZd!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!   r"   c                    || _         d S r/   )r   )r3   r   s     r   r4   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   )r:   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{   )r3   r   r   script_name	path_infos        r   check_environzLintMiddleware.check_environ   sc   ==$$A   


 	 	C '!!AAAA    
 >"f,,5{qQQQQkk-44KKR00	 	;q>S00MkMM     	1,,IIII     	 	,,r   statusr   r   list[tuple[str, str]]exc_info?None | tuple[type[BaseException], BaseException, TracebackType]rk   c                ,   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   r:   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.rv   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)   r   splitr;   	isdecimalr   r   r|   r(   listtupler}   
isinstancer   check_headers)	r3   r   r   r   status_code_strr~   itemnamevalues	            r   check_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 	 	DDzz&&#d))q..:KTUVVVVKD%Dzz$$U3(>(>={WX    zz||x''4 	    
8U(C(C.JJJJ'""7###G##r   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   r:   "zUnquoted etag emitted.locationz+Absolute URLs required for location header.)r{   
startswithr   r   r   netloc)r3   r   r   r   s       r   r   zLintMiddleware.check_headersN  s   {{6""|,,  ??4(( C##$    ABBx!HRSS	0000S0000-{qIIII;;z**H%%, A         r   app_iterri   c                b    t          |t                    rt          dt          d           d S d S )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   r   r   r   )r3   r   s     r   check_iteratorzLintMiddleware.check_iteratori  sL    h$$ 	6      	 	r   r6   r7   kwargsc                d    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 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   r:   r   r   zwsgi.file_wrapperr6   r7   r   r!   t.Callable[[bytes], None]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   r:   r%   )r;   r   r   r   r\   )	r6   r   r   r   r   r^   rj   r3   start_responses	        r   checking_start_responsez8LintMiddleware.__call__.<locals>.checking_start_response  s     4yy&&QCIIQQQ      WH+VVVq'F-1!WG  IINNa  "66vwQQKNvw I I6RRRr   r   )r6   r7   r   r7   r!   r   )r;   r   r   r   r+   rL   r
   r   tcastr   rg   Tupler|   r   )	r3   r6   r   r   r   r   r^   rj   r   s	   `     @@@r   re   zLintMiddleware.__call__s  s[   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 	S, 88GQVO=T%U%UVVH%%%afQWS'\2K@@&
 
 	
r   N)r   r   r!   r"   )r   r   r!   r"   )r   r   r   r   r   r   r!   rk   )r   r   r!   r"   )r   ri   r!   r"   )r6   r7   r   r7   r!   ri   )
r   r   r   r   r4   r   r   r   r   re   r   r   r   r   r      s         ,   * * * *X2$ 2$ 2$ 2$h   6   1
 1
 1
 1
 1
 1
r   r   )r   r   r   r   r   r    r!   r"   ) r   
__future__r   typingr   typesr   urllib.parser   warningsr   datastructuresr   httpr	   wsgir
   TYPE_CHECKING_typeshed.wsgir   r   r   Warningr   r   r   r)   r+   rL   r\   rg   r   r   r   r   <module>r      s3    # " " " " "           ! ! ! ! ! !       $ $ $ $ $ $ # # # # # #      ? /,,,,,,............+ + + + +' + + ++ + + + +' + + + := 
 
 
 
 
1 1 1 1 1 1 1 1h       ($ $ $ $ $ $ $ $M M M M M M M M`P
 P
 P
 P
 P
 P
 P
 P
 P
 P
r   