U
    Rh                     @  s\   d dl mZ d dlZd dlmZmZmZmZ G dd dZdddd	d
Z	G dd dZ
dS )    )annotationsN)ASGI3ApplicationASGIReceiveCallableASGISendCallableScopec                   @  s8   e Zd ZdZdddddddZd	d
dddddZdS )ProxyHeadersMiddlewareaB  Middleware for handling known proxy headers

    This middleware can be used when a known proxy is fronting the application,
    and is trusted to be properly setting the `X-Forwarded-Proto` and
    `X-Forwarded-For` headers with the connecting client information.

    Modifies the `client` and `scheme` information so that they reference
    the connecting client, rather that the connecting proxy.

    References:
    - <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers#Proxies>
    - <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For>
    	127.0.0.1r   list[str] | strNone)apptrusted_hostsreturnc                 C  s   || _ t|| _d S N)r   _TrustedHostsr   )selfr   r    r   F./venv/lib/python3.8/site-packages/uvicorn/middleware/proxy_headers.py__init__   s    zProxyHeadersMiddleware.__init__r   r   r   )scopereceivesendr   c                   s   |d dkr |  |||I d H S |d}|r6|d nd }|| jkrt|d }d|kr|d d }|dkr|d d	kr|d
d|d< n||d< d|kr|d d}| j|}	|	rd}
|	|
f|d< |  |||I d H S )NtypeZlifespanZclientr   headerss   x-forwarded-protolatin1>   httphttpswsswsZ	websocketr   r   Zschemes   x-forwarded-for)r   getr   dictdecodestripreplaceget_trusted_client_host)r   r   r   r   Zclient_addrZclient_hostr   Zx_forwarded_protox_forwarded_forhostZportr   r   r   __call__   s&    

zProxyHeadersMiddleware.__call__N)r   )__name__
__module____qualname____doc__r   r&   r   r   r   r   r      s   r   strz	list[str])valuer   c                 C  s   dd |  dD S )Nc                 S  s   g | ]}|  qS r   )r!   ).0itemr   r   r   
<listcomp>@   s     z$_parse_raw_hosts.<locals>.<listcomp>,)split)r,   r   r   r   _parse_raw_hosts?   s    r2   c                   @  s@   e Zd ZdZdddddZddd	d
dZdddddZdS )r   z(Container for trusted hosts and networksr	   r
   )r   r   c              	   C  s   |ddgfk| _ t | _t | _t | _| j st|tr@t|}|D ]~}d|krz| jt	
| W q tk
r   | j| Y qX qDz| jt	| W qD tk
r   | j| Y qDX qDd S )N*/)always_trustsettrusted_literalsr   trusted_networks
isinstancer+   r2   add	ipaddressZ
ip_network
ValueError
ip_address)r   r   r%   r   r   r   r   F   s"    
z_TrustedHosts.__init__z
str | Nonebool)r%   r   c                   sj   | j r
dS |sdS z4t|  | jkr.W dS t fdd| jD W S  tk
rd   || jk Y S X d S )NTFc                 3  s   | ]} |kV  qd S r   r   )r-   ZnetZipr   r   	<genexpr>x   s     z-_TrustedHosts.__contains__.<locals>.<genexpr>)r5   r;   r=   r   anyr8   r<   r7   )r   r%   r   r?   r   __contains__m   s    

z_TrustedHosts.__contains__r+   )r$   r   c                 C  s<   t |}| jr|d S t|D ]}|| kr|  S q|d S )zExtract the client host from x_forwarded_for header

        In general this is the first "untrusted" host in the forwarded for list.
        r   )r2   r5   reversed)r   r$   Zx_forwarded_for_hostsr%   r   r   r   r#   }   s    
z%_TrustedHosts.get_trusted_client_hostN)r'   r(   r)   r*   r   rB   r#   r   r   r   r   r   C   s   'r   )Z
__future__r   r;   Zuvicorn._typesr   r   r   r   r   r2   r   r   r   r   r   <module>   s
   7