o bIs@sdZddlZddlZddlZddlZddlmZddlmZddl m Z m Z ddl m ZddlmZddlmZdd lmZdd lmZmZdd lmZmZdd lmZdd lmZmZm Z ddl!m"Z"m#Z#ddl$m%Z%ddl&m'Z'm(Z(ddl)m*Z*m+Z+m,Z,m-Z-ddl.m/Z/ddl0m1Z1dZ2gdZ3e%eddddddde%eddddddde*j4Z5e*j6Z7dZ8ddZ d d!Z9ee+j:Gd"d#d#e'e*j;ej<Z;ee+j=Gd$d%d%Z>ee+j?Gd&d'd'Z@Gd(d)d)ZAGd*d+d+ej<ZBe#d,ejCZCeejDGd-d.d.e*jEZFdS)/a This is a web server which integrates with the twisted.internet infrastructure. @var NOT_DONE_YET: A token value which L{twisted.web.resource.IResource.render} implementations can return to indicate that the application will later call C{.write} and C{.finish} to complete the request, and that the HTTP connection should be left open. @type NOT_DONE_YET: Opaque; do not depend on any particular type for this value. N)hexlify)escape)ListOptionalquote) implementer)Version) copyright)address interfaces) AlreadyCalledAlreadyCancelled)Logger) componentsfailurereflect) nativeString networkString)deprecatedModuleAttribute)Copyable ViewPoint)httpiwebresourceutil)UnsupportedMethod)unquote)supportedMethodsRequestSessionSiteversion NOT_DONE_YETGzipEncoderFactoryTwisted z4Please use twisted.web.http.datetimeToString insteadztwisted.web.serverdate_time_stringz4Please use twisted.web.http.stringToDatetime insteadstring_date_time)GETHEADsPOSTcOs"t|dg|Ri|dS)Ncharmap)_quotedecodeencode)stringargskwargsr34/usr/lib/python3/dist-packages/twisted/web/server.pyrKs"rcCs8t|tjr d|j|jfSt|tjrd|jfSt|S)NINETUNIX) isinstancer IPv4Addresshostport UNIXAddressnametuple)addrr3r3r4_addressToTupleOs   r?c@s@eZdZUdZdZdZdZdZee e e d<dZ ee e e d<dZ dZdZeZdd Zd d Zd d ZddZddZddZddZddZddZddZddZddZd d!Zd"d#Zd$d%Z d&d'Z!d>d(d)Z"d*d+Z#d,d-Z$dZ%dZ&e'd.d/Z(d?d0d1Z)d2d3Z*d4d5Z+d6d7Z,d8d9Z-d:d;Z.d} with it. @see: L{Site.getResourceFor()} sserversdaterNr]*)rIrK setHeaderr#rdatetimeToStringrArTmaprpathsplitrB _handleStargetResourceForr_IEncodingResource providedBy getEncoder_encoderrender BaseExceptionprocessingFailedrFailure)rFresrcencoderr3r3r4processs$       zRequest.processcCs|js6|jtjtjfv}|jd}|jd}|o|ddk}|r6|dur6|jdur6|s6|jd|jg|j sK|j rB|j |}tj ||dSdS)z Write data to the transport (if not responding to a HEAD request). @param data: A string to write to the response. @type data: L{bytes} content-typecontent-lengthr0N)startedWritingcoder NOT_MODIFIED NO_CONTENTresponseHeaders getRawHeadersdefaultContentType setRawHeaders _inFakeHeadror/r write)rFdataneedsCT contentType contentLengthcontentLengthZeror3r3r4rs&     z Request.writecCs.|jr|j}|rtj||tj|S)zH Override C{http.Request.finish} for possible encoding. )rofinishrr rrFrr3r3r4r s   zRequest.finishc CsZz||}Wnty}z|j}|jdkr\d|vr\|jjd|dd|_d|_||}|tur;|jjd|dn |ddt |fd |_d|_| d | WYd }~d S|jt vr|d d |dtt|jt|jt |dkr}dp~dd dd|Dd}ttjd|}||}nttjddt|jdf}||}WYd }~nd }~ww|turd St|tsttjddtt|ddtt|ddtt||}|jdkrt |dkr|jjd ||d!|ddt |f| d n|ddt |f| || d S)"ah Ask a resource to render itself. If the resource does not support the requested method, generate a C{NOT IMPLEMENTED} or C{NOT ALLOWED} response. @param resrc: The resource to render. @type resrc: L{twisted.web.resource.IResource} @see: L{IResource.render()} r+r*z,Using GET to fake a HEAD request for {resrc})rtTzBTried to fake a HEAD request for {resrc}, but it got away from me.rx%dFNAllows, zzYour browser approached me (at %(URI)s) with the method "%(method)s". I only allow the method%(plural)s %(allowed)s here.rsz, cSsg|]}t|qSr3)r).0rWr3r3r4 Osz"Request.render..)URImethodpluralallowedzMethod Not AllowedzHuh?z'I don't know how to treat a %s request.r,zRequest did not return bytesz Request: z
z Resource: zValue: rzbWarning: HEAD request {slf} for resource {resrc} is returning a message body. I think I'll eat it.)slfrt)rprallowedMethodsr_loginforr$rerZrrrjoinrrurir ErrorPager NOT_ALLOWEDNOT_IMPLEMENTEDr.r7bytesINTERNAL_SERVER_ERRORr_PREr safe_repr)rFrtbodyerrepager3r3r4rps       9      zRequest.rendercCst|jjd|d|jjrdt|d}nd}|tj| dd| dd t |f| || |S) aO Finish this request with an indication that processing failed and possibly display a traceback. @param reason: Reason this request has failed. @type reason: L{twisted.python.failure.Failure} @return: The reason passed to this method. @rtype: L{twisted.python.failure.Failure} r)rsweb.Server Traceback (most recent call last)web.Server Traceback (most recent call last): s s_Processing FailedProcessing Failedrwr@rxr) rrrKdisplayTracebacksr formatFailuresetResponseCoderrrerZrr)rFreasonrr3r3r4rr~s      zRequest.processingFailedcC||dS)z(Remote version of write; same interface.N)r)rFrVrr3r3r4 view_writezRequest.view_writecCs |dS)z)Remote version of finish; same interface.N)rrFrVr3r3r4 view_finishs zRequest.view_finishcKs|j||fi|dS)z,Remote version of addCookie; same interface.N) addCookie)rFrVkvr2r3r3r4view_addCookieszRequest.view_addCookiecC|||dS)z,Remote version of setHeader; same interface.N)re)rFrVrrr3r3r4view_setHeaderszRequest.view_setHeadercCr)z2Remote version of setLastModified; same interface.N)setLastModified)rFrVwhenr3r3r4view_setLastModifiedrzRequest.view_setLastModifiedcCr)z*Remote version of setETag; same interface.N)setETag)rFrVtagr3r3r4 view_setETagrzRequest.view_setETagcCr)zD Remote version of setResponseCode; same interface. N)r)rFrVr{messager3r3r4view_setResponseCodezRequest.view_setResponseCodecCs|t||dS)zbRemote version of registerProducer; same interface. (requires a remote producer.) N)registerProducer_RemoteProducerWrapper)rFrVproducer streamingr3r3r4view_registerProducerszRequest.view_registerProducercCs |dSrC)unregisterProducerrr3r3r4view_unregisterProducer zRequest.view_unregisterProducercCs|r|jS|jS)a If a session has already been created or looked up with L{Request.getSession}, this will return that object. (This will always be the session that matches the security of the request; so if C{forceNotSecure} is used on a secure request, this will not return that session.) @return: the session attribute @rtype: L{Session} or L{None} )isSecure_secureSession_insecureSessionrFr3r3r4sessions zRequest.sessionc Cs|o| }|sd}d}nd}d}t||}|dur/z|Wn ttfy.d}Ynw|durfd|g|j}||}|rUz|j |}Wn t yTYnw|sf|j }|j ||j d|dt||||rs||S|S) a Check if there is a session cookie, and if not, create it. By default, the cookie with be secure for HTTPS requests and not secure for HTTP requests. If for some reason you need access to the insecure cookie from a secure request you can set C{forceNotSecure = True}. @param forceNotSecure: Should we retrieve a session that will be transmitted over HTTP, even if this L{Request} was delivered over HTTPS? @type forceNotSecure: L{bool} sTWISTED_SESSIONrsTWISTED_SECURE_SESSIONrN_r])rhsecure)rgetattrtouchr rrsitepath getCookierK getSessionKeyError makeSessionruidsetattr getComponent) rFsessionInterfaceforceNotSecurer cookieStringsessionAttributer cookiename sessionCookier3r3r4rs:       zRequest.getSessioncCst|j}|r d}nd}||krd}nd|}td|r!dp"dt||f}ddd |D}||S) NiPrz:%dzhttp%s://%s%s/rr]cSsg|]}t|ddqS)r)safer)rsegmentr3r3r4r'sz'Request._prePathURL..)getHostr:rrrgetRequestHostnamer)rFrAr:defaulthostportprefixrhr3r3r4 _prePathURLs"  zRequest._prePathURLcCs ||jSrC)rrArr3r3r4 prePathURL*rzRequest.prePathURLcCsddlm}|j|S)Nr)urlpath)twisted.pythonrURLPath fromRequest)rFrr3r3r4r-s  zRequest.URLPathcCs||jdd}||_dS)z_ Remember the currently-processed part of the URL for later recalling. Nr\)rrA appRootURL)rFurlr3r3r4rememberRootURL2s zRequest.rememberRootURLcCs|jS)zn Get a previously-remembered URL. @return: An absolute URL. @rtype: L{bytes} )rrr3r3r4 getRootURL:szRequest.getRootURLcCsH|jdkr |tjn |tj|dd|dd|dS)a Handle receiving a request whose path is '*'. RFC 7231 defines an OPTIONS * request as being something that a client can send as a low-effort way to probe server capabilities or readiness. Rather than bother the user with this, we simply fast-path it back to an empty 200 OK. Any non-OPTIONS verb gets a 405 Method Not Allowed telling the client they can only use OPTIONS. sOPTIONSrsContent-LengthryN)rrrOKrrerrr3r3r4rjCs     zRequest._handleStarrC)NF)0__name__ __module__ __qualname____doc__rrKrrArrr__annotations__rB __pychecker__rrorrrDrXr[r_rbrvrrrprrrrrrrrrrrrrpropertyrrrrrrrrjr3r3r3r4r XsR $& g#   7 r c@s&eZdZdZedZdZddZdS)r%z~ @cvar compressLevel: The compression level used by the compressor, default to 9 (highest). @since: 12.3 s(:?^|[\s,])gzip(:?$|[\s,]) cCsfd|jdg}|j|r1|jd}|r!d|dg}nd}|jd|gt|j|SdS)zo Check the headers if the client accepts gzip encoding, and encodes the request if so. ,saccept-encodingscontent-encodingsgzipN) rrOr_gzipCheckRegexsearchr~r _GzipEncoder compressLevel)rFrequest acceptHeadersencodingr3r3r4encoderForRequestes    z$GzipEncoderFactory.encoderForRequestN) rrrrrecompilerrrr3r3r3r4r%Ys   r%c@s,eZdZdZdZddZddZddZdS) rz An encoder which supports gzip. @ivar _zlibCompressor: The zlib compressor instance used to compress the stream. @ivar _request: A reference to the originating request. @since: 12.3 NcCs"t|tjdtj|_||_dS)N)zlib compressobjDEFLATED MAX_WBITS_zlibCompressor_request)rFrrr3r3r4rDs z_GzipEncoder.__init__cCs"|jjs |jjd|j|S)zR Write to the request, automatically compressing data on the fly. rx)r rzr~ removeHeaderrcompressrr3r3r4r/s z_GzipEncoder.encodecCs|j}d|_|S)zf Finish handling the request request, flushing any data from the zlib buffer. N)rflush)rFremainr3r3r4rs z_GzipEncoder.finish)rrrrrrDr/rr3r3r3r4rxs   rc@seZdZddZdS)rcCs(|d|_|d|_|d|_dS)NresumeProducingpauseProducing stopProducing) remoteMethodrrr)rFrMr3r3r4rDs  z_RemoteProducerWrapper.__init__N)rrrrDr3r3r3r4rs rcsJeZdZdZdZdZdfdd ZddZdd Zd d Z d d Z Z S)r!a A user's session with a system. This utility class contains no functionality, but is used to represent a session. @ivar site: The L{Site} that generated the session. @type site: L{Site} @ivar uid: A unique identifier for the session. @type uid: L{bytes} @ivar _reactor: An object providing L{IReactorTime} to use for scheduling expiration. @ivar sessionTimeout: Time after last modification the session will expire, in seconds. @type sessionTimeout: L{float} @ivar lastModified: Time the C{touch()} method was last called (or time the session was created). A UNIX timestamp as returned by L{IReactorTime.seconds()}. @type lastModified: L{float} iNcsBt|dur |j}||_||_||_g|_|i|_dS)z Initialize a session with a unique ID for that session. @param reactor: L{IReactorTime} used to schedule expiration of the session. If C{None}, the reactor associated with I{site} is used. N) superrDreactor_reactorrKrexpireCallbacksrsessionNamespaces)rFrKrr __class__r3r4rDs  zSession.__init__cCs|j|j|j|_dS)zF Start expiration tracking. @return: L{None} N)r callLatersessionTimeoutexpire _expireCallrr3r3r4startCheckingExpirationszSession.startCheckingExpirationcCs|j|dS)zJ Call this callback when the session expires or logs out. N)rappend)rFcallbackr3r3r4notifyOnExpirerzSession.notifyOnExpirecCsP|jj|j=|jD]}|q g|_|jr$|jr&|jd|_dSdSdS)z/ Expire/logout of the session. N)rKsessionsrrractivecancel)rFcr3r3r4rs    zSession.expirecCs,|j|_|jdur|j|jdSdS)zN Mark the session as modified, which resets expiration timer. N)rseconds lastModifiedrresetrrr3r3r4rs  z Session.touchrC) rrrrrrrDrr rr __classcell__r3r3rr4r!s r!z TwistedWeb/cseZdZdZdZeZdZeZ dZ e j Z dfdd Zdd Zd d Zd d ZddZddZfddZdZddZddZddZddZZS)r"a* A web site: manage log, sessions, and resources. @ivar requestFactory: A factory which is called with (channel) and creates L{Request} instances. Default to L{Request}. @ivar displayTracebacks: If set, unhandled exceptions raised during rendering are returned to the client as HTML. Default to C{False}. @ivar sessionFactory: factory for sessions objects. Default to L{Session}. @ivar sessions: Mapping of session IDs to objects returned by C{sessionFactory}. @type sessions: L{dict} mapping L{bytes} to L{Session} given the default C{sessionFactory} @ivar counter: The number of sessions that have been generated. @type counter: L{int} @ivar sessionCheckTime: Deprecated and unused. See L{Session.sessionTimeout} instead. rFiNcs4tj|i|i|_||_|dur||_dSdS)a @param resource: The root of the resource hierarchy. All request traversal for requests received by this factory will begin at this resource. @type resource: L{IResource} provider @param requestFactory: Overwrite for default requestFactory. @type requestFactory: C{callable} or C{class}. @see: L{twisted.web.http.HTTPFactory.__init__} N)rrDr!rrequestFactory)rFrr)r1r2rr3r4rD s   z Site.__init__cCs(ddlm}|tj|tj|S)Nr)logfile)rr*LogFileosrhbasenamedirname)rFrhr*r3r3r4 _openLogFile1s zSite._openLogFilecCs|j}i|d<|S)Nr!)rPrQ)rFdr3r3r4 __getstate__6s zSite.__getstate__cCs|jd|_t|dS)zP (internal) Generate an opaque, unique ID for a user's session. r )counterr_entropyrr3r3r4_mkuid;s z Site._mkuidcCs*|}|||}|j|<||S)zU Generate a new Session instance, and store it for future reference. )r5sessionFactoryr!r)rFrrr3r3r4rBszSite.makeSessioncCs |j|S)z Get a previously generated session. @param uid: Unique ID of the session. @type uid: L{bytes}. @raise KeyError: If the session is not found. )r!)rFrr3r3r4rKs zSite.getSessioncst|}|j|_||_|S)z; Generate a channel attached to this site. )r buildProtocolr)rK)rFr>rIrr3r4r7Vs zSite.buildProtocolcCs||d|dS)z@ Redirect because a Site is always a directory. r]N)redirectrrrFrr3r3r4rpas z Site.rendercCs||_|j||S)z7 Emulate a resource's getChild method. )rKrgetChildWithDefault)rFpathElrr3r3r4r:hszSite.getChildWithDefaultcCs"||_t|j|_t|j|S)z Get a resource for a request. This iterates through the resource hierarchy, calling getChildWithDefault on each resource it finds for a path element, stopping when it hits an element where isLeaf is true. )rKrQrArrgetChildForRequestr9r3r3r4rkoszSite.getResourceForcCsdg}tjr |dd|S)z2 Protocols this server can speak. shttp/1.1rsh2)r H2_ENABLEDinsert)rF baseProtocolsr3r3r4acceptableProtocols~s zSite.acceptableProtocolsrC)rrrrr3r r)rr!r6sessionCheckTimer,urandomr4rDr/r1r5rrr7isLeafrpr:rkr@r(r3r3rr4r"s(  r")GrrQr,rrbinasciirhtmlrtypingrr urllib.parserr-zope.interfacer incrementalr twistedr twisted.internetr r twisted.internet.errorr rtwisted.loggerrrrrrtwisted.python.compatrrtwisted.python.deprecatertwisted.spread.pbrr twisted.webrrrrtwisted.web.errorrtwisted.web.httprr$__all__rfr(stringToDatetimer)rr?IRequestr rE_IRequestEncoderFactoryr%_IRequestEncoderrrr!r#IProtocolNegotiationFactory HTTPFactoryr"r3r3r3r4sp              (U