o
    j>                     @   s   d dl Z d dlZd dlZd dlZd dlZd dlmZ d dlmZm	Z	m
Z
 d dlmZmZ d dlmZ dZedZeeZG dd	 d	ZG d
d de jZdd Zdd Zdd Zdd Zdd ZG dd dZdS )    N)TOKEN_RE)ConfigurationProblemInvalidHeaderInvalidHeaderName)SERVER_SOFTWARESERVER)utili?z[ \t\x21-\x7e\x80-\xff]*c                   @   s.   e Zd ZdddZdd Zdd Zdd	 Zd
S )FileWrapper    c                 C   s&   || _ || _t|dr|j| _d S d S )Nclose)filelikeblksizehasattrr   )selfr   r    r   G/var/www/ai-app/venv/lib/python3.10/site-packages/gunicorn/http/wsgi.py__init__   s
   
zFileWrapper.__init__c                 C   s   | j | j}|r|S tN)r   readr   
IndexError)r   keydatar   r   r   __getitem__#      zFileWrapper.__getitem__c                 C   s   | S r   r   r   r   r   r   __iter__)   s   zFileWrapper.__iter__c                 C   s   | j | j}|r|S tr   )r   r   r   StopIteration)r   r   r   r   r   __next__,   r   zFileWrapper.__next__N)r
   )__name__
__module____qualname__r   r   r   r   r   r   r   r   r	      s
    
r	   c                   @   s   e Zd Zdd Zdd ZdS )WSGIErrorsWrapperc                 C   s`   t d}|j}g | _|jdkr| jtj |dd  }|D ]}t|dr-| j|j	 qd S )Nzgunicorn.error-   stream)
logging	getLoggerhandlersstreamserrorlogappendsysstderrr   r$   )r   cfgr)   r'   hr   r   r   r   5   s   


zWSGIErrorsWrapper.__init__c              	   C   sJ   | j D ]}z|| W n ty   ||d Y nw |  qd S )NzUTF-8)r(   writeUnicodeErrorencodeflush)r   r   r$   r   r   r   r/   E   s   

zWSGIErrorsWrapper.writeN)r   r   r    r   r/   r   r   r   r   r!   3   s    r!   c              	   C   s    t | dd| jdkdtdtdS )Nr#   r   Fr#   T)zwsgi.errorszwsgi.versionzwsgi.multithreadzwsgi.multiprocesszwsgi.run_oncezwsgi.file_wrapperzwsgi.input_terminatedr   )r!   workersr	   r   )r-   r   r   r   base_environN   s   r5   c                 C   sB   t |}|| j|| j| j| jdddd | jD  d |S )NzHTTP/%s.c                 S   s   g | ]}t |qS r   )str).0vr   r   r   
<listcomp>c   s    z#default_environ.<locals>.<listcomp>)z
wsgi.inputzgunicorn.socketREQUEST_METHODQUERY_STRINGRAW_URISERVER_PROTOCOL)r5   updatebodymethodqueryurijoinversion)reqsockr-   envr   r   r   default_environ[   s   rI   c                 C   s:   | j }|si S |d |d t|d |d t|d dS )Nproxy_protocolclient_addrclient_port
proxy_addr
proxy_port)PROXY_PROTOCOLREMOTE_ADDRREMOTE_PORT
PROXY_ADDR
PROXY_PORT)proxy_protocol_infor7   )rF   infor   r   r   proxy_environh   s   

rV   c                    s    fdd}|S )a   Create a wsgi.early_hints callback for sending 103 Early Hints.

    This allows WSGI applications to send 103 Early Hints responses
    before the final response, enabling browsers to preload resources.

    Args:
        req: The request object
        sock: The socket to write to
        resp: The Response object to check if headers have been sent

    Returns:
        A callback function that accepts a list of (name, value) header tuples
        and sends a 103 Early Hints response.

    Note:
        - Early hints are only sent for HTTP/1.1 or later clients
        - HTTP/1.0 clients will silently ignore the callback
        - Multiple calls are allowed (sending multiple 103 responses)
        - Calls after response has started are silently ignored
    c                    s   j rdS  jdk rdS d}| D ]@\}}t|tr|d}t|tr(|d}t|s3td| t|s>t	d| |
d}|| d| dd7 }q|d	7 }t| dS )
a}  Send 103 Early Hints response.

        Args:
            headers: List of (name, value) header tuples, typically Link headers
                     Example: [('Link', '</style.css>; rel=preload; as=style')]

        Raises:
            InvalidHeaderName: If a header name is not a valid HTTP token.
            InvalidHeader: If a header value contains invalid characters.
        N)r#   r#   s   HTTP/1.1 103 Early Hints
latin-1%r 	z: z
   
)headers_sentrE   
isinstancebytesdecoder   	fullmatchr   HEADER_VALUE_REr   stripr1   r   r/   )headersresponsenamevaluerF   resprG   r   r   send_early_hints   s$   







z4_make_early_hints_callback.<locals>.send_early_hintsr   )rF   rG   rg   rh   r   rf   r   _make_early_hints_callbackw   s   -ri   c                 C   s4  t | ||}t| ||}d }tjdd}| jr|d | jD ]<\}	}
|	dkr+|
}n|	dkr2|
}n|	dkr;|
|d< q |	dkrD|
|d< q d	|	d
d }||v rXd|| |
f }
|
||< q | j	|d< t
|trl||d< nt
|trx| |d< n|d |d< t|d |d< t
|tr|d}t|dkr|r|d}t|dkr| j	dkr|d n| j	dkr|d n|d n|d |d |d< t|d |d< | j}|r||std||f |t|d  }t||d< ||d< |t|  t| |||d< t| dr| j|d< | j|d< ||fS )NSCRIPT_NAME s   HTTP/1.1 100 Continue

HOSTzCONTENT-TYPECONTENT_TYPEzCONTENT-LENGTHCONTENT_LENGTHHTTP_r"   _z%s,%szwsgi.url_schemerP   r   r#   rQ   :httpP   httpsi  SERVER_NAMESERVER_PORTz2Request path %r does not start with SCRIPT_NAME %r	PATH_INFOzwsgi.early_hintspriority_weightzgunicorn.http2.priority_weightz"gunicorn.http2.priority_depends_on)ResponserI   osenvironget_expected_100_continuesendrb   replaceschemer\   r7   r]   r^   splitlenr*   path
startswithr   r   unquote_to_wsgi_strr?   rV   ri   r   rx   priority_depends_on)rF   rG   clientserverr-   rg   r{   hostscript_namehdr_name	hdr_valuer   	path_infor   r   r   create   sx   















r   c                   @   sv   e Zd Zdd Zdd Zdd Zddd	Zd
d Zdd Zdd Z	dd Z
dd Zdd Zdd Zdd Zdd ZdS )ry   c                 C   sL   || _ || _t| _d | _d| _d| _g | _d| _d | _	d| _
d| _|| _d S )NFr   )rF   rG   r   rE   statuschunked
must_closerb   r[   response_lengthsentupgrader-   )r   rF   rG   r-   r   r   r   r   "  s   
zResponse.__init__c                 C   s
   d| _ d S )NT)r   r   r   r   r   force_close0  s   
zResponse.force_closec                 C   sT   | j s| j r
dS | jd us| jrdS | jjdkrdS | jdk s&| jdv r(dS dS )NTFHEAD      i0  )r   rF   should_closer   r   rA   status_coder   r   r   r   r   3  s   zResponse.should_closeNc                 C   s   |rz| j r| jrt|d |d |d  W d }nd }w | j d ur&td|| _ zt| j  d | _W n tyA   d | _Y nw | 	| | 
 | _| jS )Nr   r#      zResponse headers already set!)r   r[   r   reraiseAssertionErrorintr   r   
ValueErrorprocess_headers
is_chunkedr   r/   )r   r   rb   exc_infor   r   r   start_response>  s"   



zResponse.start_responsec                 C   s   |D ]q\}}t |tstd| t|std| t |ts'td| t|s2td| |d}|	 }|dkrEt
|| _n&t|rk|dkrX|	 dkrWd| _n|dkrj|	 dkrj| j||f q| j||f qd S )	Nz%r is not a stringrX   rY   zcontent-length
connectionr   T	websocket)r\   r7   	TypeErrorr   r_   r   r`   r   ra   lowerr   r   r   
is_hoppishr   rb   r*   )r   rb   rd   re   lnamer   r   r   r   V  s0   





zResponse.process_headersc                 C   s@   | j d urdS | jjdkrdS | jjdkrdS | jdv rdS dS )NFr3   r   r   T)r   rF   rE   rA   r   r   r   r   r   r   v  s   

zResponse.is_chunkedc                 C   sl   | j rd}n	|  rd}nd}d| jjd | jjd | jf d| j dt  d	| g}| jr4|d
 |S )Nr   r   z
keep-alivezHTTP/%s.%s %s
r   r#   zServer: %s
z
Date: %s
zConnection: %s
zTransfer-Encoding: chunked
)	r   r   rF   rE   r   r   	http_dater   r*   )r   r   rb   r   r   r   default_headers  s   

zResponse.default_headersc                 C   sV   | j rd S |  }|dd | jD  dd| }t| jt|d d| _ d S )Nc                 S   s   g | ]
\}}d ||f qS )z%s: %s
r   )r8   kr9   r   r   r   r:     s    z)Response.send_headers.<locals>.<listcomp>z%s
rk   rW   T)	r[   r   extendrb   rD   r   r/   rG   to_bytestring)r   tosend
header_strr   r   r   send_headers  s   
zResponse.send_headersc                 C   s   |    t|tstd| t|}|}| jd ur5| j| jkr"d S t| j| j |}||k r5|d | }| jr>|dkr>d S |  j|7  _t	
| j|| j d S )Nz%r is not a byter   )r   r\   r]   r   r   r   r   minr   r   r/   rG   )r   argarglenr   r   r   r   r/     s   

zResponse.writec                 C   s   | j jduS )NF)r-   sendfiler   r   r   r   can_sendfile  s   zResponse.can_sendfilec              	   C   s   | j js|  s
dS t|jsdS |j }zt|dtj	}| j
d u r0t|j}|| }n| j
}W n ttjfyA   Y dS w |   |  rWd| }| j|d |dkre| jj|j||d |  ro| jd t||tj dS )NFr   z%X
zutf-8)offsetcountrZ   T)r-   is_sslr   r   
has_filenor   filenorz   lseekSEEK_CURr   fstatst_sizeOSErrorioUnsupportedOperationr   r   rG   sendallr1   r   SEEK_SET)r   respiterr   r   filesizenbytes
chunk_sizer   r   r   r     s2   


zResponse.sendfilec                 C   s&   |  |s|D ]	}| | qd S d S r   )r   r/   )r   r   itemr   r   r   
write_file  s
   
zResponse.write_filec                 C   s*   | j s|   | jrt| jd d S d S )N    )r[   r   r   r   write_chunkrG   r   r   r   r   r     s
   zResponse.closer   )r   r   r    r   r   r   r   r   r   r   r   r/   r   r   r   r   r   r   r   r   ry      s    
 
!ry   )r   r%   rz   rer+   gunicorn.http.messager   gunicorn.http.errorsr   r   r   gunicornr   r   r   BLKSIZEcompiler`   r&   r   logr	   	RawIOBaser!   r5   rI   rV   ri   r   ry   r   r   r   r   <module>   s(   

Ed