
ɀ^2              
   @   s`   d  d l  Z  d  d l Z y  d  d l m Z m Z m Z Wn Yn XGd d   d e  j  Z d S)    N)DictUnionTuplec               @   s  e  Z d  Z d Z d d   Z d d   Z d d   Z d d	   Z d
 d   Z dX d d d  Z	 e
 d d    Z e j d d    Z e
 d d    Z e j d d    Z e
 d d    Z e j d d    Z e
 d d    Z e j d d    Z e
 d d     Z e j d! d     Z e
 d" d#    Z e j d$ d#    Z e
 d% d&    Z e j d' d&    Z e
 d( d)    Z e j d* d)    Z e
 d+ d,    Z e j d- d,    Z e
 d. d/    Z e j d0 d/    Z e
 d1 d2    Z e j d3 d2    Z e
 d4 d5    Z e j d6 d5    Z e
 d7 d8    Z e j d9 d8    Z e
 d: d;    Z e j d< d;    Z e
 d= d>    Z e j d? d>    Z e
 d@ dA    Z e j dB dA    Z e
 dC dD    Z e j dE dD    Z e
 dF dG    Z e j dH dG    Z e
 dI dJ    Z e j dK dJ    Z e
 dL dM    Z e j dN dM    Z e
 dO dP    Z  e  j dQ dP    Z  e
 dR dS    Z! dT S)YZmirrorThreadLocaluu
  
    由于Python内置thread-local对代码补全的提示非常不友好, 所以自己继承一个

    如果不知道什么是thread-local, 请看 http://tinyurl.com/hqgb2r8

    本类在 zmirror 中被实例化为变量 parse
    这个变量的重要性不亚于 request, 在 zmirror 各个部分都会用到

    其各个变量的含义如下:
    parse.time                记录请求过程中的各种时间点
         .method              请求的方法, 如 GET POST
         .remote_domain       当前请求对应的远程域名
         .is_external_domain  远程域名是否是外部域名, 比如google镜像, www.gstatic.com 就是外部域名
         .is_https            是否需要用https 来请求远程域名
         .remote_url          远程服务器的url, 比如 https://google.com/search?q=233
         .url_no_scheme       没有协议前缀的url,比如 google.com/search?q=233 通常在缓存中用
         .remote_path_query   对应的远程path+query, 比如 /search?q=2333
         .remote_path         对应的远程path,  比如 /search
         .client_header       经过转换和重写以后的访问者请求头
         .content_type        远程服务器响应头中的 content_type, 比如 "text/plain; encoding=utf-8"
         .mime                远程服务器响应的MIME, 比如 "text/html"
         .request_data        浏览器传入的data(已经经过重写) 可能为str或bytes或None
         .request_data_encoding 浏览器传入的data的编码(如果有) 如果为二进制或编码未知, 则为None
         .request_data_encoded  编码后的二进制 request_data, 只读
         .cache_control       远程服务器响应的cache_control内容
         .remote_response     远程服务器的响应, requests.Response
         .cacheable           是否可以对这一响应应用缓存 (CDN也算是缓存的一种, 依赖于此选项)
         .extra_resp_headers  发送给浏览器的额外响应头 (比如一些调试信息什么的)
         .extra_cookies       额外的cookies, 在目前版本只能添加, 不能覆盖已有cookie
         .streamed_our_response  是否以 stream 模式向浏览器传送这个响应
         .temporary_domain_alias 用于纯文本域名替换, 见 `plain_replace_domain_alias` 选项

    本类的方法:
        .dump()                   dump所有信息到dict
        .set_extra_resp_header()  设置一个响应头, 会发送给访问者, 会在内部操作 self.extra_resp_headers
        .set_cookie()             添加一个cookie 会在内部操作 self.extra_cookies, 目前版本只能添加新的cookie, 不能覆盖已有cookie

    c             C   s   |  j    d  S)N)init)self r   '/var/www/zmirror/zmirror/threadlocal.py__init__3   s    zZmirrorThreadLocal.__init__c             C   s   d  |  _  d  |  _ d  |  _ d  |  _ d  |  _ d  |  _ d  |  _ d  |  _ d  |  _ d  |  _	 d  |  _
 d  |  _ d  |  _ d |  _ d |  _ d  |  _ d  |  _ i  |  _ i  |  _ g  |  _ i  |  _ d  S)NF)methodremote_domainis_external_domainis_https
remote_urlurl_no_schemeremote_path_queryclient_headercontent_typeremote_pathmimecache_controlremote_responsestreamed_our_response	cacheablerequest_datarequest_data_encodingtimeextra_resp_headerstemporary_domain_aliasextra_cookies)r   r   r   r	   r   6   s*    																				zZmirrorThreadLocal.initc          *   C   s   d |  j  d |  j d |  j d |  j d |  j d |  j d |  j d |  j d	 |  j d
 |  j	 d |  j
 d |  j d |  j d |  j d |  j d |  j d |  j d |  j d |  j d |  j d |  j i S)Nr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )r   r   r   r	   dumpN   s*    																				zZmirrorThreadLocal.dumpc             C   s   t  |  j    S)N)strr    )r   r   r   r	   __str__g   s    zZmirrorThreadLocal.__str__c             C   s    |  j  } | | | <| |  _  d S)z:
        :type name: str
        :type value: str
        N)r   )r   namevaluehr   r   r	   set_extra_resp_headerj   s    	
z(ZmirrorThreadLocal.set_extra_resp_header   #      <   /c             C   sZ   d d l  m } |   } | | | <| | | d <| | | d <| | j   |  j | <d S)u   
        :param ttl: cookie有效时间, 秒
        :type ttl: int
        :type path: str
        :type name:  str
        :type value:  str
        r   )SimpleCookiepathexpiresN)http.cookiesr,   OutputStringr   )r   r#   r$   Zttlr-   r,   cr   r   r	   set_cookiess   s    	
zZmirrorThreadLocal.set_cookiesc             C   s   |  j  d  S)uG   
        当前请求对应的远程域名
        :rtype: str
        _remote_domain)__getattribute__)r   r   r   r	   r      s    z ZmirrorThreadLocal.remote_domainc             C   s   |  j  d |  d S)z:type value: strr3   N)__setattr__)r   r$   r   r   r	   r      s    c             C   s   |  j  d  S)u   
        远程域名是否是外部域名, 比如google镜像, www.gstatic.com 就是外部域名
        :rtype: bool
        _is_external_domain)r4   )r   r   r   r	   r      s    z%ZmirrorThreadLocal.is_external_domainc             C   s   |  j  d |  d S)z:type value: boolr6   N)r5   )r   r$   r   r   r	   r      s    c             C   s   |  j  d  S)uQ   
        是否需要用https 来请求远程域名
        :rtype: bool
        	_is_https)r4   )r   r   r   r	   r      s    zZmirrorThreadLocal.is_httpsc             C   s   |  j  d |  d S)z:type value: boolr7   N)r5   )r   r$   r   r   r	   r      s    c             C   s   |  j  d  S)u5   
        请求的方法
        :rtype: str
        _method)r4   )r   r   r   r	   r      s    zZmirrorThreadLocal.methodc             C   s   |  j  d |  d S)z:type value: strr8   N)r5   )r   r$   r   r   r	   r      s    c             C   s   |  j  d  S)uc   
        远程服务器的url, 比如 https://google.com/search?q=233
        :rtype: str
        _remote_url)r4   )r   r   r   r	   r      s    zZmirrorThreadLocal.remote_urlc             C   s   |  j  d |  d S)z:type value: strr9   N)r5   )r   r$   r   r   r	   r      s    c             C   s   |  j  d  S)us   
        没有协议前缀的url,比如 google.com/search?q=233 通常在缓存中用
        :rtype: str
        _url_no_scheme)r4   )r   r   r   r	   r      s    z ZmirrorThreadLocal.url_no_schemec             C   s   |  j  d |  d S)z:type value: strr:   N)r5   )r   r$   r   r   r	   r      s    c             C   s   |  j  d  S)uV   
        对应的远程path+query, 比如 /search?q=2333
        :rtype: str
        _remote_path_query)r4   )r   r   r   r	   r      s    z$ZmirrorThreadLocal.remote_path_queryc             C   s   |  j  d |  d S)z:type value: strr;   N)r5   )r   r$   r   r   r	   r      s    c             C   s   |  j  d  S)uJ   
        对应的远程path,  比如 /search
        :rtype: str
        _remote_path)r4   )r   r   r   r	   r      s    zZmirrorThreadLocal.remote_pathc             C   s   |  j  d |  d S)z:type value: strr<   N)r5   )r   r$   r   r   r	   r      s    c             C   s   |  j  d  S)ua   
        经过转换和重写以后的访问者请求头
        :rtype: dict[str, str]
        _client_header)r4   )r   r   r   r	   r      s    z ZmirrorThreadLocal.client_headerc             C   s   |  j  d |  d S)z:type value: dict[str, str]r=   N)r5   )r   r$   r   r   r	   r      s    c             C   s   |  j  d  S)uv   
        远程服务器响应头中的 content_type, 比如 "text/plain; encoding=utf-8"
        :rtype: str
        _content_type)r4   )r   r   r   r	   r      s    zZmirrorThreadLocal.content_typec             C   s   |  j  d |  d S)z:type value: strr>   N)r5   )r   r$   r   r   r	   r      s    c             C   s   |  j  d  S)uV   
        远程服务器响应的MIME, 比如 "text/html"
        :rtype: str
        _mime)r4   )r   r   r   r	   r     s    zZmirrorThreadLocal.mimec             C   s   |  j  d |  d S)z:type value: strr?   N)r5   )r   r$   r   r   r	   r     s    c             C   s   |  j  d  S)uQ   
        远程服务器响应的cache_control内容
        :rtype: str
        _cache_control)r4   )r   r   r   r	   r     s    z ZmirrorThreadLocal.cache_controlc             C   s   |  j  d |  d S)z:type value: strr@   N)r5   )r   r$   r   r   r	   r     s    c             C   s   |  j  d  S)ug   
        远程服务器的响应, 对象, requests.Response
        :rtype: requests.Response
        _remote_response)r4   )r   r   r   r	   r     s    z"ZmirrorThreadLocal.remote_responsec             C   s   |  j  d |  d S)z:type value: requests.ResponserA   N)r5   )r   r$   r   r   r	   r   '  s    c             C   s   |  j  d  S)uk   
        用于纯文本域名替换, 见 `plain_replace_domain_alias` 选项
        :rtype: list
        _temporary_domain_alias)r4   )r   r   r   r	   r   ,  s    z)ZmirrorThreadLocal.temporary_domain_aliasc             C   s   |  j  d |  d S)z:type value: listrB   N)r5   )r   r$   r   r   r	   r   4  s    c             C   s   |  j  d  S)uA   我们的响应是否用 stream 模式传送
        :rtype: bool_streamed_our_response)r4   )r   r   r   r	   r   9  s    z(ZmirrorThreadLocal.streamed_our_responsec             C   s   |  j  d |  d S)z:type value: boolrC   N)r5   )r   r$   r   r   r	   r   ?  s    c             C   s   |  j  d  S)u*   响应能否被缓存
        :rtype: bool
_cacheable)r4   )r   r   r   r	   r   D  s    zZmirrorThreadLocal.cacheablec             C   s   |  j  d |  d S)z:type value: boolrD   N)r5   )r   r$   r   r   r	   r   J  s    c             C   s   |  j  d  S)u1   额外的响应头
        :rtype: Dict[str, str]_extra_resp_headers)r4   )r   r   r   r	   r   O  s    z%ZmirrorThreadLocal.extra_resp_headersc             C   s   |  j  d |  d S)z:type value: Dict[str, str]rE   N)r5   )r   r$   r   r   r	   r   U  s    c             C   s   |  j  d  S)u.   额外的cookie
        :rtype: Dict[str, str]_extra_cookies)r4   )r   r   r   r	   r   Z  s    z ZmirrorThreadLocal.extra_cookiesc             C   s   |  j  d |  d S)z:type value: Dict[str, str]rF   N)r5   )r   r$   r   r   r	   r   `  s    c             C   s   |  j  d  S)u3   用于记录时间
        :rtype: Dict[str, float]_time)r4   )r   r   r   r	   r   e  s    zZmirrorThreadLocal.timec             C   s   |  j  d |  d S)z:type value: Dict[str, float]rG   N)r5   )r   r$   r   r   r	   r   k  s    c             C   s   |  j  d  S)uR   浏览器传入的data(已经经过重写)
        :rtype: Union[str, bytes, None]_request_data)r4   )r   r   r   r	   r   p  s    zZmirrorThreadLocal.request_datac             C   s   |  j  d |  d S)z$:type value: Union[str, bytes, None]rH   N)r5   )r   r$   r   r   r	   r   v  s    c             C   s   |  j  d  S)u@   浏览器传入的data的编码
        :rtype: Union[str, None]_request_data_encoding)r4   )r   r   r   r	   r   {  s    z(ZmirrorThreadLocal.request_data_encodingc             C   s   |  j  d |  d S)z:type value: Union[str, None]rI   N)r5   )r   r$   r   r   r	   r     s    c             C   s9   t  |  j t  r. |  j j d |  j p* d  S|  j Sd S)z:rtype: Union[bytes, None]encodingzutf-8N)
isinstancer   r!   encoder   )r   r   r   r	   request_data_encoded  s    z'ZmirrorThreadLocal.request_data_encodedNi  i`'  i:	 i ))"__name__
__module____qualname____doc__r
   r   r    r"   r&   r2   propertyr   setterr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   rM   r   r   r   r	   r      sd   &	r   )	threadingrequeststypingr   r   r   localr   r   r   r   r	   <module>   s    