o
    ٷiN"                     @   s   d Z ddlZddlZddlmZ ddlmZmZmZm	Z	 ddl
mZmZ ddlmZ ddlmZmZmZmZmZ G dd	 d	ZG d
d dZG dd dZdedefddZdS )zkAGSI Brotli middleware build on top of starlette.

Code is based on GZipMiddleware shipped with starlette.
    N)NoReturn)	MODE_FONTMODE_GENERIC	MODE_TEXT
Compressor)HeadersMutableHeaders)GZipResponder)ASGIAppMessageReceiveScopeSendc                   @   s   e Zd ZdZeZeZeZ	dS )ModezBrotli available modes.N)
__name__
__module____qualname____doc__r   genericr   textr   font r   r   L/home/ubuntu/.local/lib/python3.10/site-packages/gradio/brotli_middleware.pyr      s
    r   c                   @   s   e Zd ZdZ							dd	ed
ededededededee dB ddfddZ	de
dededdfddZde
defddZde
defddZdS )BrotliMiddlewarez#Brotli middleware public interface.   r      r     TNappqualitymodelgwinlgblockminimum_sizegzip_fallbackexcluded_handlersreturnc	           	      C   sR   || _ || _tt|| _|| _|| _|| _|| _|r$dd |D | _	dS g | _	dS )ao  
        Arguments.

        mode: The compression mode can be:
            generic, text (*default*. Used for UTF-8 format text input)
            or font (for WOFF 2.0).
        quality: Controls the compression-speed vs compression-
            density tradeoff. The higher the quality, the slower the compression.
            Range is 0 to 11.
        lgwin: Base 2 logarithm of the sliding window size. Range
            is 10 to 24.
        lgblock: Base 2 logarithm of the maximum input block size.
            Range is 16 to 24. If set to 0, the value will be set based on the
            quality.
        minimum_size: Only compress responses that are bigger than this value in bytes.
        gzip_fallback: If True, uses gzip encoding if br is not in the Accept-Encoding header.
        excluded_handlers: List of handlers to be excluded from being compressed.
        c                 S   s   g | ]}t |qS r   )recompile).0pathr   r   r   
<listcomp>@   s    z-BrotliMiddleware.__init__.<locals>.<listcomp>N)
r   r   getattrr   r   r"   r    r!   r#   r$   )	selfr   r   r   r    r!   r"   r#   r$   r   r   r   __init__   s   
zBrotliMiddleware.__init__scopereceivesendc                    s   |  |s|d dks| |s| |||I d H S t|d}d|ddv rBt| j| j| j| j| j	| j
}||||I d H  d S | jr_d|ddv r_t| j| j
}||||I d H  d S | |||I d H  d S )Ntypehttp)r.   brAccept-Encoding gzip)_is_handler_excluded_is_compressible_file_typer   r   getBrotliResponderr   r   r    r!   r"   r#   r	   )r,   r.   r/   r0   headersbr_respondergzip_responderr   r   r   __call__D   s0   
zBrotliMiddleware.__call__c                    s$   | dd t fdd| jD S )Nr)   r5   c                 3   s    | ]}|  V  qd S N)search)r(   patternhandlerr   r   	<genexpr>`   s    z8BrotliMiddleware._is_handler_excluded.<locals>.<genexpr>)r9   anyr$   )r,   r.   r   rB   r   r7   ]   s   z%BrotliMiddleware._is_handler_excludedc                 C   s>   | dd}h d}d|v rd|dd   }||v S dS )z>Check if the requested file has a compressible file extension.r)   r5   >   .js.md.css.csv.htm.svg.tsv.txt.xml.html.json.F)r9   splitlower)r,   r.   r)   compressible_extensions	extensionr   r   r   r8   d   s   z+BrotliMiddleware._is_compressible_file_type)r   r   r   r   r   TN)r   r   r   r   r
   intstrboollistr-   r   r   r   r>   r7   r8   r   r   r   r   r      s>    
	

)r   c                   @   sj   e Zd ZdZdededededededd	fd
dZdede	de
dd	fddZdedd	fddZdd Zd	S )r:   zBrotli Interface.r   r   r   r    r!   r"   r%   Nc                 C   sd   || _ || _|| _|| _|| _|| _t| _i | _d| _	d| _
t| j| j| j| jd| _t | _d S )NF)r   r   r    r!   )r   r   r   r    r!   r"   unattached_sendr0   initial_messagestartedcontent_encoding_setr   br_fileioBytesIO	br_buffer)r,   r   r   r   r    r!   r"   r   r   r   r-   ~   s   	zBrotliResponder.__init__r.   r/   r0   c                    s"   || _ | ||| jI d H  d S r?   )r0   r   send_with_brotli)r,   r.   r/   r0   r   r   r   r>      s   zBrotliResponder.__call__messagec                    s  |d }|dkr|| _ t| j d d}d|v | _dS |dkr;| jr;| js1d| _| | j I dH  | |I dH  dS |dkr| jsd| _|d	d
}|dd}t|| jk rm|sm| | j I dH  | |I dH  dS |s| || j	
  }t| j d d}d|d< tt||d< |d ||d	< | | j I dH  | |I dH  dS t| j d d}d|d< |d |d= | j| || j	   | j |d	< | jd | j  | | j I dH  | |I dH  dS |dkrM|d	d
}|dd}| j| || j	   |s1| j| j	
  | j |d	< | j  | |I dH  dS | j |d	< | jd | j  | |I dH  dS dS )zApply compression using brotli.r1   zhttp.response.startr;   )rawzcontent-encodingzhttp.response.bodyTNbody    	more_bodyFr3   zContent-EncodingzContent-Lengthr4   r   )r\   r   r^   r]   r0   r9   lenr"   _processr_   finishr   rX   add_vary_headerrb   writeflushgetvalueseektruncateclose)r,   rd   message_typer;   rf   rh   r   r   r   rc      sh   





z BrotliResponder.send_with_brotlic                 C   s$   t | jdr| j|S | j|S )aZ  Workaround to support both brotli and brotlipy

        Before the official Google brotli repository offered a Python version,
        there was a separate package to connect to brotli. These APIs are nearly
        identical except that the official Google API has Compressor.process
        while the brotlipy API has Compress.compress
        process)hasattrr_   rt   compress)r,   rf   r   r   r   rj      s   zBrotliResponder._process)r   r   r   r   r
   rW   r   r-   r   r   r   r>   r   rc   rj   r   r   r   r   r:   {   s(    
>r:   _r%   c                    s
   t d)Nzsend awaitable not set)RuntimeError)rw   r   r   r   r[      s   r[   )r   r`   r&   typingr   brotlir   r   r   r   starlette.datastructuresr   r   starlette.middleware.gzipr	   starlette.typesr
   r   r   r   r   r   r   r:   r[   r   r   r   r   <module>   s    ck