o
    ßý°jŒ8  ã                   @  s  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rEddlmZ ddlmZ ddlmZ G dd„ deƒZG dd„ deƒZefd&dd„ZG dd„ dƒZG dd„ dƒZG d d!„ d!ƒZG d"d#„ d#ƒZG d$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__© r   r   ú‹/root/aizidognhua/tmp/workspace/projects/ec89d86c-575f-41c9-af57-ac45cbdbf775/venv/lib/python3.10/site-packages/werkzeug/middleware/lint.pyr   !   ó    r   c                   @  r   )ÚHTTPWarningz Warning class for HTTP warnings.Nr   r   r   r   r   r   %   r   r   ÚcontextÚstrÚobjÚobjectÚneedÚtypeÚreturnÚNonec                 C  s<   t |ƒ|urt| ›d|j›dt |ƒj›d�tdd� d S d S )Nz
 requires z, got Ú.é   ©Ú
stacklevel)r   r   r   r   )r   r   r   r   r   r   Ú
check_type)   s   
ýÿr$   c                   @  s>   e Zd Zddd„Zdd
d„Zddd„Zddd„Zddd„ZdS )ÚInputStreamÚstreamút.IO[bytes]r   r   c                 C  ó
   || _ d S ©N©Ú_stream©Úselfr&   r   r   r   Ú__init__3   ó   
zInputStream.__init__Úargsút.AnyÚbytesc                 G  sB   t |ƒdkrtdtdd� nt |ƒdkrtdtdd� | jj|Ž S )Nr   zŸWSGI 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   r   r   r   r5   6   s   ûýzInputStream.readc                 G  sL   t |ƒdkrtdtdd� nt |ƒdkrtdtd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"   r3   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()'.)r4   r   r   Ú	TypeErrorr+   Úreadliner6   r   r   r   r8   G   s   üüzInputStream.readlineút.Iterator[bytes]c                 C  s6   zt | jƒW S  ty   tdtdd� t dƒ Y S w )Nz'wsgi.input' is not iterable.r   r"   r   )Úiterr+   r7   r   r   ©r-   r   r   r   Ú__iter__Z   s   þzInputStream.__iter__c                 C  ó   t dtdd� | j ¡  d S )Nz(The application closed the input stream!r   r"   ©r   r   r+   Úcloser;   r   r   r   r?   a   ó   zInputStream.closeN)r&   r'   r   r   )r0   r1   r   r2   )r   r9   ©r   r   )r   r   r   r.   r5   r8   r<   r?   r   r   r   r   r%   2   s    



r%   c                   @  s>   e Zd Zddd„Zdd	d
„Zddd„Zddd„Zddd„ZdS )ÚErrorStreamr&   ú	t.IO[str]r   r   c                 C  r(   r)   r*   r,   r   r   r   r.   g   r/   zErrorStream.__init__Úsr   c                 C  s   t d|tƒ | j |¡ d S )Nzwsgi.error.write())r$   r   r+   Úwrite©r-   rD   r   r   r   rE   j   s   zErrorStream.writec                 C  s   | j  ¡  d S r)   )r+   Úflushr;   r   r   r   rG   n   s   zErrorStream.flushÚseqút.Iterable[str]c                 C  s   |D ]}|   |¡ qd S r)   )rE   )r-   rH   Úliner   r   r   Ú
writelinesq   s   ÿzErrorStream.writelinesc                 C  r=   )Nz(The application closed the error stream!r   r"   r>   r;   r   r   r   r?   u   r@   zErrorStream.closeN)r&   rC   r   r   )rD   r   r   r   rA   )rH   rI   r   r   )r   r   r   r.   rE   rG   rK   r?   r   r   r   r   rB   f   s    



rB   c                   @  s    e Zd Zddd„Zddd„ZdS )ÚGuardedWriterE   út.Callable[[bytes], object]Úchunksú	list[int]r   r   c                 C  s   || _ || _d S r)   )Ú_writeÚ_chunks)r-   rE   rN   r   r   r   r.   {   s   
zGuardedWrite.__init__rD   r2   c                 C  s*   t d|tƒ |  |¡ | j t|ƒ¡ d S )Nzwrite())r$   r2   rP   rQ   Úappendr4   rF   r   r   r   Ú__call__   s   
zGuardedWrite.__call__N)rE   rM   rN   rO   r   r   )rD   r2   r   r   )r   r   r   r.   rS   r   r   r   r   rL   z   s    
rL   c                   @  s>   e Zd Zdd	d
„Zddd„Zddd„Zddd„Zddd„ZdS )ÚGuardedIteratorÚiteratorút.Iterable[bytes]Úheaders_setútuple[int, Headers]rN   rO   r   r   c                 C  s(   || _ t|ƒj| _d| _|| _|| _d S )NF)Ú	_iteratorr:   Ú__next__Ú_nextÚclosedrW   rN   )r-   rU   rW   rN   r   r   r   r.   †   s
   
zGuardedIterator.__init__c                 C  s   | S r)   r   r;   r   r   r   r<   ’   s   zGuardedIterator.__iter__r2   c                 C  sP   | j r
tdtdd� |  ¡ }| jstdtd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)
r\   r   r   r[   rW   r$   r2   rN   rR   r4   )r-   Úrvr   r   r   rZ   •   s   ýzGuardedIterator.__next__c                 C  s*  d| _ t| jdƒr| j ¡  | jr�| j\}}t| jƒ}|jdtd�}|dkrQ|D ]\}}| 	¡ }|dvrCt
|ƒrCtd|›d�td	d
� q(|rOtdtd	d
� d S d S d|  kr[dk s`n |dkr~|dkrnt|› d�td	d
� |r|t|› d�td	d
� d S d S |d ur‘||kr“tdtd	d
� d S d S d S d S )NTr?   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.)r\   ÚhasattrrY   r?   rW   ÚsumrN   ÚgetÚintÚlowerr   r   r   r   )r-   Ústatus_codeÚheadersÚ
bytes_sentÚcontent_lengthÚkeyÚ_valuer   r   r   r?   ¦   s`   



ÿ
ý€
ýÿý
ýÿ
üÜ#zGuardedIterator.closec                 C  s4   | j sz
tdtdd� W d S  ty   Y d S w d S )Nz4Iterator was garbage collected before it was closed.r   r"   )r\   r   r   Ú	Exceptionr;   r   r   r   Ú__del__×   s   ýÿùzGuardedIterator.__del__N)rU   rV   rW   rX   rN   rO   r   r   )r   rT   )r   r2   rA   )r   r   r   r.   r<   rZ   r?   rn   r   r   r   r   rT   …   s    



1rT   c                   @  sL   e Zd ZdZd"dd„Zd#d
d„Zd$dd„Zd%dd„Zd&dd„Zd'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                 C  r(   r)   )rp   )r-   rp   r   r   r   r.   ú   r/   zLintMiddleware.__init__Úenvironr   c                 C  sÈ   t |ƒturtdtdd� dD ]}||vr td|›d�tdd� q|d d	kr.td
tdd� | dd¡}| dd¡}|rL|d dkrLtd|›�tdd� |r`|d dkrbtd|›�td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!   rv   )r3   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   rd   )r-   rq   rk   Úscript_nameÚ	path_infor   r   r   Úcheck_environý   s>   ý
ý€ý
ýÿzLintMiddleware.check_environÚstatusr   rh   úlist[tuple[str, str]]Úexc_infoú?None | tuple[type[BaseException], BaseException, TracebackType]rX   c           
      C  sV  t d|tƒ | d d¡d }t|ƒdks| ¡ stdtdd� t|ƒdk s+|d dkr6td	|›d
�tdd� t|ƒ}|dk rEtdtdd� t|ƒt	urRtdtdd� |D ]9}t|ƒt
usbt|ƒdkritdtdd� |\}}t|ƒtusyt|ƒtur€tdtdd� | ¡ dkr�tdtdd� qT|d uržt|t
ƒsžtdtdd� t|ƒ}	|  |	¡ ||	fS )Nr�   r3   r   r!   z!Status code must be three digits.r"   rr   ú 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$   r   Úsplitr4   Ú	isdecimalr   r   re   r   ÚlistÚtuplerf   Ú
isinstancer   Úcheck_headers)
r-   r�   rh   rƒ   Ústatus_code_strrg   ÚitemÚnameÚvalueÚheaders_objr   r   r   Úcheck_start_response)  sF   
üÿü€
z#LintMiddleware.check_start_responser   c                 C  sª   |  d¡}|d ur:| d¡r | d¡rtdtdd� |dd … }|d d… |d	d …   kr2d
ks:n tdtdd� |  d¡}|d urQt|ƒjsStdtdd� d S d S d S )NÚetag)zW/úw/r“   z)Weak etag indicator should be upper case.rr   r"   r   r3   éÿÿÿÿú"zUnquoted etag emitted.Úlocationz+Absolute URLs required for location header.)rd   Ú
startswithr   r   r   Únetloc)r-   rh   r’   r–   r   r   r   r‹   ]  s,   


ý&


ýþzLintMiddleware.check_headersÚapp_iterrV   c                 C  s    t |tƒrtdtdd� d S d S )Nz The 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   )r-   r™   r   r   r   Úcheck_iteratorx  s   

ûÿzLintMiddleware.check_iteratorr0   r1   Úkwargsc                   sÄ   t |ƒdkrtdtdd� |rtdtdd� |d }|d ‰ˆ |¡ t|d ƒ|d< t|d ƒ|d< t|d	< g ‰g ‰ d‡ ‡‡‡fdd„}ˆ |t 	d|¡¡}ˆ 
|¡ t|t 	tttf ˆ¡ˆ ƒS )Nr   zA WSGI app takes two arguments.r"   z+A WSGI app does not take keyword arguments.r   r3   rw   rx   zwsgi.file_wrapperr0   r1   r›   r   út.Callable[[bytes], None]c                    sˆ   t | ƒdvrtdt | ƒ› d�tdd� |rtdtd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   r3   r!   )r4   r   r   r‘   rL   )r0   r›   r�   rh   rƒ   ©rN   rW   r-   Ústart_responser   r   Úchecking_start_response™  s$   ýýþz8LintMiddleware.__call__.<locals>.checking_start_responser
   )r0   r1   r›   r1   r   rœ   )r4   r   r   r€   r%   rB   r	   rp   ÚtÚcastrš   rT   r‰   re   r   )r-   r0   r›   rq   rŸ   r™   r   r�   r   rS   ‚  s(   ÿ

ÿzLintMiddleware.__call__N)rp   r   r   r   )rq   r   r   r   )r�   r   rh   r‚   rƒ   r„   r   rX   )rh   r   r   r   )r™   rV   r   r   )r0   r1   r›   r1   r   rV   )
r   r   r   r   r.   r€   r‘   r‹   rš   rS   r   r   r   r   ro   ã   s    


,
4

ro   )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%   rB   rL   rT   ro   r   r   r   r   Ú<module>   s*    	4^