o
    i2                     @   s
  d 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
 dd	lmZ zdd
lmZ W n eyC   dd
lmZ Y nw G dd deZG dd deZdddZG dd deZG dd deZG dd deZeG dd deZG dd de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
    )warn   )implements_iterator)PY2)string_types)Headers)is_entity_header)FileWrapper)urlparsec                   @      e Zd ZdZdS )WSGIWarningz Warning class for WSGI warnings.N__name__
__module____qualname____doc__ r   r   S/var/www/edux/Edux_v2/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      c                 C   s,   t |turtd| t |jf t d S d S )Nz'%s' requires strings, got '%s')typestrr   r   r   )contextobj
stacklevelr   r   r   check_string&   s   r   c                   @   4   e Zd Zdd Zdd Zdd Zdd Zd	d
 ZdS )InputStreamc                 C   
   || _ d S N_streamselfstreamr   r   r   __init__/      
zInputStream.__init__c                 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   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$   argsr   r   r   r+   2   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(   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/   C   s   zInputStream.readlinec                 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"   r.   r   r   r$   r   r   r   __iter__V   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"   closer1   r   r   r   r5   ]      zInputStream.closeN)r   r   r   r&   r+   r/   r2   r5   r   r   r   r   r   .   s    r   c                   @   r   )ErrorStreamc                 C   r   r    r!   r#   r   r   r   r&   c   r'   zErrorStream.__init__c                 C   s   t d| | j| d S )Nzwsgi.error.write())r   r"   writer$   sr   r   r   r8   f   s   
zErrorStream.writec                 C   s   | j   d S r    )r"   flushr1   r   r   r   r;   j   s   zErrorStream.flushc                 C   s   |D ]}|  | qd S r    )r8   )r$   seqliner   r   r   
writelinesm   s   zErrorStream.writelinesc                 C   r3   )Nz(The application closed the error stream!r   r(   r4   r1   r   r   r   r5   q   r6   zErrorStream.closeN)r   r   r   r&   r8   r;   r>   r5   r   r   r   r   r7   b   s    r7   c                   @   s   e Zd Zdd Zdd ZdS )GuardedWritec                 C   s   || _ || _d S r    )_write_chunks)r$   r8   chunksr   r   r   r&   w   s   
zGuardedWrite.__init__c                 C   s*   t d| | j| | jt| d S )Nzwrite())r   r@   r8   rA   appendr*   r9   r   r   r   __call__{   s   
zGuardedWrite.__call__N)r   r   r   r&   rD   r   r   r   r   r?   v   s    r?   c                   @   r   )GuardedIteratorc                 C   s:   || _ trt|j| _nt|j| _d| _|| _|| _d S )NF)		_iteratorr   r0   next_next__next__closedheaders_setrB   )r$   iteratorrK   rB   r   r   r   r&      s   
zGuardedIterator.__init__c                 C   s   | S r    r   r1   r   r   r   r2      s   zGuardedIterator.__iter__c                 C   sN   | j r
tdtdd |  }| jstdtdd td| | jt| |S )Nz Iterated over closed 'app_iter'.r   r(   z8The application returned before it started the response.zapplication iterator items)	rJ   r   r   rH   rK   r   rB   rC   r*   )r$   rvr   r   r   rI      s   
zGuardedIterator.__next__c                 C   s  d| _ t| jdr| j  | jr| j\}}t| j}|jdtd}|dkrK|D ]\}}|	 }|dvr?t
|r?td| t q(|rItdt d S d S d	|  krUd
k sZn |dkrr|dkretd| t |rptd| t d S d S |d ur||krtdt d S d S d S d S )NTr5   zcontent-length)r   i0  )expireszcontent-locationz'Entity header %r found in 304 response.z#304 responses must not have a body.d         r   z/%r responses must have an empty content length.z"%r responses must not have a body.zGContent-Length and the number of bytes sent to the client do not match.)rJ   hasattrrF   r5   rK   sumrB   getintlowerr   r   r   r   )r$   status_codeheaders
bytes_sentcontent_lengthkey_valuer   r   r   r5      sL   



zGuardedIterator.closec                 C   s0   | j sztdt W d S  ty   Y d S w d S )Nz4Iterator was garbage collected before it was closed.)rJ   r   r   	Exceptionr1   r   r   r   __del__   s   
zGuardedIterator.__del__N)r   r   r   r&   r2   rI   r5   r^   r   r   r   r   rE      s    
'rE   c                   @   s@   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 check are:

    -   invalid status codes
    -   non-bytestrings 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)
    c                 C   r   r    )app)r$   r`   r   r   r   r&      r'   zLintMiddleware.__init__c                 C   s   t |turtdtdd dD ]}||vrtd| tdd q|d dkr,td	tdd |d
d}|dd}|rI|d dkrItd| tdd |r\|d dkr^t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 %r not foundr   re   )r)   r   z"Environ is not a WSGI 1.0 environ.SCRIPT_NAME 	PATH_INFOr   /z-'SCRIPT_NAME' does not start with a slash: %rz+'PATH_INFO' does not start with a slash: %r)r   dictr   r   rT   )r$   environr[   script_name	path_infor   r   r   check_environ   s>   
zLintMiddleware.check_environc                 C   s\  t d| |d dd }t|dks| sttddd t|dk s+|d dkr3ttd	dd t|}|d
k rCttddd t|turQttddd |D ]<}t|t	usat|dkrittddd |\}}t|t
usyt|t
urttddd | dkrttddd qS|d urt|t	sttddd t|}| | ||fS )Nstatusr)   r   r   z Status code must be three digitsr(   ra    zeInvalid value for status %r.  Valid status strings are three digits, a space and a status explanationrO   zstatus code < 100 detectedzheader list is not a listr   z Headers must tuple 2-item tupleszheader items must be stringszFThe status header is not supported due to conflicts with the CGI spec.zinvalid value for exc_info)r   splitr*   isdigitr   r   rU   r   listtupler   rV   
isinstancer   check_headers)r$   rq   rX   exc_inforW   itemnamevaluer   r   r   check_start_response  sF   
	
z#LintMiddleware.check_start_responsec                 C   s   | d}|d ur<|dr!|drttddd |dd  }|d d |d	d    kr3d
ks<n ttddd | d}|d urTt|jsVttddd d S d S d S )Netag)zW/w/r   z%weak etag indicator should be upcase.ra   r(   r   r)   "zunquoted etag emitted.locationz*absolute URLs required for location header)rT   
startswithr   r   r
   netloc)r$   rX   r~   r   r   r   r   rx   H  s(   


&


zLintMiddleware.check_headersc                 C   s    t |trtdtdd d S d S )NzThe application returned astring. The response will send one character at a time to the client, which will kill performance. Return a list or iterable instead.r   r(   )rw   r   r   r   )r$   app_iterr   r   r   check_iteratora  s   

zLintMiddleware.check_iteratorc                    s   t |dkrtdtdd |rtdtdd |\}| t|d |d< t|d |d< t|d< g g   fdd	}||}| t	| S )
Nr   zA WSGI app takes two arguments.r(   z+A WSGI app does not take keyword arguments.rf   rg   zwsgi.file_wrapperc                     s   t | dvrtdt |  tdd |rtdt | d d \}}t | dkr+| d }nd }|||d d < t||| S )N)r   r   z1Invalid number of arguments: %s, expected 2 or 3.r   r(   z1'start_response' does not take keyword arguments.r   )r*   r   r   r}   r?   )r-   kwargsrq   rX   ry   rB   rK   r$   start_responser   r   checking_start_response  s   


z8LintMiddleware.__call__.<locals>.checking_start_response)
r*   r   r   rp   r   r7   r	   r`   r   rE   )r$   r-   r   rm   r   r   r   r   r   rD   k  s"   

zLintMiddleware.__call__N)
r   r   r   r   r&   rp   r}   rx   r   rD   r   r   r   r   r_      s    ,0
r_   N)r   )r   warningsr   _compatr   r   r   datastructuresr   httpr   wsgir	   urllib.parser
   ImportErrorWarningr   r   r   objectr   r7   r?   rE   r_   r   r   r   r   <module>   s,    
4P