
_&              .   @   s  d  Z  d d l 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 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 d d l m Z y0 d d l Z d d l m Z d d l m Z Wn> e k
 rbd d l Z d d l m Z d d l m Z Yn Xy d d l Z Wn1 e k
 rGd d   d e  Z e   Z Yn Xy d d l  Z  Wn e k
 rd Z  Yn Xe j! Z! e" e d  Z# e# re j$ Z$ n Gd d   d e  Z$ y e j% Z& Wn e' k
 r9d Z& Yn Xd Z( e oSe" e d  Z) e
 rhe j* Z+ n e, Z+ Gd d   d e j-  Z. Gd d   d e e  Z/ e/ Z0 d d d  Z1 d d d d  Z2 d  d!   Z3 d d d" d#  Z4 Gd$ d%   d% e  Z5 d d& d'  Z6 d( d)   Z7 d* d+   Z8 Gd, d-   d- e e  Z9 Gd. d/   d/ e! e9  Z: Gd0 d1   d1 e$ e9  Z; d d d d2 d d d2 d d d3 d4 	 Z< d5 d6   Z= d2 d2 d7 d d d8 d2 d d d d2 d d9 d:  Z> d; d<   Z? d= d>   Z@ eA d? k re@   d S)@a7  
    werkzeug.serving
    ~~~~~~~~~~~~~~~~

    There are many ways to serve a WSGI application.  While you're developing
    it you usually don't want a full blown webserver like Apache but a simple
    standalone one.  From Python 2.5 onwards there is the `wsgiref`_ server in
    the standard library.  If you're using older versions of Python you can
    download the package from the cheeseshop.

    However there are some caveats. Sourcecode won't reload itself when
    changed and each time you kill the server using ``^C`` you get an
    `KeyboardInterrupt` error.  While the latter is easy to solve the first
    one can be a pain in the ass in some situations.

    The easiest way is creating a small ``start-myproject.py`` that runs the
    application::

        #!/usr/bin/env python
        # -*- coding: utf-8 -*-
        from myproject import make_app
        from werkzeug.serving import run_simple

        app = make_app(...)
        run_simple('localhost', 8080, app, use_reloader=True)

    You can also pass it a `extra_files` keyword argument with a list of
    additional files (like configuration files) you want to observe.

    For bigger applications you should consider using `click`
    (http://click.pocoo.org) instead of a simple start file.


    :copyright: 2007 Pallets
    :license: BSD-3-Clause
    N)datetime)	timedelta   )PY2)reraise)WIN)wsgi_encoding_dance)_log)InternalServerError)
uri_to_iri)	url_parse)url_unquote)BaseHTTPRequestHandler)
HTTPServerc               @   s   e  Z d  Z d d   Z d S)	_SslDummyc             C   s   t  d   d  S)NzSSL support unavailable)RuntimeError)selfname r   4/tmp/pip-build-5gj8f0j9/Werkzeug/werkzeug/serving.py__getattr__F   s    z_SslDummy.__getattr__N)__name__
__module____qualname__r   r   r   r   r   r   E   s   r   forkc               @   s   e  Z d  Z d S)ForkingMixInN)r   r   r   r   r   r   r   r   X   s   r      fromfdc               @   sF   e  Z d  Z d Z d d   Z d d   Z d d   Z d d	   Z d
 S)DechunkedInputz8An input stream that handles Transfer-Encoding 'chunked'c             C   s   | |  _  d |  _ d |  _ d  S)NFr   )_rfile_done_len)r   rfiler   r   r   __init__q   s    		zDechunkedInput.__init__c             C   s   d S)NTr   )r   r   r   r   readablev   s    zDechunkedInput.readablec             C   sn   y1 |  j  j   j d  } t | j   d  } Wn t k
 rQ t d   Yn X| d k  rj t d   | S)Nlatin1   zInvalid chunk headerr   z!Negative chunk length not allowed)r   readlinedecodeintstrip
ValueErrorIOError)r   liner!   r   r   r   read_chunk_leny   s    zDechunkedInput.read_chunk_lenc             C   s   d } x |  j  r | t |  k  r |  j d k rC |  j   |  _ |  j d k r[ d |  _  |  j d k r t t |  |  j  } |  j j |  | | | |  <|  j | 8_ | | 7} |  j d k r	 |  j j   } | d k r	 t d   q	 W| S)Nr   T   
   
   z!Missing chunk terminating newline)r/   r0   r1   )	r    lenr!   r.   minr   readr'   r,   )r   bufr4   n
terminatorr   r   r   readinto   s     	 
zDechunkedInput.readintoN)r   r   r   __doc__r#   r$   r.   r8   r   r   r   r   r   n   s
   
r   c               @   s   e  Z d  Z d Z e d d    Z d d   Z d d   Z d d	   Z d
 d   Z	 d d d  Z
 d d   Z d d d  Z d d   Z d d   Z d d   Z d d d d  Z d d   Z d d   Z d  d!   Z d" d#   Z d S)$WSGIRequestHandlerz3A request handler that implements WSGI dispatching.c             C   s   d d l  m } d | S)Nr   )__version__z	Werkzeug/) r;   )r   r;   r   r   r   server_version   s    z!WSGIRequestHandler.server_versionc       	   (      s  t    j  }   f d d   }   j j d  k r9 d n d }   j sQ d   _ t   j t  rx   j d f   _ n  | j r | j r d | j | j f } n	 | j } t	 |  } d d/ d
 | d   j
 d t j d   j j d   j j d d d | d   j d   j d d d t |  d t | j  d t   j  d t   j  d   j   d   j   d   j j d d t   j j d	  d   j i } x   j   D]x \ } } | j   j d d   } | j d! d  } | d0 k rd$ | } | | k rd% j | | |  } | | | <qW| j d& d  j   j   d' k rdd( | d) <t | d  | d <| j r| j r| j | d* <y8   j j  d+ d(  } | d  k	 rt! j" |  | d, <Wn6 t# k
 r  j j$ d- d.  Yn t% k
 rYn X| S)1Nc                  s   d   j  _ d  S)NT)servershutdown_signalr   )r   r   r   shutdown_server   s    z8WSGIRequestHandler.make_environ.<locals>.shutdown_serverhttphttpsz<local>r   z/%s%szwsgi.versionr   zwsgi.url_schemez
wsgi.inputzwsgi.errorszwsgi.multithreadzwsgi.multiprocesszwsgi.run_onceFzwerkzeug.server.shutdownZSERVER_SOFTWAREREQUEST_METHODZSCRIPT_NAMEr<   Z	PATH_INFOQUERY_STRINGZREQUEST_URIZRAW_URIREMOTE_ADDRZREMOTE_PORTZSERVER_NAMEZSERVER_PORTZSERVER_PROTOCOL-_z
CONTENT_TYPECONTENT_LENGTHZHTTP_z{},{}ZHTTP_TRANSFER_ENCODINGchunkedTzwsgi.input_terminatedZ	HTTP_HOSTbinary_formZSSL_CLIENT_CERTerrorz&Cannot fetch SSL peer certificate info)r   r   )rH   rI   )&r   pathr>   ssl_contextclient_address
isinstancestrschemenetlocr   r"   sysstderrmultithreadmultiprocessr=   commandr   queryaddress_stringport_integerserver_addressrequest_versionget_header_itemsupperreplaceformatgetr*   lowerr   
connectiongetpeercertsslDER_cert_to_PEM_certr+   logAttributeError)	r   request_urlr@   Z
url_schemeZ	path_infoenvironkeyvalueZ	peer_certr   )r   r   make_environ   sj    							
$
zWSGIRequestHandler.make_environc                s   j  j d d  j   j   d k r7  j j d   j    _   g   g        f d d    d     f d d        f d	 d
   } y |  j j	  Wn t
 t j f k
 r } z  j |    WYd  d  } ~ Xn t k
 r j j r  d d l m } | d d  } y$  sL d  d   =| t    Wn t k
 rnYn X j j d d | j  Yn Xd  S)NZExpectr<   z100-continues   HTTP/1.1 100 Continue

c                s   s t  d    sp \ } }  d  d   <y | j d  d  \ } } Wn t k
 ro | d } } Yn Xt |  }  j | |  t   } x= | D]5 \ } }  j | |  | j   } | j |  q Wd | k p  d d k p| d k  p| d k s"d
  _	  j d d  d | k rD j d  j
    d | k rf j d  j     j   t |  t  st  d   |  r j j |    j j   d  S)Nzwrite() before start_responser   r<   zcontent-lengthrC   HEAD      0  T
Connectioncloser>   ServerdateDatezapplications must write bytes)rq   rr   )AssertionErrorsplitr+   r)   send_responsesetZsend_headerrc   addclose_connectionversion_stringZdate_time_stringZend_headersrP   byteswfilewriteflush)datastatusresponse_headerscodemsgZheader_keysrl   rm   )rk   headers_sentheaders_setr   r   r   r     s:    		
z*WSGIRequestHandler.run_wsgi.<locals>.writec                sS   | r' z   r t  |   Wd  d  } Xn  r9 t d   |  | g  d  d   < S)NzHeaders already set)r   rx   )r   r   exc_info)r   r   r   r   r   start_response+  s    
z3WSGIRequestHandler.run_wsgi.<locals>.start_responsec                s_   |      } z/ x | D] }  |  q W s=  d  Wd  t  | d  rZ | j   Xd  S)N    rt   )hasattrrt   )appZapplication_iterr   )rk   r   r   r   r   r   execute7  s    z,WSGIRequestHandler.run_wsgi.<locals>.executer   )get_current_tracebackZignore_system_exceptionsTrL   zError on request:
%s)headersrb   rc   r*   r   r   rn   rk   r>   r   _ConnectionErrorsockettimeoutconnection_dropped	Exceptionpassthrough_errorsZdebug.tbtoolsr   r
   rh   	plaintext)r   r   er   	tracebackr   )rk   r   r   r   r   r   r   run_wsgi   s0    '#"zWSGIRequestHandler.run_wsgic             C   s   y t  j |   Wn t t j f k
 rN } z |  j |  WYd d } ~ XnG t k
 r } z' |  j j d k s t	 |  r   WYd d } ~ Xn X|  j j
 r |  j   d S)z/Handles a request ignoring dropped connections.N)r   handler   r   r   r   r   r>   rN   is_ssl_errorr?   initiate_shutdown)r   r   r   r   r   r   V  s    zWSGIRequestHandler.handlec             C   sP   t  t d t j  } t   r4 t j t j   |  d |  j _ d |  j _	 d S)zpA horrible, horrible way to kill the server for Python 2.6 and
        later.  It's the best we can do.
        SIGKILLTFN)
getattrsignalSIGTERMis_running_from_reloaderoskillgetpidr>   _BaseServer__shutdown_requestZ_BaseServer__serving)r   sigr   r   r   r   b  s
    	z$WSGIRequestHandler.initiate_shutdownNc             C   s   d S)z`Called if the connection was closed by the client.  By default
        nothing happens.
        Nr   )r   rL   rk   r   r   r   r   p  s    z%WSGIRequestHandler.connection_droppedc             C   sA   |  j  j   |  _ |  j s' d |  _ n |  j   r= |  j   Sd S)zHandle a single HTTP request.r   N)r"   r'   Zraw_requestliner}   Zparse_requestr   )r   r   r   r   handle_one_requestu  s
    	z%WSGIRequestHandler.handle_one_requestc             C   s   |  j  |  | d k r? | |  j k r9 |  j | d p< d } |  j d k r} d |  j | | f } |  j j | j d   d S)z3Send the response header and log the response code.Nr   r<   zHTTP/0.9z
%s %d %s
ascii)log_request	responsesr]   Zprotocol_versionr   r   encode)r   r   messagehdrr   r   r   rz   }  s    &z WSGIRequestHandler.send_responsec             C   s   t  j |   j   S)N)r   r~   r*   )r   r   r   r   r~     s    z!WSGIRequestHandler.version_stringc             C   sR   t  |  d d   r |  j d S|  j s* d St |  j t  rC |  j S|  j d Sd  S)Nrk   rE   z<local>r   )r   rk   rO   rP   rQ   )r   r   r   r   rZ     s    	z!WSGIRequestHandler.address_stringc             C   s   |  j  d S)Nr   )rO   )r   r   r   r   r[     s    zWSGIRequestHandler.port_integerrF   c             C   sv  y, t  |  j  } d |  j | |  j f } Wn t k
 rI |  j } Yn Xt |  } t rYt j } | d d k r | | d d } n | d d k r | | d d } n | d	 k r | | d d
 } n | d d k r | | d d } nd | d k r| | d d } nC | d d k rA| | d d d d } n | | d d d d } |  j	 d d | | |  d  S)Nz%s %s %sr   1ZboldT2ZfgZwhiteZ304Zcyan3ZgreenZ404Zyellow4ZredZmagentainfoz
"%s" %s %s)
r   rM   rX   r]   ri   ZrequestlinerQ   clickstylerh   )r   r   sizerM   r   colorr   r   r   r     s,    	zWSGIRequestHandler.log_requestc             G   s   |  j  d |  d  S)NrL   )rh   )r   argsr   r   r   	log_error  s    zWSGIRequestHandler.log_errorc             G   s   |  j  d | |  d  S)Nr   )rh   )r   ra   r   r   r   r   log_message  s    zWSGIRequestHandler.log_messagec             G   s.   t  | d |  j   |  j   | | f  d  S)Nz%s - - [%s] %s
)r	   rZ   Zlog_date_time_string)r   typer   r   r   r   r   rh     s    zWSGIRequestHandler.logc             C   s   t  r g  } x |  j j D] } y& | d d  j d d  \ } } WnJ t k
 r | d d k r | r | j   \ } } | | } n   Yn X| j | | j   f  q Wn |  j j   } | S)	aV  
        Get an iterable list of key/value pairs representing headers.

        This function provides Python 2/3 compatibility as related to the
        parsing of request headers. Python 2.7 is not compliant with
        RFC 3875 Section 4.1.18 which requires multiple values for headers
        to be provided or RFC 2616 which allows for folding of multi-line
        headers. This function will return a matching list regardless
        of Python version. It can be removed once Python 2.7 support
        is dropped.

        :return: List of tuples containing header hey/value pairs
        r      :r   	 )r   r   )r   r   ry   r+   popappendlstripitems)r   r   headerrl   rm   r   r   r   r^     s    & z#WSGIRequestHandler.get_header_items)r   r   r   r9   propertyr=   rn   r   r   r   r   r   rz   r~   rZ   r[   r   r   r   rh   r^   r   r   r   r   r:      s"   SV	
r:   c       	      C   s  yT d d l  m } d d l m } d d l m } d d l m } d d l m	 } Wn t
 k
 rt t d   Yn X| j d d	 d
 d d |    } |  d  k r d }  | j | j | j d  | j | j |   g  } | j   j |  j |  j | j    j | j    j t j    j t j   t d d   j | j | j g  d d j | j | j  d  g  d d j! | | j"   |    } | | f S)Nr   )x509)NameOID)default_backend)hashes)rsaz<Using ad-hoc certificates requires the cryptography library.Zpublic_exponenti  Zkey_sizei   backend*zDummy Certificatedaysim  criticalF)#Zcryptographyr   Zcryptography.x509.oidr   Zcryptography.hazmat.backendsr   cryptography.hazmat.primitivesr   Z)cryptography.hazmat.primitives.asymmetricr   ImportError	TypeErrorZgenerate_private_keyNameZNameAttributeZORGANIZATION_NAMEZCOMMON_NAMEZCertificateBuilderZsubject_nameZissuer_nameZ
public_keyZserial_numberZrandom_serial_numberZnot_valid_beforedtutcnowZnot_valid_afterr   add_extensionZExtendedKeyUsageZOID_SERVER_AUTHZSubjectAlternativeNameZDNSNamesignSHA256)	cnr   r   r   r   r   pkeysubjectcertr   r   r   generate_adhoc_ssl_pair  s4    			$r   c       	      C   s   | d k	 r d | | f } t  d |  \ } } d d l m } |  d } |  d } t | d  # } | j | j | j j   Wd QRXt | d  > } | j | j d	 | j j d
 | j	 j
 d | j     Wd QRX| | f S)a  Creates an SSL key for development.  This should be used instead of
    the ``'adhoc'`` key which generates a new cert on each server start.
    It accepts a path for where it should store the key and cert and
    either a host or CN.  If a host is given it will use the CN
    ``*.host/CN=host``.

    For more information see :func:`run_simple`.

    .. versionadded:: 0.9

    :param base_path: the path to the certificate and key.  The extension
                      ``.crt`` is added for the certificate, ``.key`` is
                      added for the key.
    :param host: the name of the host.  This can be used as an alternative
                 for the `cn`.
    :param cn: the `CN` to use.
    Nz
*.%s/CN=%sr   r   )serializationz.crtz.keywbencodingra   encryption_algorithm)r   r   r   openr   public_bytesEncodingPEMprivate_bytesPrivateFormatTraditionalOpenSSLNoEncryption)		base_pathhostr   r   r   r   	cert_file	pkey_filefr   r   r   make_ssl_devcert!  s    

#	r   c        
   	   C   s  d d l  }  d d l } t   \ } } d d l m } |  j   \ } } |  j   \ } } | j t j |  | j t j |  t j	 | | j
 | j j   t j	 | | j d | j j d | j j d | j     t j |  t j |  t | |  }	 |	 S)z:Generates an adhoc SSL context for the development server.r   N)r   r   ra   r   )tempfileatexitr   r   r   mkstempregisterr   remover   r   r   r   r   r   r   r   rt   load_ssl_context)
r   r   r   r   r   Zcert_handler   Zpkey_handler   ctxr   r   r   generate_adhoc_ssl_contextK  s&    	r   c             C   sW   | d k r7 y t  j } Wn t k
 r6 t  j } Yn Xt |  } | j |  |  | S)a  Loads SSL context from cert/private key files and optional protocol.
    Many parameters are directly taken from the API of
    :py:class:`ssl.SSLContext`.

    :param cert_file: Path of the certificate to use.
    :param pkey_file: Path of the private key to use. If not given, the key
                      will be obtained from the certificate file.
    :param protocol: One of the ``PROTOCOL_*`` constants in the stdlib ``ssl``
                     module. Defaults to ``PROTOCOL_SSLv23``.
    N)rf   ZPROTOCOL_TLS_SERVERri   PROTOCOL_SSLv23_SSLContextload_cert_chain)r   r   protocolr   r   r   r   r   i  s    r   c               @   s@   e  Z d  Z d Z d d   Z d d d d  Z d d   Z d S)	r   zuA dummy class with a small subset of Python3's ``ssl.SSLContext``, only
    intended to be used with and by Werkzeug.c             C   s(   | |  _  d  |  _ d  |  _ d  |  _ d  S)N)	_protocol	_certfile_keyfile	_password)r   r   r   r   r   r#     s    			z_SSLContext.__init__Nc             C   s%   | |  _  | p | |  _ | |  _ d  S)N)r   r   r   )r   certfilekeyfilepasswordr   r   r   r     s    	z_SSLContext.load_cert_chainc          	   K   s+   t  j | d |  j d |  j d |  j | S)Nr  r  ssl_version)rf   wrap_socketr   r   r   )r   sockkwargsr   r   r   r    s    		z_SSLContext.wrap_socket)r   r   r   r9   r#   r   r  r   r   r   r   r     s   r   c             C   s,   |  d k r t  j   d }  t |  t j  S)z?Checks if the given error (or the current one) is an SSL error.Nr   )rT   r   rP   rf   SSLError)rL   r   r   r   r     s    r   c             C   s?   |  j  d  r t j Sd |  k r8 t t d  r8 t j St j S)zUReturn ``AF_INET4``, ``AF_INET6``, or ``AF_UNIX`` depending on
    the host and port.zunix://r   AF_INET6)
startswithr   AF_UNIXr   r	  AF_INET)r   portr   r   r   select_address_family  s
    r  c             C   ss   | t  k r  |  j d d  d Sy% t j |  | | t j t j  } Wn t j k
 rf |  | f SYn X| d d S)zVReturn a fully qualified socket address that can be passed to
    :func:`socket.bind`.z://r   r      )af_unixry   r   getaddrinfoSOCK_STREAMIPPROTO_TCPgaierror)r   r  familyresr   r   r   get_sockaddr  s    r  c               @   sp   e  Z d  Z d Z d Z d Z e Z d d d d d d  Z d d   Z	 d d	   Z
 d
 d   Z d d   Z d S)BaseWSGIServerz3Simple single-threaded, single-process WSGI server.FNc             C   s  | d  k r t  } t | |  |  _ | d  k	 rQ t j | |  j t j  } d } t | t |  |  j  }	 |  j t k r t	 j
 j |	  r t	 j |	  t j |  |	 |  | |  _ | |  _ d |  _ | |  _ |  j j   d |  _ | d  k	 r|  j j   | |  _ |  j j   |  _ | d  k	 rt | t  rBt |   } | d k rWt   } |  j }
 t rt |
 t j  rt j |
 j |
 j |
 j |
  }
 | j |
 d d |  _ | |  _  n	 d  |  _  d  S)Nr   Fr   Zadhocserver_sideT)!r:   r  address_familyr   r   r  r  r)   r  r   rM   existsunlinkr   r#   r   r   r?   r   getsocknamer  rt   r\   rP   tupler   r   r   r  r   protor  rN   )r   r   r  r   handlerr   rN   fdZ	real_sockr\   r  r   r   r   r#     s<    
!							!zBaseWSGIServer.__init__c             G   s   t  | | |  d  S)N)r	   )r   r   r   r   r   r   r   rh     s    zBaseWSGIServer.logc             C   sE   d |  _  z* y t j |   Wn t k
 r1 Yn XWd  |  j   Xd  S)NF)r?   r   serve_foreverKeyboardInterruptserver_close)r   r   r   r   r"    s    		zBaseWSGIServer.serve_foreverc             C   s<   |  j  r   t t j   d t  r) d  St j |  | |  S)Nr   )r   rP   rT   r   r   r   handle_error)r   requestrO   r   r   r   r%    s
    	zBaseWSGIServer.handle_errorc             C   s   |  j  j   \ } } | | f S)N)r   accept)r   conr   r   r   r   get_request  s    zBaseWSGIServer.get_request)r   r   r   r9   rV   rW   LISTEN_QUEUErequest_queue_sizer#   rh   r"  r%  r)  r   r   r   r   r    s   /		r  c               @   s"   e  Z d  Z d Z d Z d Z d S)ThreadedWSGIServerz"A WSGI server that does threading.TN)r   r   r   r9   rV   daemon_threadsr   r   r   r   r,    s   r,  c               @   s7   e  Z d  Z d Z d Z d d d d d d d  Z d S)ForkingWSGIServerz A WSGI server that does forking.T(   NFc	       	   	   C   sA   t  s t d   t j |  | | | | | | |  | |  _ d  S)Nz'Your platform does not support forking.)can_forkr+   r  r#   max_children)	r   r   r  r   	processesr   r   rN   r!  r   r   r   r#   +  s
    zForkingWSGIServer.__init__)r   r   r   r9   rW   r#   r   r   r   r   r.  %  s   r.  Fc	       	   
   C   s   | r! | d k r! t  d   nr | rF t |  | | | | | d | S| d k rt t |  | | | | | | d | St |  | | | | | d | Sd S)ztCreate a new server instance that is either threaded, or forks
    or just processes one request after another.
    r   z5cannot have a multithreaded and multi process server.r!  N)r+   r,  r.  r  )	r   r  r   threadedr2  request_handlerr   rN   r!  r   r   r   make_server>  s"    r5  c               C   s   t  j j d  d k S)zwChecks if the application is running from within the Werkzeug
    reloader subprocess.

    .. versionadded:: 0.10
    ZWERKZEUG_RUN_MAINtrue)r   rk   rb   r   r   r   r   r   c  s    r   TZautoc          	      s  t   t  s t d   | r@ d d l m } |   |    | re d d l m } |   |      f d d              f	 d d   } | rt   s d	 k r t r t	 d
   t
    } t   |  } t j | t j  } | j t j t j d  | j |  t | d  rJ| j d  t rt | j    t j d <| j t   |  n4 | j   | t k rt d d |  t j |  d d l m } | | | | |  n |   d S)a  Start a WSGI application. Optional features include a reloader,
    multithreading and fork support.

    This function has a command-line interface too::

        python -m werkzeug.serving --help

    .. versionadded:: 0.5
       `static_files` was added to simplify serving of static files as well
       as `passthrough_errors`.

    .. versionadded:: 0.6
       support for SSL was added.

    .. versionadded:: 0.8
       Added support for automatically loading a SSL context from certificate
       file and private key.

    .. versionadded:: 0.9
       Added command-line interface.

    .. versionadded:: 0.10
       Improved the reloader and added support for changing the backend
       through the `reloader_type` parameter.  See :ref:`reloader`
       for more information.

    .. versionchanged:: 0.15
        Bind to a Unix socket by passing a path that starts with
        ``unix://`` as the ``hostname``.

    :param hostname: The host to bind to, for example ``'localhost'``.
        If the value is a path that starts with ``unix://`` it will bind
        to a Unix socket instead of a TCP socket..
    :param port: The port for the server.  eg: ``8080``
    :param application: the WSGI application to execute
    :param use_reloader: should the server automatically restart the python
                         process if modules were changed?
    :param use_debugger: should the werkzeug debugging system be used?
    :param use_evalex: should the exception evaluation feature be enabled?
    :param extra_files: a list of files the reloader should watch
                        additionally to the modules.  For example configuration
                        files.
    :param reloader_interval: the interval for the reloader in seconds.
    :param reloader_type: the type of reloader to use.  The default is
                          auto detection.  Valid values are ``'stat'`` and
                          ``'watchdog'``. See :ref:`reloader` for more
                          information.
    :param threaded: should the process handle each request in a separate
                     thread?
    :param processes: if greater than 1 then handle each request in a new process
                      up to this maximum number of concurrent processes.
    :param request_handler: optional parameter that can be used to replace
                            the default one.  You can use this to replace it
                            with a different
                            :class:`~BaseHTTPServer.BaseHTTPRequestHandler`
                            subclass.
    :param static_files: a list or dict of paths for static files.  This works
                         exactly like :class:`SharedDataMiddleware`, it's actually
                         just wrapping the application in that middleware before
                         serving.
    :param passthrough_errors: set this to `True` to disable the error catching.
                               This means that the server will die on errors but
                               it can be useful to hook debuggers in (pdb etc.)
    :param ssl_context: an SSL context for the connection. Either an
                        :class:`ssl.SSLContext`, a tuple in the form
                        ``(cert_file, pkey_file)``, the string ``'adhoc'`` if
                        the server should automatically create one, or ``None``
                        to disable SSL (which is the default).
    zport must be an integerr   )DebuggedApplication)SharedDataMiddlewarec                s     d k r   n d } d } |  j  t k rC t d d | |  nQ d | k rY d | } |  j   d	 } t d d
  d  k r d n d | | |  d  S)Nr<   r   	localhostz(Press CTRL+C to quit)r   z * Running on %s %sr   z[%s]r   z * Running on %s://%s:%d/ %srA   rB   )r<   r   )r  r  r	   r  )r  Zdisplay_hostnameZquit_msgr  )hostnamerN   r   r   log_startup  s    
zrun_simple.<locals>.log_startupc                 s   y t  t j d  }  Wn t t f k
 r7 d  }  Yn Xt          d |  } |  d  k rx  | j  | j   d  S)NWERKZEUG_SERVER_FDr!  )r)   r   rk   LookupErrorr+   r5  r   r"  )r!  Zsrv)	applicationr:  r;  r   r  r2  r4  rN   r3  r   r   inner  s"    	zrun_simple.<locals>.innerr   zsCannot bind to a random port with enabled reloader if the Python interpreter does not support socket opening by fd.set_inheritableTr<  r   zUnlinking %s)run_with_reloaderN) rP   r)   r   debugr7  Zmiddleware.shared_datar8  r   can_open_by_fdr+   r  r  r   r  
setsockopt
SOL_SOCKETSO_REUSEADDRbindr   r@  rQ   filenor   rk   listenr*  rt   r  r	   r  	_reloaderrA  )r:  r  r>  use_reloaderuse_debuggerZ
use_evalexZextra_filesZreloader_intervalZreloader_typer3  r2  r4  Zstatic_filesr   rN   r7  r8  r?  r  r\   srA  r   )	r>  r:  r;  r   r  r2  r4  rN   r3  r   
run_simplel  sB    V*		
rN  c              O   s   d d l  m } | |  |   S)Nr   )rA  )rJ  rA  )r   r  rA  r   r   r   rA    s    rA  c        	      C   sy  d d l  }  d d l m } |  j d d  } | j d d d	 d
 d d | j d d d	 d d d d d d d | j d d d	 d d d d d d d | j   \ } } d  \ } } | j r | j j d  } | d } t |  d k r | d } t |  d k r(t	 j
 j d  t	 j d  | | d  } t d | pGd d t | pVd  d | d | j d | j  d S)!z:A simple command-line interface for :py:func:`run_simple`.r   Nr   )import_stringusagez,Usage: %prog [options] app_module:app_objectz-bz--binddestaddresshelpz+The hostname:port the app should listen on.z-dz--debugrL  action
store_truedefaultFzUse Werkzeug's debugger.z-rz--reloadrK  z(Reload Python process if modules change.r   z1No application supplied, or too much. See --help
r:  z	127.0.0.1r  i  r>  )NN)optparseutilsrO  OptionParser
add_option
parse_argsrR  ry   r2   rT   stdoutr   exitrN  r)   rK  rL  )	rW  rO  parseroptionsr   r:  r  rR  r   r   r   r   main'  sN    	

	r`  __main__)Br9   ior   r   r   rT   r   r   r   _compatr   r   r   r   Z	_internalr	   
exceptionsr
   urlsr   r   r   socketserverZhttp.serverr   r   r   SocketServerBaseHTTPServerrf   objectr   r   ThreadingMixInr   r0  r   r  r  ri   r*  rC  rL   r   ConnectionError	RawIOBaser   r:   BaseRequestHandlerr   r   r   r   r   r   r  r  r  r,  r.  r5  r   rN  rA  r`  r   r   r   r   r   <module>%   s   	5 S)*Y5