o
    0c6                  	   @   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dededejddf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                   @      e Zd ZdZdS )WSGIWarningz Warning class for WSGI warnings.N__name__
__module____qualname____doc__ r   r   N/var/www/html/gps/gps/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objneedreturnc                 C   s<   t ||urt| d|jdt |jdtdd d S d S )Nz
 requires z, got .   
stacklevel)typer   r   r   )r   r   r   r   r   r   
check_type&   s   
r    c                   @   sf   e Zd ZdejddfddZdejdefddZdejdefd	d
Z	dej
e fddZdddZdS )InputStreamstreamr   Nc                 C   
   || _ d S N_streamselfr"   r   r   r   __init__0      
zInputStream.__init__argsc                 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(   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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   r1   D   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&   r0   r   r   r(   r   r   r   __iter__W   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&   closer3   r   r   r   r7   ^      zInputStream.closer   N)r   r   r   tBinaryIOr)   Anybytesr.   r1   Iteratorr4   r7   r   r   r   r   r!   /   s    r!   c                   @   s^   e Zd ZdejddfddZdeddfddZdd	d
Zdej	e ddfddZ
dddZdS )ErrorStreamr"   r   Nc                 C   r#   r$   r%   r'   r   r   r   r)   d   r*   zErrorStream.__init__sc                 C   s   t d|t | j| d S )Nzwsgi.error.write())r    strr&   writer(   r@   r   r   r   rB   g   s   zErrorStream.writec                 C   s   | j   d S r$   )r&   flushr3   r   r   r   rD   k   s   zErrorStream.flushseqc                 C   s   |D ]}|  | qd S r$   )rB   )r(   rE   liner   r   r   
writelinesn   s   zErrorStream.writelinesc                 C   r5   )Nz(The application closed the error stream!r   r   r6   r3   r   r   r   r7   r   r8   zErrorStream.closer9   )r   r   r   r:   TextIOr)   rA   rB   rD   IterablerG   r7   r   r   r   r   r?   c   s    
r?   c                   @   sF   e Zd Zdejegdf deje ddfddZdeddfdd	Z	dS )
GuardedWriterB   Nchunksr   c                 C   s   || _ || _d S r$   )_write_chunks)r(   rB   rK   r   r   r   r)   x   s   
zGuardedWrite.__init__r@   c                 C   s*   t d|t | | | jt| d S )Nzwrite())r    r=   rL   rM   appendr-   rC   r   r   r   __call__|   s   
zGuardedWrite.__call__)
r   r   r   r:   Callabler=   Listintr)   rO   r   r   r   r   rJ   w   s    (rJ   c                   @   sh   e Zd Zdeje dejeef dej	e ddfddZ
ddd	Zdefd
dZdddZdddZdS )GuardedIteratoriteratorheaders_setrK   r   Nc                 C   s(   || _ t|j| _d| _|| _|| _d S )NF)	_iteratorr2   __next___nextclosedrU   rK   )r(   rT   rU   rK   r   r   r   r)      s
   
zGuardedIterator.__init__c                 C   s   | S r$   r   r3   r   r   r   r4      s   zGuardedIterator.__iter__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)
rY   r   r   rX   rU   r    r=   rK   rN   r-   )r(   rvr   r   r   rW      s   zGuardedIterator.__next__c                 C   s  d| _ t| jdr| j  | jr| j\}}t| j}|jdtd}|dkrM|D ]\}}|	 }|dvrAt
|rAtd|dt q(|rKtd	t d S d S d
|  krWdk s\n |dkrv|dkrht| dt |rtt| dt d S d S |d ur||krtdt d S d S d S d S )NTr7   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.)rY   hasattrrV   r7   rU   sumrK   getrR   lowerr   r   r   r   )r(   status_codeheaders
bytes_sentcontent_lengthkey_valuer   r   r   r7      sH   



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.)rY   r   r   	Exceptionr3   r   r   r   __del__   s   
zGuardedIterator.__del__)r   rS   r9   )r   r   r   r:   rI   r=   TuplerR   r   rQ   r)   r4   rW   r7   rj   r   r   r   r   rS      s    


%rS   c                
   @   s   e Zd ZdZdddZdd
dZdedejej	eef  dej
ej	eje eef  dej	eef fddZdeddfddZdeje ddfddZdejdejdeje f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   Nc                 C   r#   r$   )rm   )r(   rm   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   rs   )r,   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   ra   )r(   rn   rg   script_name	path_infor   r   r   check_environ   s>   

zLintMiddleware.check_environstatusrd   exc_infoc           	      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rtdtdd | dkrtdtdd qT|d urt|t
stdtdd t|}| | ||fS )Nr~   r,   r   r   z!Status code must be three digits.r   ro    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    rA   splitr-   isdigitr   r   rR   r   listtuplerb   
isinstancer   check_headers)	r(   r~   rd   r   status_code_strrc   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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.ro   r   r   r,   "zUnquoted etag emitted.locationz+Absolute URLs required for location header.)ra   
startswithr   r   r   netloc)r(   rd   r   r   r   r   r   r   N  s,   


&


zLintMiddleware.check_headersapp_iterc                 C   s    t |trtdtdd d S 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   r=   r   r   )r(   r   r   r   r   check_iteratori  s   

zLintMiddleware.check_iteratorr+   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
tjdtjdtj	t
gd f f 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,   rt   ru   zwsgi.file_wrapperr+   r   r   c                     s   t | dvrtdt |  dtdd |rtdt | 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   )r-   r   r   r   rJ   )r+   r   r~   rd   r   rK   rU   r(   start_responser   r   checking_start_response  s   
z8LintMiddleware.__call__.<locals>.checking_start_responser	   )r-   r   r   r}   r!   r?   r   r:   r<   rP   r=   rm   castr   rS   rk   rR   r   )r(   r+   r   rn   r   r   r   r   r   rO   s  s4   

zLintMiddleware.__call__)rm   r
   r   N)rn   r   r   N)r   r   r   r   r)   r}   rA   r:   rQ   rk   OptionalTypeBaseExceptionr   rR   r   r   r   rI   r=   r   r<   rO   r   r   r   r   rl      s$    

,
6$
rl   ) r   typingr:   typesr   urllib.parser   warningsr   datastructuresr   httpr   wsgir   TYPE_CHECKING_typeshed.wsgir	   r
   r   Warningr   r   rA   objectr   r    r!   r?   rJ   rS   rl   r   r   r   r   <module>   s(     	4P