a
    ((a(                     @   s,  d dl Z d dlZd dlmZmZmZmZ ddlmZm	Z	m
Z
mZ ddlmZmZmZ ddlmZmZmZmZmZmZ ddlmZmZ ddlmZmZmZmZmZm Z m!Z! dd	l"m#Z#m$Z$ dd
l%m&Z&m'Z' ddlm(Z(m)Z)m*Z*m+Z+m,Z, ddl-m.Z. ddl/m0Z0m1Z1 ddl2T dgZ3e4e5Z6G dd deZ7dS )    N)	GeneratorListOptionalSequence   )CLIENT
CONNECTINGOPEN
Connection)HeadersHeadersLikeMultipleValuesError)InvalidHandshakeInvalidHeaderInvalidHeaderValueInvalidStatusCodeInvalidUpgradeNegotiationError)ClientExtensionFactory	Extension)build_authorization_basicbuild_extensionbuild_subprotocolparse_connectionparse_extensionparse_subprotocolparse_upgrade)
USER_AGENT
build_host)RequestResponse)ConnectionOptionExtensionHeaderOriginSubprotocolUpgradeProtocol)	parse_uri)
accept_keygenerate_key)*ClientConnectionc                       s   e Zd Zdeee eee  eee  ee	 ee
 d fddZedddZedd	d
dZeee dddZeee dddZeddddZed d fddZ  ZS )r*   N   )uriorigin
extensionssubprotocolsextra_headersmax_sizec                    s@   t  jtt|d t|| _|| _|| _|| _|| _	t
 | _d S )N)sidestater1   )super__init__r   r   r&   wsurir-   available_extensionsavailable_subprotocolsr0   r(   key)selfr,   r-   r.   r/   r0   r1   	__class__ X/Users/bob/PycharmProjects/fastapi/venv/lib/python3.9/site-packages/websockets/client.pyr5   0   s    	
zClientConnection.__init__)returnc                 C   s  t  }t| jj| jj| jj|d< | jjr:t| jj |d< | jdurN| j|d< d|d< d|d< | j	|d< d	|d
< | j
durtdd | j
D }||d< | jdurt| j}||d< | jdur| j}t|t r| }nt|tjjr| }|D ]\}}|||< q|dt t| jj|S )zT
        Create a WebSocket handshake request event to send to the server.

        HostAuthorizationNr#   	websocketUpgrader
   zSec-WebSocket-KeyZ13zSec-WebSocket-Versionc                 S   s   g | ]}|j | fqS r=   )nameZget_request_params).0extension_factoryr=   r=   r>   
<listcomp>Y   s   z,ClientConnection.connect.<locals>.<listcomp>Sec-WebSocket-ExtensionsSec-WebSocket-Protocolz
User-Agent)r   r   r6   hostportsecureZ	user_infor   r-   r9   r7   r   r8   r   r0   
isinstance	raw_itemscollectionsabcMappingitems
setdefaultr   r   resource_name)r:   headersZextensions_headerZprotocol_headerr0   rD   valuer=   r=   r>   connectA   s@    








zClientConnection.connect)responser?   c              
   C   sN  |j dkrt|j |j}tdd |dD g }tdd |D s^td|rXd|ndtd	d |d
D g }t|dkr|d 	 dkstd
|rd|ndz|d }W n^ t
y } ztd|W Y d}~n:d}~0  ty } ztdd|W Y d}~n
d}~0 0 |t| jkr2td|| || _| || _dS )a	  
        Check a handshake response received from the server.

        :param response: response
        :param key: comes from :func:`build_request`
        :raises ~websockets.exceptions.InvalidHandshake: if the handshake response
            is invalid

        e   c                 S   s   g | ]}t |qS r=   )r   rE   rV   r=   r=   r>   rG          z5ClientConnection.process_response.<locals>.<listcomp>r
   c                 s   s   | ]}|  d kV  qdS )upgradeN)lowerrZ   r=   r=   r>   	<genexpr>   r[   z4ClientConnection.process_response.<locals>.<genexpr>, Nc                 S   s   g | ]}t |qS r=   )r   rZ   r=   r=   r>   rG      r[   rC   r   r   rB   zSec-WebSocket-Acceptz/more than one Sec-WebSocket-Accept header found)status_coder   rU   sumget_allanyr   joinlenr]   KeyErrorr   r   r'   r9   r   process_extensionsr.   process_subprotocolsubprotocol)r:   rX   rU   
connectionr\   Z
s_w_acceptexcr=   r=   r>   process_responseq   s<    


z!ClientConnection.process_response)rU   r?   c           	   
   C   s   g }| d}|r| jdu r$tdtdd |D g }|D ]j\}}| jD ]F}|j|krZqJz|||}W n ty   Y qJY n0 ||  q<qJtd| d| q<|S )a.  
        Handle the Sec-WebSocket-Extensions HTTP response header.

        Check that each extension is supported, as well as its parameters.

        Return the list of accepted extensions.

        Raise :exc:`~websockets.exceptions.InvalidHandshake` to abort the
        connection.

        :rfc:`6455` leaves the rules up to the specification of each
        extension.

        To provide this level of flexibility, for each extension accepted by
        the server, we check for a match with each extension available in the
        client configuration. If no match is found, an exception is raised.

        If several variants of the same extension are accepted by the server,
        it may be configured severel times, which won't make sense in general.
        Extensions must implement their own requirements. For this purpose,
        the list of previously accepted extensions is provided.

        Other requirements, for example related to mandatory extensions or the
        order of extensions, may be implemented by overriding this method.

        rH   Nzno extensions supportedc                 S   s   g | ]}t |qS r=   )r   rE   header_valuer=   r=   r>   rG      r[   z7ClientConnection.process_extensions.<locals>.<listcomp>zUnsupported extension: name = z, params = )rb   r7   r   ra   rD   Zprocess_response_paramsr   append)	r:   rU   Zaccepted_extensionsr.   Zparsed_extensionsrD   Zresponse_paramsrF   	extensionr=   r=   r>   rg      s8    





z#ClientConnection.process_extensionsc                 C   s   d}| d}|r|| jdu r$tdtdd |D g }t|dkr\d|}td| |d	 }|| jvr|td
| |S )z
        Handle the Sec-WebSocket-Protocol HTTP response header.

        Check that it contains exactly one supported subprotocol.

        Return the selected subprotocol.

        NrI   zno subprotocols supportedc                 S   s   g | ]}t |qS r=   )r   rm   r=   r=   r>   rG      r[   z8ClientConnection.process_subprotocol.<locals>.<listcomp>r   r_   zmultiple subprotocols: r   zunsupported subprotocol: )rb   r8   r   ra   re   rd   r   )r:   rU   ri   r/   Zparsed_subprotocolsZsubprotocols_displayr=   r=   r>   rh      s    	



z$ClientConnection.process_subprotocol)requestr?   c                 C   s8   t d| j|j t d| j|j | j|  dS )zD
        Send a WebSocket handshake request to the server.

        z%s > GET %s HTTP/1.1z%s > %rN)loggerdebugr2   pathrU   Zwritesro   	serialize)r:   rq   r=   r=   r>   send_request  s    zClientConnection.send_request)NNNc              
   #   s   t | jj| jj| jjE d H }| jtks.J zhz| | W n> t	y| } z&|j
|d}tjddd W Y d }~nd }~0 0 | t W | j| n| j| 0 t  E d H  d S )N)	exceptionzInvalid handshakeT)exc_info)r    parsereaderZ	read_lineZ
read_exactZread_to_eofr3   r   rl   r   _replacerr   rs   Z	set_stater	   eventsro   r4   )r:   rX   rk   r;   r=   r>   ry     s    
$zClientConnection.parse)NNNNr+   )__name__
__module____qualname__strr   r#   r   r   r$   r   intr5   r   rW   r    rl   r   r   r   rg   rh   rv   r   ry   __classcell__r=   r=   r;   r>   r*   /   s&        

03H!
)8rO   loggingtypingr   r   r   r   rj   r   r   r	   r
   Zdatastructuresr   r   r   
exceptionsr   r   r   r   r   r   Zextensions.baser   r   rU   r   r   r   r   r   r   r   httpr   r   Zhttp11r   r    r!   r"   r#   r$   r%   r,   r&   utilsr'   r(   Zlegacy.client__all__	getLoggerr}   rr   r*   r=   r=   r=   r>   <module>   s     $	
