a
    Nf8                     @  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rd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d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                   @  s   e Zd ZdZdS )WSGIWarningz Warning class for WSGI warnings.N__name__
__module____qualname____doc__ r   r   Q/var/www/ai-form-bot/venv/lib/python3.9/site-packages/werkzeug/middleware/lint.pyr   !   s   r   c                   @  s   e Zd ZdZdS )HTTPWarningz Warning class for HTTP warnings.Nr   r   r   r   r   r   %   s   r   strobjecttypeNone)contextobjneedreturnc                 C  s8   t ||ur4t| d|jdt |jdtdd d S )Nz
 requires z, got .   
stacklevel)r   r   r   r   )r   r   r   r   r   r   
check_type)   s    r"   c                   @  sX   e Zd ZdddddZdddd	d
ZdddddZddddZddddZdS )InputStreamzt.IO[bytes]r   streamr   c                 C  s
   || _ d S N_streamselfr%   r   r   r   __init__3   s    zInputStream.__init__t.Anybytes)argsr   c                 G  sB   t |dkrtdtdd nt |dkr6tdtd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*   r.   r   r   r   r1   6   s    zInputStream.readc                 G  sL   t |dkrtdtdd n$t |dkr8t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    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()'.)r0   r   r   	TypeErrorr(   readliner2   r   r   r   r4   G   s    zInputStream.readlinezt.Iterator[bytes]r   c                 C  s:   zt | jW S  ty4   tdtdd t d Y S 0 d S )Nz'wsgi.input' is not iterable.r   r    r   )iterr(   r3   r   r   r*   r   r   r   __iter__Z   s
    zInputStream.__iter__c                 C  s   t dtdd | j  d S )Nz(The application closed the input stream!r   r    r   r   r(   closer7   r   r   r   r:   a   s    zInputStream.closeN)r   r   r   r+   r1   r4   r8   r:   r   r   r   r   r#   2   s
   r#   c                   @  sX   e Zd ZdddddZddddd	Zdd
ddZdddddZdd
ddZdS )ErrorStreamz	t.IO[str]r   r$   c                 C  s
   || _ d S r&   r'   r)   r   r   r   r+   g   s    zErrorStream.__init__r   sr   c                 C  s   t d|t | j| d S )Nzwsgi.error.write())r"   r   r(   writer*   r=   r   r   r   r>   j   s    zErrorStream.writer5   c                 C  s   | j   d S r&   )r(   flushr7   r   r   r   r@   n   s    zErrorStream.flushzt.Iterable[str])seqr   c                 C  s   |D ]}|  | qd S r&   )r>   )r*   rA   liner   r   r   
writelinesq   s    zErrorStream.writelinesc                 C  s   t dtdd | j  d S )Nz(The application closed the error stream!r   r    r9   r7   r   r   r   r:   u   s    zErrorStream.closeN)r   r   r   r+   r>   r@   rC   r:   r   r   r   r   r;   f   s
   r;   c                   @  s.   e Zd ZddddddZdddd	d
ZdS )GuardedWritezt.Callable[[bytes], object]	list[int]r   )r>   chunksr   c                 C  s   || _ || _d S r&   )_write_chunks)r*   r>   rF   r   r   r   r+   {   s    zGuardedWrite.__init__r-   r<   c                 C  s*   t d|t | | | jt| d S )Nzwrite())r"   r-   rG   rH   appendr0   r?   r   r   r   __call__   s    
zGuardedWrite.__call__N)r   r   r   r+   rJ   r   r   r   r   rD   z   s   rD   c                   @  sX   e Zd ZdddddddZd dd	d
ZddddZddddZddddZdS )GuardedIteratort.Iterable[bytes]tuple[int, Headers]rE   r   )iteratorheaders_setrF   r   c                 C  s(   || _ t|j| _d| _|| _|| _d S )NF)	_iteratorr6   __next___nextclosedrO   rF   )r*   rN   rO   rF   r   r   r   r+      s
    zGuardedIterator.__init__r5   c                 C  s   | S r&   r   r7   r   r   r   r8      s    zGuardedIterator.__iter__r-   c                 C  sP   | j rtdtdd |  }| js0t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)
rS   r   r   rR   rO   r"   r-   rF   rI   r0   )r*   rvr   r   r   rQ      s    zGuardedIterator.__next__c                 C  s  d| _ t| jdr| j  | jr| j\}}t| j}|jdtd}|dkr|D ]6\}}|	 }|dvrRt
|rRtd|dtd	d
 qR|rtdtd	d
 nvd|  krdk sn |dkr|dkrt| dtd	d
 |rt| dtd	d
 n"|d ur||krtdtd	d
 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.)rS   hasattrrP   r:   rO   sumrF   getintlowerr   r   r   r   )r*   status_codeheadersZ
bytes_sentcontent_lengthkey_valuer   r   r   r:      sV    




zGuardedIterator.closec                 C  s0   | j s,ztdtdd W n ty*   Y n0 d S )Nz4Iterator was garbage collected before it was closed.r   r    )rS   r   r   	Exceptionr7   r   r   r   __del__   s    
zGuardedIterator.__del__N)r   r   r   r+   r8   rQ   r:   rd   r   r   r   r   rK      s
   1rK   c                   @  sv   e Zd ZdZdddddZdddd	d
ZdddddddZdddddZdddddZddd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)
    r   r   )appr   c                 C  s
   || _ d S r&   )rf   )r*   rf   r   r   r   r+      s    zLintMiddleware.__init__r   )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}|r|d dkrtd|tdd |r|d dkrtd|tdd d S )Nz/WSGI environment is not a standard Python dict.   r    )	REQUEST_METHODZSERVER_NAMEZSERVER_PORTwsgi.version
wsgi.inputwsgi.errorszwsgi.multithreadzwsgi.multiprocesszwsgi.run_oncezRequired environment key z
 not foundr   rj   )r/   r   z"Environ is not a WSGI 1.0 environ.ZSCRIPT_NAME Z	PATH_INFOr   /z+'SCRIPT_NAME' does not start with a slash: z)'PATH_INFO' does not start with a slash: )r   dictr   r   r[   )r*   rg   ra   script_nameZ	path_infor   r   r   check_environ   s:    
zLintMiddleware.check_environr   zlist[tuple[str, str]]z?None | tuple[type[BaseException], BaseException, TracebackType]rM   )statusr_   exc_infor   c           
      C  s\  t d|t |d dd }t|dks0| s>tdtdd t|dk sV|d dkrltd	|d
tdd t|}|dk rtdtdd t|t	urtdtdd |D ]t}t|t
ust|dkrtdtdd |\}}t|tust|turtdtdd | dkrtdtdd q|d urBt|t
sBtdtdd t|}	| |	 ||	fS )Nrr   r/   r   r   z!Status code must be three digits.r    rh    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   splitr0   	isdecimalr   r   r\   r   listtupler]   
isinstancer   check_headers)
r*   rr   r_   rs   Zstatus_code_strr^   itemnamevalueZheaders_objr   r   r   check_start_response)  sD    

z#LintMiddleware.check_start_responser   )r_   r   c                 C  s   | d}|d urt|dr@|dr4tdtdd |dd  }|d d |d	d    krdd
kstn tdtdd | d}|d urt|jstdtdd d S )Netag)zW/w/r   z)Weak etag indicator should be upper case.rh   r    r   r/   "zUnquoted etag emitted.locationz+Absolute URLs required for location header.)r[   
startswithr   r   r   netloc)r*   r_   r   r   r   r   r   rz   ]  s(    


&

zLintMiddleware.check_headersrL   )app_iterr   c                 C  s   t |trtdtdd 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    )ry   r   r   r   )r*   r   r   r   r   check_iteratorx  s    
zLintMiddleware.check_iteratorr,   r.   kwargsr   c                   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
d
dd fdd}|t	d|}
| t|t	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/   rk   rl   zwsgi.file_wrapperr,   zt.Callable[[bytes], None]r   c                    s   t | dvr&tdt |  dtdd |r8t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   r/   r   )r0   r   r   r~   rD   )r.   r   rr   r_   rs   rF   rO   r*   Zstart_responser   r   checking_start_response  s$    z8LintMiddleware.__call__.<locals>.checking_start_responser
   )r0   r   r   rq   r#   r;   r	   rf   tcastr   rK   Tupler\   r   )r*   r.   r   rg   r   r   r   r   r   rJ     s(    

zLintMiddleware.__call__N)
r   r   r   r   r+   rq   r~   rz   r   rJ   r   r   r   r   re      s   ,4
re   ) r   
__future__r   typingr   typesr   urllib.parser   warningsr   Zdatastructuresr   httpr   Zwsgir	   TYPE_CHECKINGZ_typeshed.wsgir
   r   r   Warningr   r   r   r"   r#   r;   rD   rK   re   r   r   r   r   <module>   s(   	4^