a
    -=ic6                     @   s  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 deZG dd deZefeeej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
    N)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   i/home/droni/.local/share/virtualenvs/DPS-5Je3_V2c/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   )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)typer   r   r   )r   r   r   r   r   r   
check_type&   s    r   c                   @   sh   e Zd Zeje ddddZejedddZejeddd	Z	ej
e d
ddZdd
ddZdS )InputStreamNstreamr   c                 C   s
   || _ d S N_streamselfr!   r   r   r   __init__0   s    zInputStream.__init__)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   r+   3   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()'.)r*   r   r   	TypeErrorr$   readliner,   r   r   r   r.   D   s    zInputStream.readline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$   r-   r   r   r&   r   r   r   __iter__W   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$   closer1   r   r   r   r4   ^   s    zInputStream.close)r   r   r   tIObytesr'   Anyr+   r.   Iteratorr2   r4   r   r   r   r   r   /   s
   r   c                   @   sd   e Zd Zeje ddddZeddddZddd	d
Zej	e ddddZ
ddddZdS )ErrorStreamNr    c                 C   s
   || _ d S r"   r#   r%   r   r   r   r'   d   s    zErrorStream.__init__sr   c                 C   s   t d|t | j| d S )Nzwsgi.error.write())r   strr$   writer&   r<   r   r   r   r>   g   s    zErrorStream.writer/   c                 C   s   | j   d S r"   )r$   flushr1   r   r   r   r@   k   s    zErrorStream.flush)seqr   c                 C   s   |D ]}|  | qd S r"   )r>   )r&   rA   liner   r   r   
writelinesn   s    zErrorStream.writelinesc                 C   s   t dtdd | j  d S )Nz(The application closed the error stream!r   r   r3   r1   r   r   r   r4   r   s    zErrorStream.close)r   r   r   r5   r6   r=   r'   r>   r@   IterablerC   r4   r   r   r   r   r:   c   s
   r:   c                   @   s@   e Zd Zejegef eje ddddZ	eddddZ
dS )GuardedWriteN)r>   chunksr   c                 C   s   || _ || _d S r"   )_write_chunks)r&   r>   rF   r   r   r   r'   x   s    zGuardedWrite.__init__r;   c                 C   s*   t d|t | | | jt| d S )Nzwrite())r   r7   rG   rH   appendr*   r?   r   r   r   __call__|   s    
zGuardedWrite.__call__)r   r   r   r5   Callabler7   objectListintr'   rJ   r   r   r   r   rE   w   s   $rE   c                   @   sn   e Zd Zeje ejeef ej	e ddddZ
d dddZeddd	Zddd
dZddddZdS )GuardedIteratorN)iteratorheaders_setrF   r   c                 C   s(   || _ t|j| _d| _|| _|| _d S )NF)	_iteratorr0   __next___nextclosedrQ   rF   )r&   rP   rQ   rF   r   r   r   r'      s
    zGuardedIterator.__init__r/   c                 C   s   | S r"   r   r1   r   r   r   r2      s    zGuardedIterator.__iter__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)
rU   r   r   rT   rQ   r   r7   rF   rI   r*   )r&   rvr   r   r   rS      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 ]2\}}|	 }|dvrPt
|rPtd|dt qP|rtd	t nfd
|  krdk sn |dkr|dkrt| dt |rt| dt n|d ur||krtdt d S )NTr4   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.)rU   hasattrrR   r4   rQ   sumrF   getrN   lowerr   r   r   r   )r&   status_codeheadersZ
bytes_sentcontent_lengthkey_valuer   r   r   r4      s>    



zGuardedIterator.closec                 C   s,   | j s(ztdt W n ty&   Y n0 d S )Nz4Iterator was garbage collected before it was closed.)rU   r   r   	Exceptionr1   r   r   r   __del__   s    zGuardedIterator.__del__)r   r   r   r5   rD   r7   TuplerN   r   rM   r'   r2   rS   r4   re   r   r   r   r   rO      s   %rO   c                   @   s   e Zd ZdZdddddZdddd	d
Zeejej	eef  ej
ej	eje eef  ej	eef dddZeddddZeje ddddZejejeje 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
   N)appr   c                 C   s
   || _ d S r"   )rh   )r&   rh   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   rl   )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&   ri   rb   script_nameZ	path_infor   r   r   check_environ   s:    
zLintMiddleware.check_environ)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 )Nrt   r)   r   r   z!Status code must be three digits.r   rj    zInvalid value for status zJ. Valid status strings are three digits, a space and a status explanation.rX   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   rN   r   listtupler^   
isinstancer   check_headers)	r&   rt   r`   ru   Zstatus_code_strr_   itemnamevaluer   r   r   check_start_response  sD    

z#LintMiddleware.check_start_response)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.rj   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   r|   N  s(    


&

zLintMiddleware.check_headers)app_iterr   c                 C   s   t |trtdtdd 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{   r7   r   r   )r&   r   r   r   r   check_iteratori  s    
zLintMiddleware.check_iterator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  tjtjtj	t
gd f 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)   rm   rn   zwsgi.file_wrapperr   c                     s   t | dvr&tdt |  dtdd |r4tdt | d }| d }t | d	krX| 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   rE   )r(   r   rt   r`   ru   rF   rQ   r&   Zstart_responser   r   checking_start_response  s    
z8LintMiddleware.__call__.<locals>.checking_start_responser	   )r*   r   r   rs   r   r:   r   r5   r8   rK   r7   rh   castr   rO   rf   rN   r   )r&   r(   r   ri   r   r   r   r   r   rJ   s  s,    

zLintMiddleware.__call__)r   r   r   r   r'   rs   r=   r5   rM   rf   OptionalTypeBaseExceptionr   rN   r   r   r|   rD   r7   r   r8   rJ   r   r   r   r   rg      s   .6
rg   ) r   typingr5   typesr   urllib.parser   warningsr   Zdatastructuresr   httpr   Zwsgir   TYPE_CHECKINGZ_typeshed.wsgir	   r
   r   Warningr   r   r=   rL   r   r   r   r:   rE   rO   rg   r   r   r   r   <module>   s&   	4P