a +b Y@sddlmZddlmZddlmZmZmZmZddl m Z Gddde Z ej dd Gd d d e Zdd dZGddde ZGddde ZddZd S))absolute_import)attr)encodingerrorpycompatutil)urlutilc@sjeZdZdZddZddZddZdd Zd d Zd d Z dddZ ddZ ddZ ddZ ddZdS) multidictzA dict like object that can store multiple values for a key. Used to store parsed request parameters. This is inspired by WebOb's class of the same name. cCs i|_dSN_itemsselfr=/usr/lib64/python3.9/site-packages/mercurial/hgweb/request.py__init__!szmultidict.__init__cCs|j|dS)z%Returns the last set value for a key.r rkeyrrr __getitem__$szmultidict.__getitem__cCs|g|j|<dS)z,Replace a values for a key with a new value.Nr rrvaluerrr __setitem__(szmultidict.__setitem__cCs |j|=dS)zDelete all values for a key.Nr rrrr __delitem__,szmultidict.__delitem__cCs ||jvSr r rrrr __contains__0szmultidict.__contains__cCs t|jSr )lenr rrrr__len__3szmultidict.__len__NcCs(z ||WSty"|YS0dSr )rKeyError)rrdefaultrrrget6s  z multidict.getcCs|j|g|dS)zQz+multidict.asdictoflists..)r iteritemsr rrrr asdictoflistsPszmultidict.asdictoflists)N)__name__ __module__ __qualname____doc__rrrrrrr r#r$r&r/rrrrr s  r T)frozenc@seZdZdZeZeZeZeZ eZ eZ eZ eZ eZeZeZeZeZeZeZeZeZdS) parsedrequestztRepresents a parsed WSGI request. Contains both parsed parameters as well as a handle on the input stream. N)r0r1r2r3rZibmethodurlbaseurl advertisedurladvertisedbaseurl urlscheme remoteuser remotehostapppath dispatchparts dispatchpathreponame querystringqsparamsheadersbodyfhrawenvrrrrr5Ts$r5Ncs|tjr&ddfddt|D}|s4|d}|rBt|}|dd}|rd|jrd|jd}n|}dd }|d r||d 7}n||d 7}|||d }|r|jr||j7}|jr|j}n4|jd kr|jsd}n|jdkr|jsd}n|d }|||}n||d 7}|||d }|}|} |t j |dd7}|t j |dd7}|r|j pjd} | r| dsd| } |t j | 7}n|t j |dd7}|t j |dd7}|dr|d|d7}|d|d7}|r"|j pd} | r.| ds.d| } n |dd} |rd|d} |dsXtd|d | s~td|d|f|dt| d} | r| dstd|d|f| d| } | dd}d|} nLd|vr(|ddr|ddd}d|} ng}d} ng}d} |dd}t}t j j|ddD]\}}|||qRg}t|D]8\}}| drx||tdddd|fqxd d!lm}||}d"|vrd#|vr|d"|d$<d%|vrd&|vr|d%|d'<|dur>|d(}d$|vr>t |t|d$p8d)}t|d*|||| |d|d+|d,| || ||||||d-S).aParse URL components from environment variables. WSGI defines request attributes via environment variables. This function parses the environment variables into a data structure. If ``reponame`` is defined, the leading path components matching that string are effectively shifted from ``PATH_INFO`` to ``SCRIPT_NAME``. This simulates the world view of a WSGI application that processes requests from the base URL of a repo. If ``altbaseurl`` (typically comes from ``web.baseurl`` config option) is defined, it is used - instead of the WSGI environment variables - for constructing URL components up to and including the WSGI application path. For example, if the current WSGI application is at ``/repo`` and a request is made to ``/rev/@`` with this argument set to ``http://myserver:9000/prefix``, the URL and path components will resolve as if the request were to ``http://myserver:9000/prefix/rev/@``. In other words, ``wsgi.url_scheme``, ``SERVER_NAME``, ``SERVER_PORT``, and ``SCRIPT_NAME`` are all effectively replaced by components from this URL. ``bodyfh`` can be used to specify a file object to read the request body from. If not defined, ``wsgi.input`` from the environment dict is used. cSs,t|ts|Stjrt|St|SdSr ) isinstancestrrZ iswindowsrZ strtolocalfsencode)srrrtobytess   z$parserequestfromenv..tobytescsi|]\}}||qSrrr(rKrrr,r-z'parserequestfromenv..s REPO_NAMEswsgi.url_schemes://cSs8|dr |dkr4|d|7}n|dkr4|d|7}|S)Nshttps://443:80) startswith)rJportrrraddports   z$parserequestfromenv..addports HTTP_HOSTs SERVER_NAMEs SERVER_PORTshttprOshttpsrMs SCRIPT_NAMEr-s PATH_INFO/s QUERY_STRING?sreponame requires PATH_INFOs0PATH_INFO does not begin with repo name: %s (%s)NsDreponame prefix of PATH_INFO does not end at path delimiter: %s (%s)T)keep_blank_valuessHTTP__-r% wsgiheaderssCONTENT_LENGTHsHTTP_CONTENT_LENGTHContent-Lengths CONTENT_TYPEsHTTP_CONTENT_TYPEs Content-Types wsgi.input0sREQUEST_METHODs REMOTE_USERs REMOTE_HOST)r6r7r8r9r:r;r<r=r>r?r@rArBrCrDrErF) rZispy3r.r r r7schemehostrQrZurlreqquotepathrPstriprProgrammingErrorrrstripsplitjoinr Zparseqslr#r"replacerYHeaders cappedreaderintr5)envrAZ altbaseurlrEZfullurlZadvertisedfullurlrRrQr8r:r_r>Z repoprefixr@r?rBrCr*r+rDrYrrLrparserequestfromenvs#                         &      rkc@s0eZdZdZddZddZddZdd Zd S) offsettrackingwriteraA file object like object that is append only and tracks write count. Instances are bound to a callable. This callable is called with data whenever a ``write()`` is attempted. Instances track the amount of written data so they can answer ``tell()`` requests. The intent of this class is to wrap the ``write()`` function returned by a WSGI ``start_response()`` function. Since ``write()`` is a callable and not a file object, it doesn't implement other file object methods. cCs||_d|_dS)Nr)_write_offset)rZwritefnrrrrwszoffsettrackingwriter.__init__cCs8||}|dur&|jt|7_n|j|7_dSr )rmrnr)rrJresrrrwrite{s zoffsettrackingwriter.writecCsdSr rrrrrflushszoffsettrackingwriter.flushcCs|jSr )rnrrrrtellszoffsettrackingwriter.tellN)r0r1r2r3rrprqrrrrrrrlis  rlc@sHeZdZdZddZddZddZdd Zd d Zd d Z ddZ dS) wsgiresponseaPRepresents a response to a WSGI request. A response consists of a status line, headers, and a body. Consumers must populate the ``status`` and ``headers`` fields and make a call to a ``setbody*()`` method before the response can be issued. When it is time to start sending the response over the wire, ``sendresponse()`` is called. It handles emitting the header portion of the response message. It then yields chunks of body data to be written to the peer. Typically, the WSGI application itself calls and returns the value from ``sendresponse()``. cCsL||_||_d|_ddlm}|g|_d|_d|_d|_ d|_ d|_ dS)zCreate an empty response tied to a specific request. ``req`` is a ``parsedrequest``. ``startresponse`` is the ``start_response`` function passed to the WSGI application. Nr%rXF) _req_startresponsestatusrfrYrgrD _bodybytes_bodygen_bodywillwrite_started _bodywritefn)rZreqZ startresponserYrrrrs  zwsgiresponse.__init__cCs(|jdus|jdus|jr$tddS)Ns!cannot define body multiple times)rwrxryrrarrrr _verifybodyszwsgiresponse._verifybodycCs$|||_dt||jd<dS)ztDefine the response body as static bytes. The empty string signals that there is no response body. s%drZN)r|rwrrD)rbrrr setbodybytesszwsgiresponse.setbodybytescCs|||_dS)z1Define the response body as a generator of bytes.N)r|rx)rgenrrr setbodygenszwsgiresponse.setbodygencCs|d|_dS)aSignal an intent to use write() to emit the response body. **This is the least preferred way to send a body.** It is preferred for WSGI applications to emit a generator of chunks constituting the response body. However, some consumers can't emit data this way. So, WSGI provides a way to obtain a ``write(data)`` function that can be used to synchronously perform an unbuffered write. Calling this function signals an intent to produce the body in this manner. TN)r|ryrrrrsetbodywillwriteszwsgiresponse.setbodywillwriteccs|jrtdd|_|js&td|jdurJ|jdurJ|jsJtd|jdr|j ddkrn|jd=d d |j D}|rtd d t ||jdus|jrtd d}d}|j j dddkrn(|j jdvrnt|j jtjsd}nd}|rd|jd<|rJt|j jtjs.J|j jd}|s.qJq.dd|jD}|t|j|}|jr|jVnL|jr|jD] }t|trt|}|Vqn|jr||_n tddS)zSend the generated response to the client. Before this is called, ``status`` must be set and one of ``setbodybytes()`` or ``setbodygen()`` must be called. Calling this method multiple times is not allowed. s$sendresponse() called multiple timesTsstatus line not definedNsresponse body not defineds304 rZr[cSsh|]}|dvr|qS))sdatesetagsexpiress cache-controlscontent-locationscontent-security-policysvary)lower)r)r*rrr s z,wsgiresponse.sendresponse..s"illegal header on 304 response: %ss, s,must use setbodybytes('') with 304 responsesFsExpectr-s 100-continue)sPOSTsPUTsCloses ConnectionicSs$g|]\}}t|t|fqSr)rZstrurlr(rrr Esz-wsgiresponse.sendresponse..sdo not know how to send body)rzrrarvrwrxryrPrDr keysrdsortedrtrr6rGrErrhreaditemsrurZsysstr bytearraybytesr{)rZ badheadersZdrainclosechunkZ strheadersrprrr sendresponsesx          zwsgiresponse.sendresponsecCs4|jstd|js td|js*Jt|jS)aObtain a file object like object representing the response body. For this to work, you must call ``setbodywillwrite()`` and then ``sendresponse()`` first. ``sendresponse()`` is a generator and the function won't run to completion unless the generator is advanced. The generator yields not items. The easiest way to consume it is with ``list(res.sendresponse())``, which should resolve to an empty list - ``[]``. s"must call setbodywillwrite() firstsWmust call sendresponse() first; did you remember to consume it since it is a generator?)ryrrarzr{rlrrrr getbodyfile[s   zwsgiresponse.getbodyfileN) r0r1r2r3rr|r~rrrrrrrrrss rscs|fdd}|S)z{For compatibility with old CGI scripts. A plain hgweb() or hgwebdir() can and should now be used as a WSGI application.cs ||Sr r)rjZrespondZ applicationrrrun_wsgixsz!wsgiapplication..run_wsgir)Z app_makerrrrrwsgiapplicationss r)NNN)Z __future__rZ thirdpartyrrfrrrrZutilsr objectr rJr5rkrlrsrrrrr s   ; 0 e!j