U
    dRf/                     @   sR  d Z ddlmZ ddlmZ ddlm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 ddlmZ ddlmZ ddlmZmZ dd	lmZmZmZ d
ZdZG dd deZG dd deZ G dd de!Z"G dd deZ#G dd de!Z$dddde e ddedf
ddZ%edddde e ddedf
ddZ&e e fddZ'dS ) a  
# Run server:
>>> import thriftpy2
>>> from thriftpy2.http import make_server
>>> pingpong = thriftpy2.load("pingpong.thrift")
>>>
>>> class Dispatcher(object):
>>>     def ping(self):
>>>         return "pong"

>>> server = make_server(pingpong.PingService, Dispatcher(),
                         host='127.0.0.1', port=6000)
>>> server.serve()

# Run client:
>>> import thriftpy2
>>> from thriftpy2.http import make_client
>>> pingpong = thriftpy2.load("pingpong.thrift")
>>> client = make_client(pingpong.PingService, host='127.0.0.1', port=6000)
>>> client.ping()

# Run HTTPS client with unverified SSL context for TESTING ONLY purpose:
>>> import ssl
>>> ssl_context_factory = ssl._create_unverified_context
>>> client = make_client(pingpong.PingService, host='example.com', port=443,
...                      scheme="https",
...                      ssl_context_factory=ssl_context_factory)
>>> client.ping()
    )absolute_importN)contextmanager)BytesIO)TBinaryProtocolFactory)TServer)TClient
TProcessor)TBufferedTransportFactoryTMemoryBufferTTransportBasez{scheme}://{host}:{port}{path}i0u  c                   @   s@   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dS )TFileObjectTransportz?Wraps a file-like object to make it work as a Thrift transport.c                 C   s
   || _ d S N)fileobj)selfr    r   2/tmp/pip-unpacked-wheel-jqs7l_7o/thriftpy2/http.py__init__9   s    zTFileObjectTransport.__init__c                 C   s   dS )NTr   r   r   r   r   isOpen<   s    zTFileObjectTransport.isOpenc                 C   s   | j   d S r   )r   closer   r   r   r   r   ?   s    zTFileObjectTransport.closec                 C   s   | j |S r   )r   read)r   szr   r   r   r   B   s    zTFileObjectTransport.readc                 C   s   | j | d S r   )r   writer   bufr   r   r   r   E   s    zTFileObjectTransport.writec                 C   s   | j   d S r   )r   flushr   r   r   r   r   H   s    zTFileObjectTransport.flushN)
__name__
__module____qualname____doc__r   r   r   r   r   r   r   r   r   r   r   6   s   r   c                   @   s   e Zd ZdZdd ZdS )ResponseExceptiona{  Allows handlers to override the HTTP response

    Normally, THttpServer always sends a 200 response.  If a handler wants
    to override this behavior (e.g., to simulate a misconfigured or
    overloaded web server during testing), it can raise a ResponseException.
    The function passed to the constructor will be called with the
    RequestHandler as its only argument.
    c                 C   s
   || _ d S r   )handler)r   r!   r   r   r   r   U   s    zResponseException.__init__N)r   r   r   r   r   r   r   r   r   r    L   s   r    c                   @   s"   e Zd ZdZdddZdd ZdS )THttpHeaderFactoryz4Default header factory return no custom headers
    Nc                 C   s   |r|| _ nt | _ dS )zInitialize a header factory
        @param headers(dict)
            A dictionary of static headers the factory generates
        N)_THttpHeaderFactory__headersdictr   headersr   r   r   r   \   s    zTHttpHeaderFactory.__init__c                 C   s   | j S r   )r#   r   r   r   r   get_headersf   s    zTHttpHeaderFactory.get_headers)N)r   r   r   r   r   r'   r   r   r   r   r"   Y   s   

r"   c                   @   s&   e Zd ZdZejfddZdd ZdS )THttpServerzA simple HTTP-based Thrift server
    This class is not very performant, but it is useful (for example) for
    acting as a mock version of an Apache-based PHP Thrift endpoint.
    c              	      sB   t j| |d||ddd |  G  fdddtj}|||| _dS )zSet up protocol factories and HTTP server.
        See http.server for server_address.
        See TServer for protocol factories.
        N)Ztransitrans_factoryiprot_factoryZotrans_factoryoprot_factoryc                       s   e Zd Z fddZdS )z,THttpServer.__init__.<locals>.RequestHandlerc              
      s   t | jd }t| j|}t|} j|} j	|}t
 } j	|}z j|| W n, tk
r } z||  W 5 d }~X Y n0X | d | dd |   | j|  d S )NContent-Length   zcontent-typeapplication/x-thrift)intr&   r   rfiler   r   r)   get_transportr*   get_protocolr
   r+   	processorprocessr    r!   Zsend_responseZsend_headerZend_headerswfiler   getvalue)r   Zcontent_lenr   ZitransiprotZotransZoprotZexnZthttpserverr   r   do_POST   s    
z4THttpServer.__init__.<locals>.RequestHandler.do_POSTN)r   r   r   r9   r   r8   r   r   RequestHandler   s   r:   )r   r   http_serverZBaseHTTPRequestHandlerhttpd)r   r3   server_addressr)   r*   Zserver_classr:   r   r8   r   r   o   s    

 zTHttpServer.__init__c                 C   s   | j   d S r   )r<   serve_foreverr   r   r   r   serve   s    zTHttpServer.serveN)r   r   r   r   r;   Z
HTTPServerr   r?   r   r   r   r   r(   j   s   	
/r(   c                   @   st   e Zd Z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eedrpeeZdS )THttpClientz,Http implementation of TTransport base.
    Nc                 C   s   t j|}|j| _| jdks"t| jdkr<|jp6tj| _n| jdkrT|jpPtj| _|j	| _
|j| _|jr~|  jd|j 7  _t | _d| _|pt | _d| _|r| | || _dS )zInitialize a HTTP Socket.

        @param uri(str)    The http_scheme:://host:port/path to connect to.
        @param timeout   timeout in ms
        )httphttpsrA   rB   z?%sN)urllibparseurlparseschemeAssertionErrorporthttp_client	HTTP_PORT
HTTPS_PORThostnamehostpathqueryr   _THttpClient__wbuf_THttpClient__httpr"   _http_header_factory_THttpClient__timeout
setTimeout_ssl_context_factory)r   uritimeoutssl_context_factoryhttp_header_factoryparsedr   r   r   r      s$    


zTHttpClient.__init__c                 C   sJ   | j dkr4| jr|  nd }tj| j| j|d| _nt| j| j| _d S )NrB   )context)rF   rU   rI   HTTPSConnectionrM   rH   rQ   HTTPConnection)r   ssl_contextr   r   r   open   s    


zTHttpClient.openc                 C   s   | j   d | _ d S r   )rQ   r   r   r   r   r   r      s    
zTHttpClient.closec                 C   s
   | j d k	S r   )rQ   r   r   r   r   r      s    zTHttpClient.isOpenc                 C   s,   t tdst|r"|dkr"|d nd | _d S )Ngetdefaulttimeoutr   g     @@)hasattrsocketNotImplementedErrorrS   )r   msr   r   r   rT      s    
zTHttpClient.setTimeoutc                 C   s   t || _d S r   )r"   rR   r%   r   r   r   setCustomHeaders   s    zTHttpClient.setCustomHeadersc                 C   s   | j |}|S r   )responser   )r   r   contentr   r   r   r      s    zTHttpClient.readc                 C   s   | j | d S r   )rP   r   r   r   r   r   r      s    zTHttpClient.writec                 C   s>  | j  }t | _ |sd S |  r*|   |   | jjd| jdd | j	d| j
 | j	dd | j	dtt| | j }|rd|krd	}tjtjd
 }|rd|tj|f }| j	d| |r| j  D ]\}}| j	|| q| j  | j| | j }|j|j|   | _| _| _|| _ d S )NPOSTT)	skip_hostHostzContent-Typer.   r,   z
User-AgentzPython/THttpClientr   z%s (%s))!rP   r6   r   r   r   r_   rQ   
putrequestrN   	putheaderrM   strlenrR   r'   osbasenamesysargvrC   rD   quoteitems
endheaderssendgetresponsestatusmsg
getheaderscodemessager&   rf   )r   dataZcustom_headers
user_agentscriptkeyvalrf   r   r   r   r      sD    

 


  zTHttpClient.flushc                    s    fdd}|S )Nc               	      s<   t  }t | d j d }z | |}W 5 t | X |S )Nr   )rb   r`   setdefaulttimeoutrS   )argskwargsorig_timeoutresultfr   r   _f  s    z&THttpClient.__with_timeout.<locals>._fr   )r   r   r   r   r   Z__with_timeout  s    	zTHttpClient.__with_timeoutr`   )NNN)r   r   r   r   r   r_   r   r   rT   re   r   r   r   Z_THttpClient__with_timeoutra   rb   r   r   r   r   r@      s     
	,
r@   	localhosti#   rA   c                 C   s   |
r8t j|
}|jp|}|jp"|}|jp,|}|jp6|}|rP|d dkrPd| }tj||||d}t	||	||}|
|}||}|  t| |S Nr   /)rF   rM   rH   rN   )rC   rD   rE   rL   rH   rF   rN   HTTP_URIformatr@   r1   r2   r_   r   servicerM   rH   rN   rF   proto_factorytrans_factoryrX   rY   rW   url
parsed_urlrV   Zhttp_socket	transportr7   r   r   r   make_client  s     





r   c                 c   s   |
r8t j|
}|jp|}|jp"|}|jp,|}|jp6|}|rP|d dkrPd| }tj||||d}t	||	||}|
|}z"||}|  t| |V  W 5 |  X d S r   )rC   rD   rE   rL   rH   rF   rN   r   r   r@   r1   r   r2   r_   r   r   r   r   r   client_context6  s$    





r   c                 C   s"   t | |}t|||f||d}|S )N)r)   r*   )r   r(   )r   r!   rM   rH   r   r   r3   serverr   r   r   make_serverR  s    

r   )(r   
__future__r   http.clientclientrI   Zhttp.serverr   r;   ro   rb   rq   rC   
contextlibr   ior   Zthriftpy2.protocolr   Zthriftpy2.serverr   Zthriftpy2.thriftr   r   Zthriftpy2.transportr	   r
   r   r   ZDEFAULT_HTTP_CLIENT_TIMEOUT_MSr   	Exceptionr    objectr"   r(   r@   r   r   r   r   r   r   r   <module>   sP   8| 
 