o 6a@sHddlmZddlmZddlmZmZGdddZGdddZdS) )BytesIO)SpooledTemporaryFile) AsyncToSync sync_to_asyncc@s eZdZdZddZddZdS) WsgiToAsgizG Wraps a WSGI application to make it into an ASGI application. cCs ||_dSN)wsgi_applicationselfrr ./usr/lib/python3/dist-packages/asgiref/wsgi.py__init__ s zWsgiToAsgi.__init__cst|j|||IdHdS)z ASGI application instantiation point. We return a new WsgiToAsgiInstance here with the WSGI app and the scope, ready to respond when it is __call__ed. N)WsgiToAsgiInstancer)r scopereceivesendr r r __call__szWsgiToAsgi.__call__N)__name__ __module__ __qualname____doc__r rr r r r rs rc@s>eZdZdZddZddZddZd d d Zed d Z dS)rz; Per-socket instance of a wrapped WSGI application cCs||_d|_d|_dS)NF)rresponse_startedresponse_content_lengthr r r r r s zWsgiToAsgiInstance.__init__cs|ddkr td||_tdd<} |IdH}|ddkr%td||d d |d s4nq|d t||_||IdHWddS1sRwYdS) Ntypehttpz&WSGI wrapper received a non-HTTP scopei)max_sizeTz http.requestz0WSGI wrapper received a non-HTTP-request messagebody more_bodyr) ValueErrorrrwritegetseekr sync_send run_wsgi_app)r rrrrmessager r r r"s"       "zWsgiToAsgiInstance.__call__c Cs8|d|dddd|ddd|ddd |d d |d d |tdddd }d|vrH|dd|d<t|dd|d<nd|d<d|d<d|vr\|dd|d<|jdgD]6\}}|d}|dkrsd}n|dkrzd}n d|d d!}|d}||vr||d"|}|||<qc|S)#zM Builds a scope and request body into a WSGI environ object. method root_pathutf8latin1path query_stringasciizHTTP/%s http_version)rschemerTF) REQUEST_METHOD SCRIPT_NAME PATH_INFO QUERY_STRINGSERVER_PROTOCOLz wsgi.versionzwsgi.url_schemez wsgi.inputz wsgi.errorszwsgi.multithreadzwsgi.multiprocessz wsgi.run_onceserverr SERVER_NAMEr/ SERVER_PORT localhost80client REMOTE_ADDRheaderscontent-lengthCONTENT_LENGTHz content-type CONTENT_TYPEzHTTP_%s-_,)r!encodedecoderstrrupperreplace)r rrenvironnamevaluecorrected_namer r r build_environ5s@      z WsgiToAsgiInstance.build_environNc Cs|jr |d|dt|dr|durtd|dd\}}t|}dd|D}d|_|D]\}}|d kr@t||_q1d ||d |_dS) z/ WSGI start_response callable. r/response_startNz=You cannot call start_response a second time without exc_info cSs(g|]\}}|d|dfqS)r-)lowerrD).0rJrKr r r rsz5WsgiToAsgiInstance.start_response..r>zhttp.response.start)rstatusr=) rwith_tracebackhasattrrsplitintrrQrO) r rTresponse_headersexc_info status_coderBr=rJrKr r r start_responsebs(    z!WsgiToAsgiInstance.start_responsecCs||j|}d}|||jD]:}|jsd|_||j|jdur4|j|}t||kr4|d|}|d|dd|t|7}||jkrJnq|jsWd|_||j|ddidS)z Called in a subthread to run the WSGI app. We encapsulate like this so that the start_response callable is called in the same thread. rTNzhttp.response.body)rrrr) rMrrr\rr#rOrlen)r rrI bytes_sentoutput bytes_allowedr r r r$s*         zWsgiToAsgiInstance.run_wsgi_appr) rrrrr rrMr\rr$r r r r rs - rN) iortempfiler asgiref.syncrrrrr r r r s