ó
ú2ec           @   s¿   d  Z  d d l m Z d d l m Z d d l m Z d d l	 Z	 d d l
 m Z d d l m Z d Z d e f d „  ƒ  YZ d d d „ Z d e f d „  ƒ  YZ d „  Z d d d „ Z d S(   sÞ  
An application that proxies WSGI requests to a remote server.

TODO:

* Send ``Via`` header?  It's not clear to me this is a Via in the
  style of a typical proxy.

* Other headers or metadata?  I put in X-Forwarded-For, but that's it.

* Signed data of non-HTTP keys?  This would be for things like
  REMOTE_USER.

* Something to indicate what the original URL was?  The original host,
  scheme, and base path.

* Rewriting ``Location`` headers?  mod_proxy does this.

* Rewriting body?  (Probably not on this one -- that can be done with
  a different middleware that wraps this middleware)

* Example::

    use = egg:Paste#proxy
    address = http://server3:8680/exist/rest/db/orgs/sch/config/
    allowed_request_methods = GET

iÿÿÿÿ(   t   http_client(   t   parse(   t   quoteN(   t   httpexceptions(   t   aslists   transfer-encodingt
   connections
   keep-alives   proxy-authenticates   proxy-authorizationt   tet   trailerst   upgradet   Proxyc           B   s    e  Z d d d  „ Z d „  Z RS(   c         C   s¥   | |  _  t j | ƒ |  _ |  j d j ƒ  |  _ |  j d |  _ |  j d |  _ g  | D] } | rX | j ƒ  ^ qX |  _ g  | D] } | r€ | j ƒ  ^ q€ |  _	 d  S(   Ni    i   i   (
   t   addresst   urlparset   urlsplitt   parsedt   lowert   schemet   hostt   patht   allowed_request_methodst   suppress_http_headers(   t   selfR
   R   R   t   x(    (    s5   /usr/local/lib/python2.7/dist-packages/paste/proxy.pyt   __init__7   s    	(c         C   s  |  j  r8 | d j ƒ  |  j  k r8 t j d ƒ | | ƒ S|  j d k rS t j } n7 |  j d k rn t j } n t d |  j	 |  j f ƒ ‚ | |  j
 ƒ } i  } xs | j ƒ  D]e \ } } | j d ƒ r¬ | d j ƒ  j d d	 ƒ } | d
 k s¬ | |  j k rq¬ n  | | | <q¬ q¬ W|  j
 | d
 <d | k r?| d | d <n  | j d ƒ r_| d | d <n  | j d ƒ rÞ| d d k rª| d j d ƒ } t t | ƒ ƒ | d <qä| d | d <t | d ƒ }	 | d j |	 ƒ } n d } t | d ƒ }
 |  j r>|
 } | r&| d d k r&| d } n  t j |  j | ƒ } n |
 } | j d ƒ rh| d | d 7} n  | j | d | | | ƒ | j ƒ  } t | j ƒ } d | j | j f } | | | ƒ | j d ƒ }	 |	 d  k	 ró| j t |	 ƒ ƒ } n | j ƒ  } | j  ƒ  | g S(   Nt   REQUEST_METHODt
   Disallowedt   httpt   httpss   Unknown scheme for %r: %rt   HTTP_i   t   _t   -R   t   REMOTE_ADDRs   x-forwarded-fort   CONTENT_TYPEs   content-typet   CONTENT_LENGTHs   -1s
   wsgi.inputiÿÿÿÿs   content-lengtht    t	   PATH_INFOi    t   /i   t   QUERY_STRINGt   ?s   %s %s(!   R   R   R   t   HTTPBadRequestR   t   httplibt   HTTPConnectiont   HTTPSConnectiont
   ValueErrorR
   R   t   itemst
   startswitht   replaceR   t   gett   readt   strt   lent   intR   R   R   t   urljoint   requestt   getresponset   parse_headerst   msgt   statust   reasont	   getheadert   Nonet   close(   R   t   environt   start_responset	   ConnClasst   connt   headerst   keyt   valuet   bodyt   lengtht	   path_infot   request_pathR   t   rest   headers_outR8   (    (    s5   /usr/local/lib/python2.7/dist-packages/paste/proxy.pyt   __call__D   sh    		

(    (    (   t   __name__t
   __module__R   RJ   (    (    (    s5   /usr/local/lib/python2.7/dist-packages/paste/proxy.pyR	   5   s   R!   c         C   s.   t  | ƒ } t  | ƒ } t | d | d | ƒS(   s¤  
    Make a WSGI application that proxies to another address:

    ``address``
        the full URL ending with a trailing ``/``

    ``allowed_request_methods``:
        a space seperated list of request methods (e.g., ``GET POST``)

    ``suppress_http_headers``
        a space seperated list of http headers (lower case, without
        the leading ``http_``) that should not be passed on to target
        host
    R   R   (   R   R	   (   t   global_confR
   R   R   (    (    s5   /usr/local/lib/python2.7/dist-packages/paste/proxy.pyt
   make_proxy†   s    t   TransparentProxyc           B   s/   e  Z d  Z d d d „ Z d „  Z d „  Z RS(   s$  
    A proxy that sends the request just as it was given, including
    respecting HTTP_HOST, wsgi.url_scheme, etc.

    This is a way of translating WSGI requests directly to real HTTP
    requests.  All information goes in the environment; modify it to
    modify the way the request is made.

    If you specify ``force_host`` (and optionally ``force_scheme``)
    then HTTP_HOST won't be used to determine where to connect to;
    instead a specific host will be connected to, but the ``Host``
    header in the request will remain intact.
    R   c         C   s   | |  _  | |  _ d  S(   N(   t
   force_hostt   force_scheme(   R   RP   RQ   (    (    s5   /usr/local/lib/python2.7/dist-packages/paste/proxy.pyR   ®   s    	c         C   s,   d |  j  j t t |  ƒ ƒ |  j |  j f S(   Ns%   <%s %s force_host=%r force_scheme=%r>(   t	   __class__RK   t   hext   idRP   RQ   (   R   (    (    s5   /usr/local/lib/python2.7/dist-packages/paste/proxy.pyt   __repr__³   s    	c         C   sã  | d } |  j  d  k r" | } n	 |  j } | d k rC t j } n( | d k r[ t j } n t d | ƒ ‚ d | k r† t d ƒ ‚ n  | d } |  j  d  k r¨ | } n	 |  j  } | | ƒ } i  }	 xR | j ƒ  D]D \ }
 } |
 j d ƒ rÐ |
 d j	 ƒ  j
 d	 d
 ƒ }
 | |	 |
 <qÐ qÐ W| |	 d <d | k rKd | k rK| d |	 d <n  | j d ƒ rk| d |	 d <n  | j d ƒ rÅt | d ƒ } | d j | ƒ } | d k rìt t | ƒ ƒ | d <qìn' d | k ràd } d } n d } d } | j d d ƒ | j d d ƒ } t | ƒ } d | k r;| d | d 7} n  | j | d | | |	 ƒ | j ƒ  } t | j ƒ } d | j | j f } | | | ƒ | j d ƒ } | d  k	 rÆ| j t | ƒ ƒ } n | j ƒ  } | j ƒ  | g S(   Ns   wsgi.url_schemeR   R   s   Unknown scheme %rt	   HTTP_HOSTs*   WSGI environ must contain an HTTP_HOST keyR   i   R   R   R   R   t   HTTP_X_FORWARDED_FORs   x-forwarded-forR   s   content-typeR    s
   wsgi.inputiÿÿÿÿR!   i    t   SCRIPT_NAMER"   R$   R%   R   s   %s %ss   content-length(   RP   R;   RQ   R'   R(   R)   R*   R+   R,   R   R-   R.   R2   R/   R0   R1   R   R4   R5   R6   R7   R8   R9   R:   R<   (   R   R=   R>   R   t   conn_schemeR?   R   t	   conn_hostR@   RA   RB   RC   RE   RD   R   RH   RI   R8   (    (    s5   /usr/local/lib/python2.7/dist-packages/paste/proxy.pyRJ   ¹   sn    
		
		
	
N(   RK   RL   t   __doc__R;   R   RU   RJ   (    (    (    s5   /usr/local/lib/python2.7/dist-packages/paste/proxy.pyRO   ž   s
   	c         C   sM  g  } t  j rW x7|  j ƒ  D]4 \ } } | j ƒ  t k r | j | | f ƒ q q Wnò xï |  j D]ä } | ss qa n  | d j ƒ  rÛ | sœ t d | ƒ ‚ n  | j	 ƒ  \ } } | d | j
 ƒ  } | j | | f ƒ qa n  y | j d d ƒ \ } } Wn t d | ƒ ‚ n X| j
 ƒ  } | j ƒ  t k ra | j | | f ƒ qa qa W| S(   sB   
    Turn a Message object into a list of WSGI-style headers.
    i    s%   First header starts with a space (%r)t    t   :i   s   Invalid header: %r(   t   sixt   PY3R+   R   t   filtered_headerst   appendRA   t   isspaceR*   t   popt   stript   split(   t   messageRI   t   headerRC   t   full_headert   last_headert
   last_value(    (    s5   /usr/local/lib/python2.7/dist-packages/paste/proxy.pyR6   ú   s0    	R   c         C   s   t  d | d | ƒ S(   s   
    Create a proxy that connects to a specific host, but does
    absolutely no other filtering, including the Host header.
    RP   RQ   (   RO   (   RM   RP   RQ   (    (    s5   /usr/local/lib/python2.7/dist-packages/paste/proxy.pyt   make_transparent_proxy  s    (   s   transfer-encodingR   s
   keep-alives   proxy-authenticates   proxy-authorizationR   R   R   (   R[   t	   six.movesR    R'   t   six.moves.urllibR   R   t   six.moves.urllib.parseR   R^   t   pasteR   t   paste.util.convertersR   R`   t   objectR	   RN   RO   R6   R;   Rk   (    (    (    s5   /usr/local/lib/python2.7/dist-packages/paste/proxy.pyt   <module>   s(          Q\	!