
     f8                    ^   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__     [/var/www/api.educacionweb.es/myenv/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typereturnNonec           	         t          |          |ur9t          | d|j        dt          |          j        dt          d           d S d S )Nz
 requires z, got .   
stacklevel)r    r   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__3       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   r0   readr2   r5   s     r   r;   zInputStream.read6   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&   r9   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   	TypeErrorr0   readliner<   s     r   r?   zInputStream.readlineG   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   )iterr0   r>   r   r   r2   s    r   __iter__zInputStream.__iter__Z   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   r0   closerC   s    r   rG   zInputStream.closea   3    7QRSSSSr   N)r+   r,   r!   r"   )r5   r6   r!   r7   )r!   r@   r!   r"   )r   r   r   r3   r;   r?   rD   rG   r   r   r   r*   r*   2   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.   r/   r1   s     r   r3   zErrorStream.__init__g   r4   r   sr   c                f    t          d|t                     | j                            |           d S )Nzwsgi.error.write())r(   r   r0   writer2   rN   s     r   rP   zErrorStream.writej   s1    'C0001r   c                8    | j                                          d S r.   )r0   flushrC   s    r   rS   zErrorStream.flushn   s    r   seqt.Iterable[str]c                :    |D ]}|                      |           d S r.   )rP   )r2   rT   lines      r   
writelineszErrorStream.writelinesq   s0     	 	DJJt	 	r   c                f    t          dt          d           | j                                         d S )Nz(The application closed the error stream!r   r&   rF   rC   s    r   rG   zErrorStream.closeu   rH   r   N)r+   rL   r!   r"   )rN   r   r!   r"   rI   )rT   rU   r!   r"   )r   r   r   r3   rP   rS   rX   rG   r   r   r   rK   rK   f   sx                         r   rK   c                      e Zd ZddZdd
ZdS )GuardedWriterP   t.Callable[[bytes], object]chunks	list[int]r!   r"   c                "    || _         || _        d S r.   )_write_chunks)r2   rP   r]   s      r   r3   zGuardedWrite.__init__{   s    r   rN   r7   c                    t          d|t                     |                     |           | j                            t          |                     d S )Nzwrite())r(   r7   r`   ra   appendr:   rQ   s     r   __call__zGuardedWrite.__call__   sE    9a'''ACFF#####r   N)rP   r\   r]   r^   r!   r"   )rN   r7   r!   r"   )r   r   r   r3   rd   r   r   r   r[   r[   z   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)	_iteratorrB   __next___nextclosedri   r]   )r2   rg   ri   r]   s       r   r3   zGuardedIterator.__init__   s5     "(^^,
&r   c                    | S r.   r   rC   s    r   rD   zGuardedIterator.__iter__   s    r   r7   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)
ro   r   r   rn   ri   r(   r7   r]   rc   r:   )r2   rvs     r   rm   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    rg|D ]G\  }}|	                                }|dvr*t          |          rt          d|dt          d	
           H|rt          dt          d	
           d S d S d|cxk    rdk     sn |dk    r@|dk    rt          | dt          d	
           |rt          | dt          d	
           d S d S |!||k    rt          dt          d	
           d S d S d S d S )NTrG   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.)ro   hasattrrl   rG   ri   sumr]   getintlowerr	   r   r   r   )r2   status_codeheaders
bytes_sentcontent_lengthkey_values          r   rG   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''(   
  =##$       ))))c))))[C-?-?!Q&&&UUU##$   
  &HHH##$        +*0L0L, 	     I)	 )	F ,+0L0Lr   c                j    | j         s+	 t          dt          d           d S # t          $ r Y d S w xY wd S )Nz4Iterator was garbage collected before it was closed.r   r&   )ro   r   r   	ExceptionrC   s    r   __del__zGuardedIterator.__del__   si    { 	J      
    	 	s   " 
00N)rg   rh   ri   rj   r]   r^   r!   r"   )r!   rf   )r!   r7   rI   )r   r   r   r3   rD   rm   rG   r   r   r   r   rf   rf      sy        
 
 
 
      "/ / / /b	 	 	 	 	 	r   rf   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   )r2   r   s     r   r3   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   )r9   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   rz   )r2   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]rj   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   r9   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.ru   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)
r2   r   r~   r   status_code_strr}   itemnamevalueheaders_objs
             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g&&;'''K''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   r9   "zUnquoted etag emitted.locationz+Absolute URLs required for location header.)rz   
startswithr   r   r   netloc)r2   r~   r   r   s       r   r   zLintMiddleware.check_headers]  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_iterrh   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   )r2   r   s     r   check_iteratorzLintMiddleware.check_iteratorx  sL    h$$ 	6      	 	r   r5   r6   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   r9   r   r   zwsgi.file_wrapperr5   r6   r   r!   t.Callable[[bytes], None]c                 p   t          |           dvr(t          dt          |            dt          d           |rt          dt          d           | 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   r9   r%   )r:   r   r   r   r[   )	r5   r   r   r~   r   r]   ri   r2   start_responses	        r   checking_start_responsez8LintMiddleware.__call__.<locals>.checking_start_response  s     4yy&&QCIIQQQ      G     q'F-1!WG t99>>Qt  "66vwQQKNvw I I6RRRr   r   )r5   r6   r   r6   r!   r   )r:   r   r   r   r*   rK   r
   r   tcastr   rf   Tupler{   r   )	r2   r5   r   r   r   r   r]   ri   r   s	   `     @@@r   rd   zLintMiddleware.__call__  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4 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!   rj   )r~   r   r!   r"   )r   rh   r!   r"   )r5   r6   r   r6   r!   rh   )
r   r   r   r   r3   r   r   r   r   rd   r   r   r   r   r      s         ,   * * * *X2( 2( 2( 2(h   6   5
 5
 5
 5
 5
 5
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*   rK   r[   rf   r   r   r   r   <module>r      s3    # " " " " "           ! ! ! ! ! !       $ $ $ $ $ $ # # # # # #      ? /,,,,,,............+ + + + +' + + ++ + + + +' + + + 8; 
 
 
 
 
1 1 1 1 1 1 1 1h       ($ $ $ $ $ $ $ $[ [ [ [ [ [ [ [|T
 T
 T
 T
 T
 T
 T
 T
 T
 T
r   