asda?‰PNG  IHDR ? f ??C1 sRGB ??é gAMA ±? üa pHYs ? ??o¨d GIDATx^íüL”÷e÷Y?a?("Bh?_ò???¢§?q5k?*:t0A-o??¥]VkJ¢M??f?±8\k2íll£1]q?ù???T PKe[rutil.pynu["""Miscellaneous WSGI-related Utilities""" import posixpath __all__ = [ 'FileWrapper', 'guess_scheme', 'application_uri', 'request_uri', 'shift_path_info', 'setup_testing_defaults', ] class FileWrapper: """Wrapper to convert file-like objects to iterables""" def __init__(self, filelike, blksize=8192): self.filelike = filelike self.blksize = blksize if hasattr(filelike,'close'): self.close = filelike.close def __getitem__(self,key): data = self.filelike.read(self.blksize) if data: return data raise IndexError def __iter__(self): return self def __next__(self): data = self.filelike.read(self.blksize) if data: return data raise StopIteration def guess_scheme(environ): """Return a guess for whether 'wsgi.url_scheme' should be 'http' or 'https' """ if environ.get("HTTPS") in ('yes','on','1'): return 'https' else: return 'http' def application_uri(environ): """Return the application's base URI (no PATH_INFO or QUERY_STRING)""" url = environ['wsgi.url_scheme']+'://' from urllib.parse import quote if environ.get('HTTP_HOST'): url += environ['HTTP_HOST'] else: url += environ['SERVER_NAME'] if environ['wsgi.url_scheme'] == 'https': if environ['SERVER_PORT'] != '443': url += ':' + environ['SERVER_PORT'] else: if environ['SERVER_PORT'] != '80': url += ':' + environ['SERVER_PORT'] url += quote(environ.get('SCRIPT_NAME') or '/', encoding='latin1') return url def request_uri(environ, include_query=True): """Return the full request URI, optionally including the query string""" url = application_uri(environ) from urllib.parse import quote path_info = quote(environ.get('PATH_INFO',''), safe='/;=,', encoding='latin1') if not environ.get('SCRIPT_NAME'): url += path_info[1:] else: url += path_info if include_query and environ.get('QUERY_STRING'): url += '?' + environ['QUERY_STRING'] return url def shift_path_info(environ): """Shift a name from PATH_INFO to SCRIPT_NAME, returning it If there are no remaining path segments in PATH_INFO, return None. Note: 'environ' is modified in-place; use a copy if you need to keep the original PATH_INFO or SCRIPT_NAME. Note: when PATH_INFO is just a '/', this returns '' and appends a trailing '/' to SCRIPT_NAME, even though empty path segments are normally ignored, and SCRIPT_NAME doesn't normally end in a '/'. This is intentional behavior, to ensure that an application can tell the difference between '/x' and '/x/' when traversing to objects. """ path_info = environ.get('PATH_INFO','') if not path_info: return None path_parts = path_info.split('/') path_parts[1:-1] = [p for p in path_parts[1:-1] if p and p != '.'] name = path_parts[1] del path_parts[1] script_name = environ.get('SCRIPT_NAME','') script_name = posixpath.normpath(script_name+'/'+name) if script_name.endswith('/'): script_name = script_name[:-1] if not name and not script_name.endswith('/'): script_name += '/' environ['SCRIPT_NAME'] = script_name environ['PATH_INFO'] = '/'.join(path_parts) # Special case: '/.' on PATH_INFO doesn't get stripped, # because we don't strip the last element of PATH_INFO # if there's only one path part left. Instead of fixing this # above, we fix it here so that PATH_INFO gets normalized to # an empty string in the environ. if name=='.': name = None return name def setup_testing_defaults(environ): """Update 'environ' with trivial defaults for testing purposes This adds various parameters required for WSGI, including HTTP_HOST, SERVER_NAME, SERVER_PORT, REQUEST_METHOD, SCRIPT_NAME, PATH_INFO, and all of the wsgi.* variables. It only supplies default values, and does not replace any existing settings for these variables. This routine is intended to make it easier for unit tests of WSGI servers and applications to set up dummy environments. It should *not* be used by actual WSGI servers or applications, since the data is fake! """ environ.setdefault('SERVER_NAME','127.0.0.1') environ.setdefault('SERVER_PROTOCOL','HTTP/1.0') environ.setdefault('HTTP_HOST',environ['SERVER_NAME']) environ.setdefault('REQUEST_METHOD','GET') if 'SCRIPT_NAME' not in environ and 'PATH_INFO' not in environ: environ.setdefault('SCRIPT_NAME','') environ.setdefault('PATH_INFO','/') environ.setdefault('wsgi.version', (1,0)) environ.setdefault('wsgi.run_once', 0) environ.setdefault('wsgi.multithread', 0) environ.setdefault('wsgi.multiprocess', 0) from io import StringIO, BytesIO environ.setdefault('wsgi.input', BytesIO()) environ.setdefault('wsgi.errors', StringIO()) environ.setdefault('wsgi.url_scheme',guess_scheme(environ)) if environ['wsgi.url_scheme']=='http': environ.setdefault('SERVER_PORT', '80') elif environ['wsgi.url_scheme']=='https': environ.setdefault('SERVER_PORT', '443') _hoppish = { 'connection':1, 'keep-alive':1, 'proxy-authenticate':1, 'proxy-authorization':1, 'te':1, 'trailers':1, 'transfer-encoding':1, 'upgrade':1 }.__contains__ def is_hop_by_hop(header_name): """Return true if 'header_name' is an HTTP/1.1 "Hop-by-Hop" header""" return _hoppish(header_name.lower()) PKe[Utsimple_server.pynu["""BaseHTTPServer that implements the Python WSGI protocol (PEP 3333) This is both an example of how WSGI can be implemented, and a basis for running simple web applications on a local machine, such as might be done when testing or debugging an application. It has not been reviewed for security issues, however, and we strongly recommend that you use a "real" web server for production use. For example usage, see the 'if __name__=="__main__"' block at the end of the module. See also the BaseHTTPServer module docs for other API information. """ from http.server import BaseHTTPRequestHandler, HTTPServer import sys import urllib.parse from wsgiref.handlers import SimpleHandler from platform import python_implementation __version__ = "0.2" __all__ = ['WSGIServer', 'WSGIRequestHandler', 'demo_app', 'make_server'] server_version = "WSGIServer/" + __version__ sys_version = python_implementation() + "/" + sys.version.split()[0] software_version = server_version + ' ' + sys_version class ServerHandler(SimpleHandler): server_software = software_version def close(self): try: self.request_handler.log_request( self.status.split(' ',1)[0], self.bytes_sent ) finally: SimpleHandler.close(self) class WSGIServer(HTTPServer): """BaseHTTPServer that implements the Python WSGI protocol""" application = None def server_bind(self): """Override server_bind to store the server name.""" HTTPServer.server_bind(self) self.setup_environ() def setup_environ(self): # Set up base environment env = self.base_environ = {} env['SERVER_NAME'] = self.server_name env['GATEWAY_INTERFACE'] = 'CGI/1.1' env['SERVER_PORT'] = str(self.server_port) env['REMOTE_HOST']='' env['CONTENT_LENGTH']='' env['SCRIPT_NAME'] = '' def get_app(self): return self.application def set_app(self,application): self.application = application class WSGIRequestHandler(BaseHTTPRequestHandler): server_version = "WSGIServer/" + __version__ def get_environ(self): env = self.server.base_environ.copy() env['SERVER_PROTOCOL'] = self.request_version env['SERVER_SOFTWARE'] = self.server_version env['REQUEST_METHOD'] = self.command if '?' in self.path: path,query = self.path.split('?',1) else: path,query = self.path,'' env['PATH_INFO'] = urllib.parse.unquote(path, 'iso-8859-1') env['QUERY_STRING'] = query host = self.address_string() if host != self.client_address[0]: env['REMOTE_HOST'] = host env['REMOTE_ADDR'] = self.client_address[0] if self.headers.get('content-type') is None: env['CONTENT_TYPE'] = self.headers.get_content_type() else: env['CONTENT_TYPE'] = self.headers['content-type'] length = self.headers.get('content-length') if length: env['CONTENT_LENGTH'] = length for k, v in self.headers.items(): k=k.replace('-','_').upper(); v=v.strip() if k in env: continue # skip content length, type,etc. if 'HTTP_'+k in env: env['HTTP_'+k] += ','+v # comma-separate multiple headers else: env['HTTP_'+k] = v return env def get_stderr(self): return sys.stderr def handle(self): """Handle a single HTTP request""" self.raw_requestline = self.rfile.readline(65537) if len(self.raw_requestline) > 65536: self.requestline = '' self.request_version = '' self.command = '' self.send_error(414) return if not self.parse_request(): # An error code has been sent, just exit return handler = ServerHandler( self.rfile, self.wfile, self.get_stderr(), self.get_environ() ) handler.request_handler = self # backpointer for logging handler.run(self.server.get_app()) def demo_app(environ,start_response): from io import StringIO stdout = StringIO() print("Hello world!", file=stdout) print(file=stdout) h = sorted(environ.items()) for k,v in h: print(k,'=',repr(v), file=stdout) start_response("200 OK", [('Content-Type','text/plain; charset=utf-8')]) return [stdout.getvalue().encode("utf-8")] def make_server( host, port, app, server_class=WSGIServer, handler_class=WSGIRequestHandler ): """Create a new WSGI server listening on `host` and `port` for `app`""" server = server_class((host, port), handler_class) server.set_app(app) return server if __name__ == '__main__': with make_server('', 8000, demo_app) as httpd: sa = httpd.socket.getsockname() print("Serving HTTP on", sa[0], "port", sa[1], "...") import webbrowser webbrowser.open('http://localhost:8000/xyz?abc') httpd.handle_request() # serve one request, then exit PKe[X-nn headers.pynu["""Manage HTTP Response Headers Much of this module is red-handedly pilfered from email.message in the stdlib, so portions are Copyright (C) 2001,2002 Python Software Foundation, and were written by Barry Warsaw. """ # Regular expression that matches `special' characters in parameters, the # existence of which force quoting of the parameter value. import re tspecials = re.compile(r'[ \(\)<>@,;:\\"/\[\]\?=]') def _formatparam(param, value=None, quote=1): """Convenience function to format and return a key=value pair. This will quote the value if needed or if quote is true. """ if value is not None and len(value) > 0: if quote or tspecials.search(value): value = value.replace('\\', '\\\\').replace('"', r'\"') return '%s="%s"' % (param, value) else: return '%s=%s' % (param, value) else: return param class Headers: """Manage a collection of HTTP response headers""" def __init__(self, headers=None): headers = headers if headers is not None else [] if type(headers) is not list: raise TypeError("Headers must be a list of name/value tuples") self._headers = headers if __debug__: for k, v in headers: self._convert_string_type(k) self._convert_string_type(v) def _convert_string_type(self, value): """Convert/check value type.""" if type(value) is str: return value raise AssertionError("Header names/values must be" " of type str (got {0})".format(repr(value))) def __len__(self): """Return the total number of headers, including duplicates.""" return len(self._headers) def __setitem__(self, name, val): """Set the value of a header.""" del self[name] self._headers.append( (self._convert_string_type(name), self._convert_string_type(val))) def __delitem__(self,name): """Delete all occurrences of a header, if present. Does *not* raise an exception if the header is missing. """ name = self._convert_string_type(name.lower()) self._headers[:] = [kv for kv in self._headers if kv[0].lower() != name] def __getitem__(self,name): """Get the first header value for 'name' Return None if the header is missing instead of raising an exception. Note that if the header appeared multiple times, the first exactly which occurrence gets returned is undefined. Use getall() to get all the values matching a header field name. """ return self.get(name) def __contains__(self, name): """Return true if the message contains the header.""" return self.get(name) is not None def get_all(self, name): """Return a list of all the values for the named field. These will be sorted in the order they appeared in the original header list or were added to this instance, and may contain duplicates. Any fields deleted and re-inserted are always appended to the header list. If no fields exist with the given name, returns an empty list. """ name = self._convert_string_type(name.lower()) return [kv[1] for kv in self._headers if kv[0].lower()==name] def get(self,name,default=None): """Get the first header value for 'name', or return 'default'""" name = self._convert_string_type(name.lower()) for k,v in self._headers: if k.lower()==name: return v return default def keys(self): """Return a list of all the header field names. These will be sorted in the order they appeared in the original header list, or were added to this instance, and may contain duplicates. Any fields deleted and re-inserted are always appended to the header list. """ return [k for k, v in self._headers] def values(self): """Return a list of all header values. These will be sorted in the order they appeared in the original header list, or were added to this instance, and may contain duplicates. Any fields deleted and re-inserted are always appended to the header list. """ return [v for k, v in self._headers] def items(self): """Get all the header fields and values. These will be sorted in the order they were in the original header list, or were added to this instance, and may contain duplicates. Any fields deleted and re-inserted are always appended to the header list. """ return self._headers[:] def __repr__(self): return "%s(%r)" % (self.__class__.__name__, self._headers) def __str__(self): """str() returns the formatted headers, complete with end line, suitable for direct HTTP transmission.""" return '\r\n'.join(["%s: %s" % kv for kv in self._headers]+['','']) def __bytes__(self): return str(self).encode('iso-8859-1') def setdefault(self,name,value): """Return first matching header value for 'name', or 'value' If there is no header named 'name', add a new header with name 'name' and value 'value'.""" result = self.get(name) if result is None: self._headers.append((self._convert_string_type(name), self._convert_string_type(value))) return value else: return result def add_header(self, _name, _value, **_params): """Extended header setting. _name is the header field to add. keyword arguments can be used to set additional parameters for the header field, with underscores converted to dashes. Normally the parameter will be added as key="value" unless value is None, in which case only the key will be added. Example: h.add_header('content-disposition', 'attachment', filename='bud.gif') Note that unlike the corresponding 'email.message' method, this does *not* handle '(charset, language, value)' tuples: all values must be strings or None. """ parts = [] if _value is not None: _value = self._convert_string_type(_value) parts.append(_value) for k, v in _params.items(): k = self._convert_string_type(k) if v is None: parts.append(k.replace('_', '-')) else: v = self._convert_string_type(v) parts.append(_formatparam(k.replace('_', '-'), v)) self._headers.append((self._convert_string_type(_name), "; ".join(parts))) PKe[g: R R handlers.pynu["""Base classes for server/gateway implementations""" from .util import FileWrapper, guess_scheme, is_hop_by_hop from .headers import Headers import sys, os, time __all__ = [ 'BaseHandler', 'SimpleHandler', 'BaseCGIHandler', 'CGIHandler', 'IISCGIHandler', 'read_environ' ] # Weekday and month names for HTTP date/time formatting; always English! _weekdayname = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] _monthname = [None, # Dummy so we can use 1-based month numbers "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] def format_date_time(timestamp): year, month, day, hh, mm, ss, wd, y, z = time.gmtime(timestamp) return "%s, %02d %3s %4d %02d:%02d:%02d GMT" % ( _weekdayname[wd], day, _monthname[month], year, hh, mm, ss ) _is_request = { 'SCRIPT_NAME', 'PATH_INFO', 'QUERY_STRING', 'REQUEST_METHOD', 'AUTH_TYPE', 'CONTENT_TYPE', 'CONTENT_LENGTH', 'HTTPS', 'REMOTE_USER', 'REMOTE_IDENT', }.__contains__ def _needs_transcode(k): return _is_request(k) or k.startswith('HTTP_') or k.startswith('SSL_') \ or (k.startswith('REDIRECT_') and _needs_transcode(k[9:])) def read_environ(): """Read environment, fixing HTTP variables""" enc = sys.getfilesystemencoding() esc = 'surrogateescape' try: ''.encode('utf-8', esc) except LookupError: esc = 'replace' environ = {} # Take the basic environment from native-unicode os.environ. Attempt to # fix up the variables that come from the HTTP request to compensate for # the bytes->unicode decoding step that will already have taken place. for k, v in os.environ.items(): if _needs_transcode(k): # On win32, the os.environ is natively Unicode. Different servers # decode the request bytes using different encodings. if sys.platform == 'win32': software = os.environ.get('SERVER_SOFTWARE', '').lower() # On IIS, the HTTP request will be decoded as UTF-8 as long # as the input is a valid UTF-8 sequence. Otherwise it is # decoded using the system code page (mbcs), with no way to # detect this has happened. Because UTF-8 is the more likely # encoding, and mbcs is inherently unreliable (an mbcs string # that happens to be valid UTF-8 will not be decoded as mbcs) # always recreate the original bytes as UTF-8. if software.startswith('microsoft-iis/'): v = v.encode('utf-8').decode('iso-8859-1') # Apache mod_cgi writes bytes-as-unicode (as if ISO-8859-1) direct # to the Unicode environ. No modification needed. elif software.startswith('apache/'): pass # Python 3's http.server.CGIHTTPRequestHandler decodes # using the urllib.unquote default of UTF-8, amongst other # issues. elif ( software.startswith('simplehttp/') and 'python/3' in software ): v = v.encode('utf-8').decode('iso-8859-1') # For other servers, guess that they have written bytes to # the environ using stdio byte-oriented interfaces, ending up # with the system code page. else: v = v.encode(enc, 'replace').decode('iso-8859-1') # Recover bytes from unicode environ, using surrogate escapes # where available (Python 3.1+). else: v = v.encode(enc, esc).decode('iso-8859-1') environ[k] = v return environ class BaseHandler: """Manage the invocation of a WSGI application""" # Configuration parameters; can override per-subclass or per-instance wsgi_version = (1,0) wsgi_multithread = True wsgi_multiprocess = True wsgi_run_once = False origin_server = True # We are transmitting direct to client http_version = "1.0" # Version that should be used for response server_software = None # String name of server software, if any # os_environ is used to supply configuration from the OS environment: # by default it's a copy of 'os.environ' as of import time, but you can # override this in e.g. your __init__ method. os_environ= read_environ() # Collaborator classes wsgi_file_wrapper = FileWrapper # set to None to disable headers_class = Headers # must be a Headers-like class # Error handling (also per-subclass or per-instance) traceback_limit = None # Print entire traceback to self.get_stderr() error_status = "500 Internal Server Error" error_headers = [('Content-Type','text/plain')] error_body = b"A server error occurred. Please contact the administrator." # State variables (don't mess with these) status = result = None headers_sent = False headers = None bytes_sent = 0 def run(self, application): """Invoke the application""" # Note to self: don't move the close()! Asynchronous servers shouldn't # call close() from finish_response(), so if you close() anywhere but # the double-error branch here, you'll break asynchronous servers by # prematurely closing. Async servers must return from 'run()' without # closing if there might still be output to iterate over. try: self.setup_environ() self.result = application(self.environ, self.start_response) self.finish_response() except: try: self.handle_error() except: # If we get an error handling an error, just give up already! self.close() raise # ...and let the actual server figure it out. def setup_environ(self): """Set up the environment for one request""" env = self.environ = self.os_environ.copy() self.add_cgi_vars() env['wsgi.input'] = self.get_stdin() env['wsgi.errors'] = self.get_stderr() env['wsgi.version'] = self.wsgi_version env['wsgi.run_once'] = self.wsgi_run_once env['wsgi.url_scheme'] = self.get_scheme() env['wsgi.multithread'] = self.wsgi_multithread env['wsgi.multiprocess'] = self.wsgi_multiprocess if self.wsgi_file_wrapper is not None: env['wsgi.file_wrapper'] = self.wsgi_file_wrapper if self.origin_server and self.server_software: env.setdefault('SERVER_SOFTWARE',self.server_software) def finish_response(self): """Send any iterable data, then close self and the iterable Subclasses intended for use in asynchronous servers will want to redefine this method, such that it sets up callbacks in the event loop to iterate over the data, and to call 'self.close()' once the response is finished. """ try: if not self.result_is_file() or not self.sendfile(): for data in self.result: self.write(data) self.finish_content() finally: self.close() def get_scheme(self): """Return the URL scheme being used""" return guess_scheme(self.environ) def set_content_length(self): """Compute Content-Length or switch to chunked encoding if possible""" try: blocks = len(self.result) except (TypeError,AttributeError,NotImplementedError): pass else: if blocks==1: self.headers['Content-Length'] = str(self.bytes_sent) return # XXX Try for chunked encoding if origin server and client is 1.1 def cleanup_headers(self): """Make any necessary header changes or defaults Subclasses can extend this to add other defaults. """ if 'Content-Length' not in self.headers: self.set_content_length() def start_response(self, status, headers,exc_info=None): """'start_response()' callable as specified by PEP 3333""" if exc_info: try: if self.headers_sent: # Re-raise original exception if headers sent raise exc_info[0](exc_info[1]).with_traceback(exc_info[2]) finally: exc_info = None # avoid dangling circular ref elif self.headers is not None: raise AssertionError("Headers already set!") self.status = status self.headers = self.headers_class(headers) status = self._convert_string_type(status, "Status") assert len(status)>=4,"Status must be at least 4 characters" assert status[:3].isdigit(), "Status message must begin w/3-digit code" assert status[3]==" ", "Status message must have a space after code" if __debug__: for name, val in headers: name = self._convert_string_type(name, "Header name") val = self._convert_string_type(val, "Header value") assert not is_hop_by_hop(name),"Hop-by-hop headers not allowed" return self.write def _convert_string_type(self, value, title): """Convert/check value type.""" if type(value) is str: return value raise AssertionError( "{0} must be of type str (got {1})".format(title, repr(value)) ) def send_preamble(self): """Transmit version/status/date/server, via self._write()""" if self.origin_server: if self.client_is_modern(): self._write(('HTTP/%s %s\r\n' % (self.http_version,self.status)).encode('iso-8859-1')) if 'Date' not in self.headers: self._write( ('Date: %s\r\n' % format_date_time(time.time())).encode('iso-8859-1') ) if self.server_software and 'Server' not in self.headers: self._write(('Server: %s\r\n' % self.server_software).encode('iso-8859-1')) else: self._write(('Status: %s\r\n' % self.status).encode('iso-8859-1')) def write(self, data): """'write()' callable as specified by PEP 3333""" assert type(data) is bytes, \ "write() argument must be a bytes instance" if not self.status: raise AssertionError("write() before start_response()") elif not self.headers_sent: # Before the first output, send the stored headers self.bytes_sent = len(data) # make sure we know content-length self.send_headers() else: self.bytes_sent += len(data) # XXX check Content-Length and truncate if too many bytes written? self._write(data) self._flush() def sendfile(self): """Platform-specific file transmission Override this method in subclasses to support platform-specific file transmission. It is only called if the application's return iterable ('self.result') is an instance of 'self.wsgi_file_wrapper'. This method should return a true value if it was able to actually transmit the wrapped file-like object using a platform-specific approach. It should return a false value if normal iteration should be used instead. An exception can be raised to indicate that transmission was attempted, but failed. NOTE: this method should call 'self.send_headers()' if 'self.headers_sent' is false and it is going to attempt direct transmission of the file. """ return False # No platform-specific transmission by default def finish_content(self): """Ensure headers and content have both been sent""" if not self.headers_sent: # Only zero Content-Length if not set by the application (so # that HEAD requests can be satisfied properly, see #3839) self.headers.setdefault('Content-Length', "0") self.send_headers() else: pass # XXX check if content-length was too short? def close(self): """Close the iterable (if needed) and reset all instance vars Subclasses may want to also drop the client connection. """ try: if hasattr(self.result,'close'): self.result.close() finally: self.result = self.headers = self.status = self.environ = None self.bytes_sent = 0; self.headers_sent = False def send_headers(self): """Transmit headers to the client, via self._write()""" self.cleanup_headers() self.headers_sent = True if not self.origin_server or self.client_is_modern(): self.send_preamble() self._write(bytes(self.headers)) def result_is_file(self): """True if 'self.result' is an instance of 'self.wsgi_file_wrapper'""" wrapper = self.wsgi_file_wrapper return wrapper is not None and isinstance(self.result,wrapper) def client_is_modern(self): """True if client can accept status and headers""" return self.environ['SERVER_PROTOCOL'].upper() != 'HTTP/0.9' def log_exception(self,exc_info): """Log the 'exc_info' tuple in the server log Subclasses may override to retarget the output or change its format. """ try: from traceback import print_exception stderr = self.get_stderr() print_exception( exc_info[0], exc_info[1], exc_info[2], self.traceback_limit, stderr ) stderr.flush() finally: exc_info = None def handle_error(self): """Log current error, and send error output to client if possible""" self.log_exception(sys.exc_info()) if not self.headers_sent: self.result = self.error_output(self.environ, self.start_response) self.finish_response() # XXX else: attempt advanced recovery techniques for HTML or text? def error_output(self, environ, start_response): """WSGI mini-app to create error output By default, this just uses the 'error_status', 'error_headers', and 'error_body' attributes to generate an output page. It can be overridden in a subclass to dynamically generate diagnostics, choose an appropriate message for the user's preferred language, etc. Note, however, that it's not recommended from a security perspective to spit out diagnostics to any old user; ideally, you should have to do something special to enable diagnostic output, which is why we don't include any here! """ start_response(self.error_status,self.error_headers[:],sys.exc_info()) return [self.error_body] # Pure abstract methods; *must* be overridden in subclasses def _write(self,data): """Override in subclass to buffer data for send to client It's okay if this method actually transmits the data; BaseHandler just separates write and flush operations for greater efficiency when the underlying system actually has such a distinction. """ raise NotImplementedError def _flush(self): """Override in subclass to force sending of recent '_write()' calls It's okay if this method is a no-op (i.e., if '_write()' actually sends the data. """ raise NotImplementedError def get_stdin(self): """Override in subclass to return suitable 'wsgi.input'""" raise NotImplementedError def get_stderr(self): """Override in subclass to return suitable 'wsgi.errors'""" raise NotImplementedError def add_cgi_vars(self): """Override in subclass to insert CGI variables in 'self.environ'""" raise NotImplementedError class SimpleHandler(BaseHandler): """Handler that's just initialized with streams, environment, etc. This handler subclass is intended for synchronous HTTP/1.0 origin servers, and handles sending the entire response output, given the correct inputs. Usage:: handler = SimpleHandler( inp,out,err,env, multithread=False, multiprocess=True ) handler.run(app)""" def __init__(self,stdin,stdout,stderr,environ, multithread=True, multiprocess=False ): self.stdin = stdin self.stdout = stdout self.stderr = stderr self.base_env = environ self.wsgi_multithread = multithread self.wsgi_multiprocess = multiprocess def get_stdin(self): return self.stdin def get_stderr(self): return self.stderr def add_cgi_vars(self): self.environ.update(self.base_env) def _write(self,data): result = self.stdout.write(data) if result is None or result == len(data): return from warnings import warn warn("SimpleHandler.stdout.write() should not do partial writes", DeprecationWarning) while True: data = data[result:] if not data: break result = self.stdout.write(data) def _flush(self): self.stdout.flush() self._flush = self.stdout.flush class BaseCGIHandler(SimpleHandler): """CGI-like systems using input/output/error streams and environ mapping Usage:: handler = BaseCGIHandler(inp,out,err,env) handler.run(app) This handler class is useful for gateway protocols like ReadyExec and FastCGI, that have usable input/output/error streams and an environment mapping. It's also the base class for CGIHandler, which just uses sys.stdin, os.environ, and so on. The constructor also takes keyword arguments 'multithread' and 'multiprocess' (defaulting to 'True' and 'False' respectively) to control the configuration sent to the application. It sets 'origin_server' to False (to enable CGI-like output), and assumes that 'wsgi.run_once' is False. """ origin_server = False class CGIHandler(BaseCGIHandler): """CGI-based invocation via sys.stdin/stdout/stderr and os.environ Usage:: CGIHandler().run(app) The difference between this class and BaseCGIHandler is that it always uses 'wsgi.run_once' of 'True', 'wsgi.multithread' of 'False', and 'wsgi.multiprocess' of 'True'. It does not take any initialization parameters, but always uses 'sys.stdin', 'os.environ', and friends. If you need to override any of these parameters, use BaseCGIHandler instead. """ wsgi_run_once = True # Do not allow os.environ to leak between requests in Google App Engine # and other multi-run CGI use cases. This is not easily testable. # See http://bugs.python.org/issue7250 os_environ = {} def __init__(self): BaseCGIHandler.__init__( self, sys.stdin.buffer, sys.stdout.buffer, sys.stderr, read_environ(), multithread=False, multiprocess=True ) class IISCGIHandler(BaseCGIHandler): """CGI-based invocation with workaround for IIS path bug This handler should be used in preference to CGIHandler when deploying on Microsoft IIS without having set the config allowPathInfo option (IIS>=7) or metabase allowPathInfoForScriptMappings (IIS<7). """ wsgi_run_once = True os_environ = {} # By default, IIS gives a PATH_INFO that duplicates the SCRIPT_NAME at # the front, causing problems for WSGI applications that wish to implement # routing. This handler strips any such duplicated path. # IIS can be configured to pass the correct PATH_INFO, but this causes # another bug where PATH_TRANSLATED is wrong. Luckily this variable is # rarely used and is not guaranteed by WSGI. On IIS<7, though, the # setting can only be made on a vhost level, affecting all other script # mappings, many of which break when exposed to the PATH_TRANSLATED bug. # For this reason IIS<7 is almost never deployed with the fix. (Even IIS7 # rarely uses it because there is still no UI for it.) # There is no way for CGI code to tell whether the option was set, so a # separate handler class is provided. def __init__(self): environ= read_environ() path = environ.get('PATH_INFO', '') script = environ.get('SCRIPT_NAME', '') if (path+'/').startswith(script+'/'): environ['PATH_INFO'] = path[len(script):] BaseCGIHandler.__init__( self, sys.stdin.buffer, sys.stdout.buffer, sys.stderr, environ, multithread=False, multiprocess=True ) PKe[2em;;;; validate.pynu[# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php # Also licenced under the Apache License, 2.0: http://opensource.org/licenses/apache2.0.php # Licensed to PSF under a Contributor Agreement """ Middleware to check for obedience to the WSGI specification. Some of the things this checks: * Signature of the application and start_response (including that keyword arguments are not used). * Environment checks: - Environment is a dictionary (and not a subclass). - That all the required keys are in the environment: REQUEST_METHOD, SERVER_NAME, SERVER_PORT, wsgi.version, wsgi.input, wsgi.errors, wsgi.multithread, wsgi.multiprocess, wsgi.run_once - That HTTP_CONTENT_TYPE and HTTP_CONTENT_LENGTH are not in the environment (these headers should appear as CONTENT_LENGTH and CONTENT_TYPE). - Warns if QUERY_STRING is missing, as the cgi module acts unpredictably in that case. - That CGI-style variables (that don't contain a .) have (non-unicode) string values - That wsgi.version is a tuple - That wsgi.url_scheme is 'http' or 'https' (@@: is this too restrictive?) - Warns if the REQUEST_METHOD is not known (@@: probably too restrictive). - That SCRIPT_NAME and PATH_INFO are empty or start with / - That at least one of SCRIPT_NAME or PATH_INFO are set. - That CONTENT_LENGTH is a positive integer. - That SCRIPT_NAME is not '/' (it should be '', and PATH_INFO should be '/'). - That wsgi.input has the methods read, readline, readlines, and __iter__ - That wsgi.errors has the methods flush, write, writelines * The status is a string, contains a space, starts with an integer, and that integer is in range (> 100). * That the headers is a list (not a subclass, not another kind of sequence). * That the items of the headers are tuples of strings. * That there is no 'status' header (that is used in CGI, but not in WSGI). * That the headers don't contain newlines or colons, end in _ or -, or contain characters codes below 037. * That Content-Type is given if there is content (CGI often has a default content type, but WSGI does not). * That no Content-Type is given when there is no content (@@: is this too restrictive?) * That the exc_info argument to start_response is a tuple or None. * That all calls to the writer are with strings, and no other methods on the writer are accessed. * That wsgi.input is used properly: - .read() is called with zero or one argument - That it returns a string - That readline, readlines, and __iter__ return strings - That .close() is not called - No other methods are provided * That wsgi.errors is used properly: - .write() and .writelines() is called with a string - That .close() is not called, and no other methods are provided. * The response iterator: - That it is not a string (it should be a list of a single string; a string will work, but perform horribly). - That .__next__() returns a string - That the iterator is not iterated over until start_response has been called (that can signal either a server or application error). - That .close() is called (doesn't raise exception, only prints to sys.stderr, because we only know it isn't called when the object is garbage collected). """ __all__ = ['validator'] import re import sys import warnings header_re = re.compile(r'^[a-zA-Z][a-zA-Z0-9\-_]*$') bad_header_value_re = re.compile(r'[\000-\037]') class WSGIWarning(Warning): """ Raised in response to WSGI-spec-related warnings """ def assert_(cond, *args): if not cond: raise AssertionError(*args) def check_string_type(value, title): if type (value) is str: return value raise AssertionError( "{0} must be of type str (got {1})".format(title, repr(value))) def validator(application): """ When applied between a WSGI server and a WSGI application, this middleware will check for WSGI compliancy on a number of levels. This middleware does not modify the request or response in any way, but will raise an AssertionError if anything seems off (except for a failure to close the application iterator, which will be printed to stderr -- there's no way to raise an exception at that point). """ def lint_app(*args, **kw): assert_(len(args) == 2, "Two arguments required") assert_(not kw, "No keyword arguments allowed") environ, start_response = args check_environ(environ) # We use this to check if the application returns without # calling start_response: start_response_started = [] def start_response_wrapper(*args, **kw): assert_(len(args) == 2 or len(args) == 3, ( "Invalid number of arguments: %s" % (args,))) assert_(not kw, "No keyword arguments allowed") status = args[0] headers = args[1] if len(args) == 3: exc_info = args[2] else: exc_info = None check_status(status) check_headers(headers) check_content_type(status, headers) check_exc_info(exc_info) start_response_started.append(None) return WriteWrapper(start_response(*args)) environ['wsgi.input'] = InputWrapper(environ['wsgi.input']) environ['wsgi.errors'] = ErrorWrapper(environ['wsgi.errors']) iterator = application(environ, start_response_wrapper) assert_(iterator is not None and iterator != False, "The application must return an iterator, if only an empty list") check_iterator(iterator) return IteratorWrapper(iterator, start_response_started) return lint_app class InputWrapper: def __init__(self, wsgi_input): self.input = wsgi_input def read(self, *args): assert_(len(args) == 1) v = self.input.read(*args) assert_(type(v) is bytes) return v def readline(self, *args): assert_(len(args) <= 1) v = self.input.readline(*args) assert_(type(v) is bytes) return v def readlines(self, *args): assert_(len(args) <= 1) lines = self.input.readlines(*args) assert_(type(lines) is list) for line in lines: assert_(type(line) is bytes) return lines def __iter__(self): while 1: line = self.readline() if not line: return yield line def close(self): assert_(0, "input.close() must not be called") class ErrorWrapper: def __init__(self, wsgi_errors): self.errors = wsgi_errors def write(self, s): assert_(type(s) is str) self.errors.write(s) def flush(self): self.errors.flush() def writelines(self, seq): for line in seq: self.write(line) def close(self): assert_(0, "errors.close() must not be called") class WriteWrapper: def __init__(self, wsgi_writer): self.writer = wsgi_writer def __call__(self, s): assert_(type(s) is bytes) self.writer(s) class PartialIteratorWrapper: def __init__(self, wsgi_iterator): self.iterator = wsgi_iterator def __iter__(self): # We want to make sure __iter__ is called return IteratorWrapper(self.iterator, None) class IteratorWrapper: def __init__(self, wsgi_iterator, check_start_response): self.original_iterator = wsgi_iterator self.iterator = iter(wsgi_iterator) self.closed = False self.check_start_response = check_start_response def __iter__(self): return self def __next__(self): assert_(not self.closed, "Iterator read after closed") v = next(self.iterator) if type(v) is not bytes: assert_(False, "Iterator yielded non-bytestring (%r)" % (v,)) if self.check_start_response is not None: assert_(self.check_start_response, "The application returns and we started iterating over its body, but start_response has not yet been called") self.check_start_response = None return v def close(self): self.closed = True if hasattr(self.original_iterator, 'close'): self.original_iterator.close() def __del__(self): if not self.closed: sys.stderr.write( "Iterator garbage collected without being closed") assert_(self.closed, "Iterator garbage collected without being closed") def check_environ(environ): assert_(type(environ) is dict, "Environment is not of the right type: %r (environment: %r)" % (type(environ), environ)) for key in ['REQUEST_METHOD', 'SERVER_NAME', 'SERVER_PORT', 'wsgi.version', 'wsgi.input', 'wsgi.errors', 'wsgi.multithread', 'wsgi.multiprocess', 'wsgi.run_once']: assert_(key in environ, "Environment missing required key: %r" % (key,)) for key in ['HTTP_CONTENT_TYPE', 'HTTP_CONTENT_LENGTH']: assert_(key not in environ, "Environment should not have the key: %s " "(use %s instead)" % (key, key[5:])) if 'QUERY_STRING' not in environ: warnings.warn( 'QUERY_STRING is not in the WSGI environment; the cgi ' 'module will use sys.argv when this variable is missing, ' 'so application errors are more likely', WSGIWarning) for key in environ.keys(): if '.' in key: # Extension, we don't care about its type continue assert_(type(environ[key]) is str, "Environmental variable %s is not a string: %r (value: %r)" % (key, type(environ[key]), environ[key])) assert_(type(environ['wsgi.version']) is tuple, "wsgi.version should be a tuple (%r)" % (environ['wsgi.version'],)) assert_(environ['wsgi.url_scheme'] in ('http', 'https'), "wsgi.url_scheme unknown: %r" % environ['wsgi.url_scheme']) check_input(environ['wsgi.input']) check_errors(environ['wsgi.errors']) # @@: these need filling out: if environ['REQUEST_METHOD'] not in ( 'GET', 'HEAD', 'POST', 'OPTIONS', 'PATCH', 'PUT', 'DELETE', 'TRACE'): warnings.warn( "Unknown REQUEST_METHOD: %r" % environ['REQUEST_METHOD'], WSGIWarning) assert_(not environ.get('SCRIPT_NAME') or environ['SCRIPT_NAME'].startswith('/'), "SCRIPT_NAME doesn't start with /: %r" % environ['SCRIPT_NAME']) assert_(not environ.get('PATH_INFO') or environ['PATH_INFO'].startswith('/'), "PATH_INFO doesn't start with /: %r" % environ['PATH_INFO']) if environ.get('CONTENT_LENGTH'): assert_(int(environ['CONTENT_LENGTH']) >= 0, "Invalid CONTENT_LENGTH: %r" % environ['CONTENT_LENGTH']) if not environ.get('SCRIPT_NAME'): assert_('PATH_INFO' in environ, "One of SCRIPT_NAME or PATH_INFO are required (PATH_INFO " "should at least be '/' if SCRIPT_NAME is empty)") assert_(environ.get('SCRIPT_NAME') != '/', "SCRIPT_NAME cannot be '/'; it should instead be '', and " "PATH_INFO should be '/'") def check_input(wsgi_input): for attr in ['read', 'readline', 'readlines', '__iter__']: assert_(hasattr(wsgi_input, attr), "wsgi.input (%r) doesn't have the attribute %s" % (wsgi_input, attr)) def check_errors(wsgi_errors): for attr in ['flush', 'write', 'writelines']: assert_(hasattr(wsgi_errors, attr), "wsgi.errors (%r) doesn't have the attribute %s" % (wsgi_errors, attr)) def check_status(status): status = check_string_type(status, "Status") # Implicitly check that we can turn it into an integer: status_code = status.split(None, 1)[0] assert_(len(status_code) == 3, "Status codes must be three characters: %r" % status_code) status_int = int(status_code) assert_(status_int >= 100, "Status code is invalid: %r" % status_int) if len(status) < 4 or status[3] != ' ': warnings.warn( "The status string (%r) should be a three-digit integer " "followed by a single space and a status explanation" % status, WSGIWarning) def check_headers(headers): assert_(type(headers) is list, "Headers (%r) must be of type list: %r" % (headers, type(headers))) header_names = {} for item in headers: assert_(type(item) is tuple, "Individual headers (%r) must be of type tuple: %r" % (item, type(item))) assert_(len(item) == 2) name, value = item name = check_string_type(name, "Header name") value = check_string_type(value, "Header value") assert_(name.lower() != 'status', "The Status header cannot be used; it conflicts with CGI " "script, and HTTP status is not given through headers " "(value: %r)." % value) header_names[name.lower()] = None assert_('\n' not in name and ':' not in name, "Header names may not contain ':' or '\\n': %r" % name) assert_(header_re.search(name), "Bad header name: %r" % name) assert_(not name.endswith('-') and not name.endswith('_'), "Names may not end in '-' or '_': %r" % name) if bad_header_value_re.search(value): assert_(0, "Bad header value: %r (bad char: %r)" % (value, bad_header_value_re.search(value).group(0))) def check_content_type(status, headers): status = check_string_type(status, "Status") code = int(status.split(None, 1)[0]) # @@: need one more person to verify this interpretation of RFC 2616 # http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html NO_MESSAGE_BODY = (204, 304) for name, value in headers: name = check_string_type(name, "Header name") if name.lower() == 'content-type': if code not in NO_MESSAGE_BODY: return assert_(0, ("Content-Type header found in a %s response, " "which must not return content.") % code) if code not in NO_MESSAGE_BODY: assert_(0, "No Content-Type header found in headers (%s)" % headers) def check_exc_info(exc_info): assert_(exc_info is None or type(exc_info) is tuple, "exc_info (%r) is not a tuple: %r" % (exc_info, type(exc_info))) # More exc_info checks? def check_iterator(iterator): # Technically a bytestring is legal, which is why it's a really bad # idea, because it may cause the response to be returned # character-by-character assert_(not isinstance(iterator, (str, bytes)), "You should not return a string as your application iterator, " "instead return a single-item list containing a bytestring.") PKe[/qGYY(__pycache__/headers.cpython-36.opt-2.pycnu[3 \n@s.ddlZejdZdddZGdddZdS) Nz[ \(\)<>@,;:\\"/\[\]\?=]cCsX|dk rPt|dkrP|s"tj|rB|jddjdd}d||fSd||fSn|SdS)Nr\z\\"z\"z%s="%s"z%s=%s)len tspecialssearchreplace)ZparamvalueZquoter '/usr/lib64/python3.6/wsgiref/headers.py _formatparam s  r c@seZdZd$ddZddZddZdd Zd d Zd d ZddZ ddZ d%ddZ ddZ ddZ ddZddZddZddZd d!Zd"d#ZdS)&HeadersNcCs.|dk r |ng}t|tk r$td||_dS)Nz+Headers must be a list of name/value tuples)typelist TypeError_headers)selfZheadersr r r __init__s  zHeaders.__init__cCs&t|tkr|Stdjt|dS)Nz1Header names/values must be of type str (got {0}))rstrAssertionErrorformatrepr)rr r r r _convert_string_type)s zHeaders._convert_string_typecCs t|jS)N)rr)rr r r __len__0szHeaders.__len__cCs&||=|jj|j||j|fdS)N)rappendr)rnamevalr r r __setitem__4szHeaders.__setitem__cs0|jjfdd|jD|jdd<dS)Ncs g|]}|djkr|qS)r)lower).0kv)rr r @sz'Headers.__delitem__..)rrr)rrr )rr __delitem__:szHeaders.__delitem__cCs |j|S)N)get)rrr r r __getitem__Bs zHeaders.__getitem__cCs|j|dk S)N)r#)rrr r r __contains__MszHeaders.__contains__cs"|jjfdd|jDS)Ncs$g|]}|djkr|dqS)rr)r)rr )rr r r![sz#Headers.get_all..)rrr)rrr )rr get_allRszHeaders.get_allcCs6|j|j}x"|jD]\}}|j|kr|SqW|S)N)rrr)rrdefaultkvr r r r#^s  z Headers.getcCsdd|jDS)NcSsg|] \}}|qSr r )rr(r)r r r r!osz Headers.keys..)r)rr r r keysgsz Headers.keyscCsdd|jDS)NcSsg|] \}}|qSr r )rr(r)r r r r!ysz"Headers.values..)r)rr r r valuesqszHeaders.valuescCs|jddS)N)r)rr r r items{sz Headers.itemscCsd|jj|jfS)Nz%s(%r)) __class____name__r)rr r r __repr__szHeaders.__repr__cCsdjdd|jDddgS)Nz cSsg|] }d|qS)z%s: %sr )rr r r r r!sz#Headers.__str__..)joinr)rr r r __str__szHeaders.__str__cCst|jdS)Nz iso-8859-1)rencode)rr r r __bytes__szHeaders.__bytes__cCs:|j|}|dkr2|jj|j||j|f|S|SdS)N)r#rrr)rrr resultr r r setdefaults  zHeaders.setdefaultcKsg}|dk r |j|}|j|x\|jD]P\}}|j|}|dkrX|j|jddq*|j|}|jt|jdd|q*W|jj|j|dj|fdS)N_-z; )rrr,rr rr1)r_nameZ_valueZ_paramspartsr(r)r r r add_headers    zHeaders.add_header)N)N)r. __module__ __qualname__rrrrr"r$r%r&r#r*r+r,r/r2r4r6r;r r r r r s"       r )Nr)recompilerr r r r r r  s  PKe[ݮc\=\=)__pycache__/handlers.cpython-36.opt-1.pycnu[3 \ R @sdZddlmZmZmZddlmZddlZddlZddl Z dddd d d gZ d d dddddgZ dddddddddddddg Z dd Z d!d"d#d$d%d&d'd(d)d*h jZd+d,Zd-d ZGd.ddZGd/ddeZGd0ddeZGd1d d eZGd2d d eZdS)3z/Base classes for server/gateway implementations) FileWrapper guess_scheme is_hop_by_hop)HeadersN BaseHandler SimpleHandlerBaseCGIHandler CGIHandler IISCGIHandler read_environZMonZTueZWedZThuZFriZSatZSunZJanZFebZMarZAprZMayZJunZJulZAugZSepZOctZNovZDecc Cs:tj|\ }}}}}}}}} dt||t|||||fS)Nz#%s, %02d %3s %4d %02d:%02d:%02d GMT)timeZgmtime _weekdayname _monthname) Z timestampZyearZmonthZdayZhhZmmZssZwdyzr(/usr/lib64/python3.6/wsgiref/handlers.pyformat_date_timesr SCRIPT_NAME PATH_INFOZ QUERY_STRINGZREQUEST_METHODZ AUTH_TYPEZ CONTENT_TYPEZCONTENT_LENGTHZHTTPSZ REMOTE_USERZ REMOTE_IDENTcCs6t|p4|jdp4|jdp4|jdo4t|ddS)NZHTTP_ZSSL_Z REDIRECT_ ) _is_request startswith_needs_transcode)krrrrsrc Cstj}d}ydjd|Wntk r4d}YnXi}xtjjD]\}}t|rtjdkrtjj ddj }|j dr|jdj d}q|j d rq|j d rd |kr|jdj d}q|j|dj d}n|j||j d}|||<qFW|S) z'Read environment, fixing HTTP variablessurrogateescapezutf-8replaceZwin32SERVER_SOFTWAREzmicrosoft-iis/z iso-8859-1zapache/z simplehttp/zpython/3) sysgetfilesystemencodingencode LookupErrorosenvironitemsrplatformgetlowerrdecode)encescr%rvZsoftwarerrrr "s,      c@s"eZdZdZdddZ ddZ!ddZ"ddZ#d d!Z$d"d#Z%d$d%Z&d&d'Z'd(d)Z(d*d+Z)d,d-Z*d.d/Z+d0d1Z,d2d3Z-d4d5Z.d6d7Z/d8d9Z0d:d;Z1dS)?rz+Manage the invocation of a WSGI applicationrrTFz1.0Nz500 Internal Server Error Content-Type text/plains;A server error occurred. Please contact the administrator.cCsZy$|j||j|j|_|jWn0y |jWn|jYnXYnXdS)zInvoke the applicationN) setup_environr%start_responseresultfinish_response handle_errorclose)selfZ applicationrrrruns  zBaseHandler.runcCs|jj}|_|j|j|d<|j|d<|j|d<|j|d<|j|d<|j |d<|j |d<|j dk rx|j |d <|j r|j r|jd |j dS) z&Set up the environment for one requestz wsgi.inputz wsgi.errorsz wsgi.versionz wsgi.run_oncezwsgi.url_schemezwsgi.multithreadzwsgi.multiprocessNzwsgi.file_wrapperr) os_environcopyr% add_cgi_vars get_stdin get_stderr wsgi_version wsgi_run_once get_schemewsgi_multithreadwsgi_multiprocesswsgi_file_wrapper origin_serverserver_software setdefault)r6envrrrr0s          zBaseHandler.setup_environc CsJz:|j s|j r8x|jD]}|j|qW|jWd|jXdS)a>Send any iterable data, then close self and the iterable Subclasses intended for use in asynchronous servers will want to redefine this method, such that it sets up callbacks in the event loop to iterate over the data, and to call 'self.close()' once the response is finished. N)result_is_filesendfiler2writefinish_contentr5)r6datarrrr3s   zBaseHandler.finish_responsecCs t|jS)z Return the URL scheme being used)rr%)r6rrrr?szBaseHandler.get_schemec CsJyt|j}Wntttfk r(YnX|dkrFt|j|jd<dSdS)z@Compute Content-Length or switch to chunked encoding if possiblerzContent-LengthN)lenr2 TypeErrorAttributeErrorNotImplementedErrorstr bytes_sentheaders)r6Zblocksrrrset_content_lengthszBaseHandler.set_content_lengthcCsd|jkr|jdS)zqMake any necessary header changes or defaults Subclasses can extend this to add other defaults. zContent-LengthN)rRrS)r6rrrcleanup_headerss zBaseHandler.cleanup_headersc Csh|r2z$|jr&|d|dj|dWdd}Xn|jdk rDtd||_|j||_|j|d}|jS)z4'start_response()' callable as specified by PEP 3333rrNzHeaders already set!ZStatus) headers_sentwith_tracebackrRAssertionErrorstatus headers_class_convert_string_typerI)r6rYrRexc_inforrrr1s   zBaseHandler.start_responsecCs(t|tkr|Stdj|t|dS)zConvert/check value type.z!{0} must be of type str (got {1})N)typerPrXformatrepr)r6valuetitlerrrr[s z BaseHandler._convert_string_typecCs|jrx|jr|jd|j|jfjdd|jkrP|jdttjjd|j rd|jkr|jd|j jdn|jd|jjddS) z6Transmit version/status/date/server, via self._write()z HTTP/%s %s z iso-8859-1ZDatez Date: %s ZServerz Server: %s z Status: %s N) rCclient_is_modern_write http_versionrYr"rRrr rD)r6rrr send_preambles zBaseHandler.send_preamblecCsR|jstdn,|js*t||_|jn|jt|7_|j||jdS)z+'write()' callable as specified by PEP 3333zwrite() before start_response()N)rYrXrVrLrQ send_headersrc_flush)r6rKrrrrIs    zBaseHandler.writecCsdS)aPlatform-specific file transmission Override this method in subclasses to support platform-specific file transmission. It is only called if the application's return iterable ('self.result') is an instance of 'self.wsgi_file_wrapper'. This method should return a true value if it was able to actually transmit the wrapped file-like object using a platform-specific approach. It should return a false value if normal iteration should be used instead. An exception can be raised to indicate that transmission was attempted, but failed. NOTE: this method should call 'self.send_headers()' if 'self.headers_sent' is false and it is going to attempt direct transmission of the file. Fr)r6rrrrHszBaseHandler.sendfilecCs"|js|jjdd|jndS)z.Ensure headers and content have both been sentzContent-Length0N)rVrRrErf)r6rrrrJ0s zBaseHandler.finish_contentc CsFzt|jdr|jjWdd|_|_|_|_d|_d|_XdS)zClose the iterable (if needed) and reset all instance vars Subclasses may want to also drop the client connection. r5NrF)hasattrr2r5rRrYr%rQrV)r6rrrr5:s  zBaseHandler.closecCs:|jd|_|j s|jr6|j|jt|jdS)z1Transmit headers to the client, via self._write()TN)rTrVrCrbrercbytesrR)r6rrrrfGs zBaseHandler.send_headerscCs|j}|dk ot|j|S)z@True if 'self.result' is an instance of 'self.wsgi_file_wrapper'N)rB isinstancer2)r6wrapperrrrrGPszBaseHandler.result_is_filecCs|jdjdkS)z,True if client can accept status and headersZSERVER_PROTOCOLzHTTP/0.9)r%upper)r6rrrrbVszBaseHandler.client_is_modernc CsJz>ddlm}|j}||d|d|d|j||jWdd}XdS)zLog the 'exc_info' tuple in the server log Subclasses may override to retarget the output or change its format. r)print_exceptionrrUN) tracebackrnr<traceback_limitflush)r6r\rnstderrrrr log_exception[s   zBaseHandler.log_exceptioncCs2|jtj|js.|j|j|j|_|jdS)z>Log current error, and send error output to client if possibleN) rsr r\rV error_outputr%r1r2r3)r6rrrr4kszBaseHandler.handle_errorcCs$||j|jddtj|jgS)aZWSGI mini-app to create error output By default, this just uses the 'error_status', 'error_headers', and 'error_body' attributes to generate an output page. It can be overridden in a subclass to dynamically generate diagnostics, choose an appropriate message for the user's preferred language, etc. Note, however, that it's not recommended from a security perspective to spit out diagnostics to any old user; ideally, you should have to do something special to enable diagnostic output, which is why we don't include any here! N) error_status error_headersr r\ error_body)r6r%r1rrrrtss zBaseHandler.error_outputcCstdS)aOverride in subclass to buffer data for send to client It's okay if this method actually transmits the data; BaseHandler just separates write and flush operations for greater efficiency when the underlying system actually has such a distinction. N)rO)r6rKrrrrcszBaseHandler._writecCstdS)zOverride in subclass to force sending of recent '_write()' calls It's okay if this method is a no-op (i.e., if '_write()' actually sends the data. N)rO)r6rrrrgszBaseHandler._flushcCstdS)z4Override in subclass to return suitable 'wsgi.input'N)rO)r6rrrr;szBaseHandler.get_stdincCstdS)z5Override in subclass to return suitable 'wsgi.errors'N)rO)r6rrrr<szBaseHandler.get_stderrcCstdS)z>Override in subclass to insert CGI variables in 'self.environ'N)rO)r6rrrr:szBaseHandler.add_cgi_vars)rr)r.r/)N)2__name__ __module__ __qualname____doc__r=r@rAr>rCrdrDr r8rrBrrZrprurvrwrYr2rVrRrQr7r0r3r?rSrTr1r[rerIrHrJr5rfrGrbrsr4rtrcrgr;r<r:rrrrr^sV      c@sBeZdZdZdddZddZdd Zd d Zd d ZddZ dS)raqHandler that's just initialized with streams, environment, etc. This handler subclass is intended for synchronous HTTP/1.0 origin servers, and handles sending the entire response output, given the correct inputs. Usage:: handler = SimpleHandler( inp,out,err,env, multithread=False, multiprocess=True ) handler.run(app)TFcCs(||_||_||_||_||_||_dS)N)stdinstdoutrrbase_envr@rA)r6r|r}rrr% multithread multiprocessrrr__init__s zSimpleHandler.__init__cCs|jS)N)r|)r6rrrr;szSimpleHandler.get_stdincCs|jS)N)rr)r6rrrr<szSimpleHandler.get_stderrcCs|jj|jdS)N)r%updater~)r6rrrr:szSimpleHandler.add_cgi_varscCsb|jj|}|dks |t|kr$dSddlm}|dtx"||d}|sNP|jj|}qr8rrrrrr sc@s eZdZdZdZiZddZdS)r aCGI-based invocation with workaround for IIS path bug This handler should be used in preference to CGIHandler when deploying on Microsoft IIS without having set the config allowPathInfo option (IIS>=7) or metabase allowPathInfoForScriptMappings (IIS<7). Tc Csjt}|jdd}|jdd}|dj|drD|t|d|d<tj|tjjtj jtj |ddddS)Nrrr/FT)rr) r r(rrLr rr r|rr}rr)r6r%pathZscriptrrrr$s  zIISCGIHandler.__init__N)rxryrzr{r>r8rrrrrr s)r{utilrrrrRrr r$r __all__rrr __contains__rrr rrr r r rrrrs*   <H2PKe[Ry#__pycache__/__init__.cpython-36.pycnu[3 \K@sdZdS)aDwsgiref -- a WSGI (PEP 3333) Reference Library Current Contents: * util -- Miscellaneous useful functions and wrappers * headers -- Manage response headers * handlers -- base classes for server/gateway implementations * simple_server -- a simple BaseHTTPServer that supports WSGI * validate -- validation wrapper that sits between an app and a server to detect errors in either To-Do: * cgi_gateway -- Run WSGI apps under CGI (pending a deployment standard) * cgi_wrapper -- Run CGI apps under WSGI * router -- a simple middleware component that handles URL traversal N)__doc__rr(/usr/lib64/python3.6/wsgiref/__init__.pysPKe[Fy[;;"__pycache__/headers.cpython-36.pycnu[3 \n@s2dZddlZejdZd ddZGdddZdS) zManage HTTP Response Headers Much of this module is red-handedly pilfered from email.message in the stdlib, so portions are Copyright (C) 2001,2002 Python Software Foundation, and were written by Barry Warsaw. Nz[ \(\)<>@,;:\\"/\[\]\?=]cCsX|dk rPt|dkrP|s"tj|rB|jddjdd}d||fSd||fSn|SdS) z~Convenience function to format and return a key=value pair. This will quote the value if needed or if quote is true. Nr\z\\"z\"z%s="%s"z%s=%s)len tspecialssearchreplace)ZparamvalueZquoter '/usr/lib64/python3.6/wsgiref/headers.py _formatparam s  r c@seZdZdZd%ddZddZddZd d Zd d Zd dZ ddZ ddZ d&ddZ ddZ ddZddZddZddZdd Zd!d"Zd#d$ZdS)'Headersz,Manage a collection of HTTP response headersNcCsT|dk r |ng}t|tk r$td||_x$|D]\}}|j||j|q0WdS)Nz+Headers must be a list of name/value tuples)typelist TypeError_headers_convert_string_type)selfZheaderskvr r r __init__s  zHeaders.__init__cCs&t|tkr|Stdjt|dS)zConvert/check value type.z1Header names/values must be of type str (got {0})N)rstrAssertionErrorformatrepr)rr r r r r)s zHeaders._convert_string_typecCs t|jS)z9Return the total number of headers, including duplicates.)rr)rr r r __len__0szHeaders.__len__cCs&||=|jj|j||j|fdS)zSet the value of a header.N)rappendr)rnamevalr r r __setitem__4szHeaders.__setitem__cs0|jjfdd|jD|jdd<dS)zyDelete all occurrences of a header, if present. Does *not* raise an exception if the header is missing. cs g|]}|djkr|qS)r)lower).0kv)rr r @sz'Headers.__delitem__..N)rr r)rrr )rr __delitem__:szHeaders.__delitem__cCs |j|S)aHGet the first header value for 'name' Return None if the header is missing instead of raising an exception. Note that if the header appeared multiple times, the first exactly which occurrence gets returned is undefined. Use getall() to get all the values matching a header field name. )get)rrr r r __getitem__Bs zHeaders.__getitem__cCs|j|dk S)z/Return true if the message contains the header.N)r%)rrr r r __contains__MszHeaders.__contains__cs"|jjfdd|jDS)aqReturn a list of all the values for the named field. These will be sorted in the order they appeared in the original header list or were added to this instance, and may contain duplicates. Any fields deleted and re-inserted are always appended to the header list. If no fields exist with the given name, returns an empty list. cs$g|]}|djkr|dqS)rr)r )r!r")rr r r#[sz#Headers.get_all..)rr r)rrr )rr get_allRszHeaders.get_allcCs6|j|j}x"|jD]\}}|j|kr|SqW|S)z:Get the first header value for 'name', or return 'default')rr r)rrdefaultrrr r r r%^s  z Headers.getcCsdd|jDS)a*Return a list of all the header field names. These will be sorted in the order they appeared in the original header list, or were added to this instance, and may contain duplicates. Any fields deleted and re-inserted are always appended to the header list. cSsg|] \}}|qSr r )r!rrr r r r#osz Headers.keys..)r)rr r r keysgsz Headers.keyscCsdd|jDS)a!Return a list of all header values. These will be sorted in the order they appeared in the original header list, or were added to this instance, and may contain duplicates. Any fields deleted and re-inserted are always appended to the header list. cSsg|] \}}|qSr r )r!rrr r r r#ysz"Headers.values..)r)rr r r valuesqszHeaders.valuescCs|jddS)aGet all the header fields and values. These will be sorted in the order they were in the original header list, or were added to this instance, and may contain duplicates. Any fields deleted and re-inserted are always appended to the header list. N)r)rr r r items{sz Headers.itemscCsd|jj|jfS)Nz%s(%r)) __class____name__r)rr r r __repr__szHeaders.__repr__cCsdjdd|jDddgS)zkstr() returns the formatted headers, complete with end line, suitable for direct HTTP transmission.z cSsg|] }d|qS)z%s: %sr )r!r"r r r r#sz#Headers.__str__..)joinr)rr r r __str__szHeaders.__str__cCst|jdS)Nz iso-8859-1)rencode)rr r r __bytes__szHeaders.__bytes__cCs:|j|}|dkr2|jj|j||j|f|S|SdS)zReturn first matching header value for 'name', or 'value' If there is no header named 'name', add a new header with name 'name' and value 'value'.N)r%rrr)rrr resultr r r setdefaults  zHeaders.setdefaultcKsg}|dk r |j|}|j|x\|jD]P\}}|j|}|dkrX|j|jddq*|j|}|jt|jdd|q*W|jj|j|dj|fdS)afExtended header setting. _name is the header field to add. keyword arguments can be used to set additional parameters for the header field, with underscores converted to dashes. Normally the parameter will be added as key="value" unless value is None, in which case only the key will be added. Example: h.add_header('content-disposition', 'attachment', filename='bud.gif') Note that unlike the corresponding 'email.message' method, this does *not* handle '(charset, language, value)' tuples: all values must be strings or None. N_-z; )rrr,rr rr1)r_nameZ_valueZ_paramspartsrrr r r add_headers    zHeaders.add_header)N)N)r. __module__ __qualname____doc__rrrrr$r&r'r(r%r*r+r,r/r2r4r6r;r r r r r s$       r )Nr)r>recompilerr r r r r r s  PKe[Ry)__pycache__/__init__.cpython-36.opt-1.pycnu[3 \K@sdZdS)aDwsgiref -- a WSGI (PEP 3333) Reference Library Current Contents: * util -- Miscellaneous useful functions and wrappers * headers -- Manage response headers * handlers -- base classes for server/gateway implementations * simple_server -- a simple BaseHTTPServer that supports WSGI * validate -- validation wrapper that sits between an app and a server to detect errors in either To-Do: * cgi_gateway -- Run WSGI apps under CGI (pending a deployment standard) * cgi_wrapper -- Run CGI apps under WSGI * router -- a simple middleware component that handles URL traversal N)__doc__rr(/usr/lib64/python3.6/wsgiref/__init__.pysPKe[0JJ__pycache__/util.cpython-36.pycnu[3 \ @sxdZddlZddddddgZGd ddZd dZd dZdd dZddZddZdddddddddj Z ddZ dS)z$Miscellaneous WSGI-related UtilitiesN FileWrapper guess_schemeapplication_uri request_urishift_path_infosetup_testing_defaultsc@s2eZdZdZd ddZddZddZd d Zd S) rz1Wrapper to convert file-like objects to iterables cCs"||_||_t|dr|j|_dS)Nclose)filelikeblksizehasattrr )selfr r r$/usr/lib64/python3.6/wsgiref/util.py__init__s zFileWrapper.__init__cCs|jj|j}|r|StdS)N)r readr IndexError)r keydatarrr __getitem__szFileWrapper.__getitem__cCs|S)Nr)r rrr__iter__szFileWrapper.__iter__cCs|jj|j}|r|StdS)N)r rr StopIteration)r rrrr__next__szFileWrapper.__next__N)r)__name__ __module__ __qualname____doc__rrrrrrrrr s  cCs|jddkrdSdSdS) zMReturn a guess for whether 'wsgi.url_scheme' should be 'http' or 'https' ZHTTPSyeson1httpshttpN)rrr)get)environrrrr#scCs|dd}ddlm}|jdr0||d7}nR||d7}|ddkrf|dd kr|d |d7}n|dd kr|d |d7}|||jd pd dd7}|S)z@Return the application's base URI (no PATH_INFO or QUERY_STRING)zwsgi.url_schemez://r)quote HTTP_HOST SERVER_NAMEr SERVER_PORT443:80 SCRIPT_NAME/latin1)encoding) urllib.parser$r")r#urlr$rrrr+s       TcCspt|}ddlm}||jddddd}|jdsF||d d 7}n||7}|rl|jd rl|d |d 7}|S) zBReturn the full request URI, optionally including the query stringr)r$ PATH_INFOz/;=,r-)Zsafer.r+NZ QUERY_STRING?)rr/r$r")r#Z include_queryr0r$ path_inforrrr?s  cCs|jdd}|sdS|jd}dd|dd D|dd <|d}|d=|jdd}tj|d|}|jdr~|dd }| r|jd r|d7}||d<dj||d<|d krd}|S) aZShift a name from PATH_INFO to SCRIPT_NAME, returning it If there are no remaining path segments in PATH_INFO, return None. Note: 'environ' is modified in-place; use a copy if you need to keep the original PATH_INFO or SCRIPT_NAME. Note: when PATH_INFO is just a '/', this returns '' and appends a trailing '/' to SCRIPT_NAME, even though empty path segments are normally ignored, and SCRIPT_NAME doesn't normally end in a '/'. This is intentional behavior, to ensure that an application can tell the difference between '/x' and '/x/' when traversing to objects. r1r2Nr,cSsg|]}|r|dkr|qS).r).0prrr ^sz#shift_path_info..r3r+r6r:r:)r"split posixpathnormpathendswithjoin)r#r5 path_partsnameZ script_namerrrrLs$     cCs|jdd|jdd|jd|d|jddd|kr\d |kr\|jdd |jd d |jd d|jdd|jdd|jddddlm}m}|jd||jd||jdt||ddkr|jddn|ddkr|jdddS)a:Update 'environ' with trivial defaults for testing purposes This adds various parameters required for WSGI, including HTTP_HOST, SERVER_NAME, SERVER_PORT, REQUEST_METHOD, SCRIPT_NAME, PATH_INFO, and all of the wsgi.* variables. It only supplies default values, and does not replace any existing settings for these variables. This routine is intended to make it easier for unit tests of WSGI servers and applications to set up dummy environments. It should *not* be used by actual WSGI servers or applications, since the data is fake! r&z 127.0.0.1ZSERVER_PROTOCOLzHTTP/1.0r%ZREQUEST_METHODZGETr+r1r2r,z wsgi.versionr3rz wsgi.run_oncezwsgi.multithreadzwsgi.multiprocess)StringIOBytesIOz wsgi.inputz wsgi.errorszwsgi.url_schemer!r'r*r r(N)r3r) setdefaultiorBrCr)r#rBrCrrrrus&           r3)Z connectionz keep-alivezproxy-authenticatezproxy-authorizationZteZtrailersztransfer-encodingZupgradecCs t|jS)z?Return true if 'header_name' is an HTTP/1.1 "Hop-by-Hop" header)_hoppishlower)Z header_namerrr is_hop_by_hopsrH)T) rr<__all__rrrrrr __contains__rFrHrrrrs )) PKe[RuBB.__pycache__/simple_server.cpython-36.opt-2.pycnu[3 \ @sddlmZmZddlZddlZddlmZddlm Z dZ dddd gZ d e Z e d ej jdZe d eZGd ddeZGdddeZGdddeZddZeefdd ZedkreddeBZejjZededdeddddlZejdejWdQRXdS))BaseHTTPRequestHandler HTTPServerN) SimpleHandler)python_implementationz0.2 WSGIServerWSGIRequestHandlerdemo_app make_serverz WSGIServer// c@seZdZeZddZdS) ServerHandlerc Cs4z"|jj|jjddd|jWdtj|XdS)Nr r)request_handlerZ log_requestZstatussplitZ bytes_sentrclose)selfr-/usr/lib64/python3.6/wsgiref/simple_server.pyr szServerHandler.closeN)__name__ __module__ __qualname__software_versionZserver_softwarerrrrrr sr c@s0eZdZdZddZddZddZdd ZdS) rNcCstj||jdS)N)r server_bind setup_environ)rrrrr0s zWSGIServer.server_bindcCsFi}|_|j|d<d|d<t|j|d<d|d<d|d<d|d<dS) NZ SERVER_NAMEzCGI/1.1ZGATEWAY_INTERFACEZ SERVER_PORT REMOTE_HOSTCONTENT_LENGTHZ SCRIPT_NAME) base_environZ server_namestrZ server_port)renvrrrr5s  zWSGIServer.setup_environcCs|jS)N) application)rrrrget_app?szWSGIServer.get_appcCs ||_dS)N)r )rr rrrset_appBszWSGIServer.set_app)rrrr rrr!r"rrrrr*s  c@s,eZdZdeZddZddZddZdS) rz WSGIServer/cCsT|jjj}|j|d<|j|d<|j|d<d|jkrH|jjdd\}}n |jd}}tj j |d|d<||d <|j }||j d kr||d <|j d |d <|j jd dkr|j j|d<n|j d |d<|j jd}|r||d<xn|j jD]`\}}|jddj}|j}||krqd||kr@|d|d|7<q||d|<qW|S)NZSERVER_PROTOCOLZSERVER_SOFTWAREZREQUEST_METHOD?r rz iso-8859-1Z PATH_INFOZ QUERY_STRINGrrZ REMOTE_ADDRz content-typeZ CONTENT_TYPEzcontent-lengthr-_ZHTTP_,)serverrcopyrequest_versionserver_versioncommandpathrurllibparseZunquoteZaddress_stringZclient_addressZheadersgetZget_content_typeitemsreplaceupperstrip)rrr,ZqueryhostZlengthkvrrr get_environKs8        zWSGIRequestHandler.get_environcCstjS)N)sysstderr)rrrr get_stderrpszWSGIRequestHandler.get_stderrcCs||jjd|_t|jdkr__all__r*versionr sys_versionrr rrrr rZhttpdZsocketZ getsocknameZsarEZ webbrowseropenZhandle_requestrrrr s*    B    PKe[,YӪ++)__pycache__/validate.cpython-36.opt-2.pycnu[3 \;;@sdgZddlZddlZddlZejdZejdZGdddeZddZ d d Z d dZ Gd d d Z GdddZ GdddZGdddZGdddZddZddZddZddZddZd d!Zd"d#Zd$d%ZdS)& validatorNz^[a-zA-Z][a-zA-Z0-9\-_]*$z [\000-\037]c@s eZdZdS) WSGIWarningN)__name__ __module__ __qualname__rr(/usr/lib64/python3.6/wsgiref/validate.pyrysrcGs|s t|dS)N)AssertionError)Zcondargsrrrassert_~sr cCs(t|tkr|Stdj|t|dS)Nz!{0} must be of type str (got {1}))typestrr formatrepr)valuetitlerrrcheck_string_types rcsfdd}|S)Ncstt|dkdt| d|\}t|gfdd}t|d|d<t|d|d<||}t|dk oz|dkd t|t|S) NzTwo arguments requiredzNo keyword arguments allowedcstt|dkpt|dkd|ft| d|d}|d}t|dkrV|d}nd}t|t|t||t|jdt|S)NrzInvalid number of arguments: %szNo keyword arguments allowedr)r len check_status check_headerscheck_content_typecheck_exc_infoappend WriteWrapper)r kwstatusheadersexc_info)start_responsestart_response_startedrrstart_response_wrappers      z;validator..lint_app..start_response_wrapperz wsgi.inputz wsgi.errorsFz>The application must return an iterator, if only an empty list)r r check_environ InputWrapper ErrorWrappercheck_iteratorIteratorWrapper)r renvironr#iterator) application)r!r"rlint_apps  zvalidator..lint_appr)r+r,r)r+rrs )c@s<eZdZddZddZddZddZd d Zd d Zd S)r%cCs ||_dS)N)input)self wsgi_inputrrr__init__szInputWrapper.__init__cGs0tt|dk|jj|}tt|tk|S)Nr)r rr-readr bytes)r.r vrrrr1s zInputWrapper.readcGs0tt|dk|jj|}tt|tk|S)Nr)r rr-readliner r2)r.r r3rrrr4s zInputWrapper.readlinecGsNtt|dk|jj|}tt|tkx|D]}tt|tkq2W|S)Nr)r rr- readlinesr listr2)r.r lineslinerrrr5s   zInputWrapper.readlinesccs x|j}|sdS|VqWdS)N)r4)r.r8rrr__iter__s zInputWrapper.__iter__cCstdddS)Nrz input.close() must not be called)r )r.rrrcloseszInputWrapper.closeN) rrrr0r1r4r5r9r:rrrrr%s r%c@s4eZdZddZddZddZddZd d Zd S) r&cCs ||_dS)N)errors)r. wsgi_errorsrrrr0szErrorWrapper.__init__cCs tt|tk|jj|dS)N)r r r r;write)r.srrrr=szErrorWrapper.writecCs|jjdS)N)r;flush)r.rrrr?szErrorWrapper.flushcCsx|D]}|j|qWdS)N)r=)r.seqr8rrr writeliness zErrorWrapper.writelinescCstdddS)Nrz!errors.close() must not be called)r )r.rrrr:szErrorWrapper.closeN)rrrr0r=r?rAr:rrrrr&s r&c@seZdZddZddZdS)rcCs ||_dS)N)writer)r.Z wsgi_writerrrrr0szWriteWrapper.__init__cCstt|tk|j|dS)N)r r r2rB)r.r>rrr__call__szWriteWrapper.__call__N)rrrr0rCrrrrrsrc@seZdZddZddZdS)PartialIteratorWrappercCs ||_dS)N)r*)r. wsgi_iteratorrrrr0szPartialIteratorWrapper.__init__cCs t|jdS)N)r(r*)r.rrrr9szPartialIteratorWrapper.__iter__N)rrrr0r9rrrrrDsrDc@s4eZdZddZddZddZddZd d Zd S) r(cCs ||_t||_d|_||_dS)NF)original_iteratoriterr*closedcheck_start_response)r.rErIrrrr0 s zIteratorWrapper.__init__cCs|S)Nr)r.rrrr9szIteratorWrapper.__iter__cCsTt|j dt|j}t|tk r4tdd|f|jdk rPt|jdd|_|S)NzIterator read after closedFz$Iterator yielded non-bytestring (%r)zjThe application returns and we started iterating over its body, but start_response has not yet been called)r rHnextr*r r2rI)r.r3rrr__next__s   zIteratorWrapper.__next__cCs d|_t|jdr|jjdS)NTr:)rHhasattrrFr:)r.rrrr:s zIteratorWrapper.closecCs"|jstjjdt|jddS)Nz/Iterator garbage collected without being closed)rHsysstderrr=r )r.rrr__del__#s zIteratorWrapper.__del__N)rrrr0r9rKr:rOrrrrr(s  r(c Cstt|tkdt||fx d,D]}t||kd |fq$Wx*d-D]"}t||kd||ddfqFWd|krtjdtxF|jD]:}d|krqtt||tkd|t||||fqWtt|dtkd|dft|dd.kd|dt |dt |d|dd/kros,  7#  #APKe[JpKK.__pycache__/simple_server.cpython-36.opt-1.pycnu[3 \ @s dZddlmZmZddlZddlZddlmZddl m Z dZ ddd d gZ d e Z e d ejjdZe d eZGdddeZGdddeZGdddeZdd Zeefdd ZedkreddeBZejjZededdeddddlZejdejWdQRXdS)a!BaseHTTPServer that implements the Python WSGI protocol (PEP 3333) This is both an example of how WSGI can be implemented, and a basis for running simple web applications on a local machine, such as might be done when testing or debugging an application. It has not been reviewed for security issues, however, and we strongly recommend that you use a "real" web server for production use. For example usage, see the 'if __name__=="__main__"' block at the end of the module. See also the BaseHTTPServer module docs for other API information. )BaseHTTPRequestHandler HTTPServerN) SimpleHandler)python_implementationz0.2 WSGIServerWSGIRequestHandlerdemo_app make_serverz WSGIServer// c@seZdZeZddZdS) ServerHandlerc Cs4z"|jj|jjddd|jWdtj|XdS)Nr r)request_handlerZ log_requestZstatussplitZ bytes_sentrclose)selfr-/usr/lib64/python3.6/wsgiref/simple_server.pyr szServerHandler.closeN)__name__ __module__ __qualname__software_versionZserver_softwarerrrrrr sr c@s4eZdZdZdZddZddZddZd d ZdS) rz7BaseHTTPServer that implements the Python WSGI protocolNcCstj||jdS)z.Override server_bind to store the server name.N)r server_bind setup_environ)rrrrr0s zWSGIServer.server_bindcCsFi}|_|j|d<d|d<t|j|d<d|d<d|d<d|d<dS) NZ SERVER_NAMEzCGI/1.1ZGATEWAY_INTERFACEZ SERVER_PORT REMOTE_HOSTCONTENT_LENGTHZ SCRIPT_NAME) base_environZ server_namestrZ server_port)renvrrrr5s  zWSGIServer.setup_environcCs|jS)N) application)rrrrget_app?szWSGIServer.get_appcCs ||_dS)N)r )rr rrrset_appBszWSGIServer.set_app) rrr__doc__r rrr!r"rrrrr*s  c@s,eZdZdeZddZddZddZdS) rz WSGIServer/cCsT|jjj}|j|d<|j|d<|j|d<d|jkrH|jjdd\}}n |jd}}tj j |d|d<||d <|j }||j d kr||d <|j d |d <|j jd dkr|j j|d<n|j d |d<|j jd}|r||d<xn|j jD]`\}}|jddj}|j}||krqd||kr@|d|d|7<q||d|<qW|S)NZSERVER_PROTOCOLZSERVER_SOFTWAREZREQUEST_METHOD?r rz iso-8859-1Z PATH_INFOZ QUERY_STRINGrrZ REMOTE_ADDRz content-typeZ CONTENT_TYPEzcontent-lengthr-_ZHTTP_,)serverrcopyrequest_versionserver_versioncommandpathrurllibparseZunquoteZaddress_stringZclient_addressZheadersgetZget_content_typeitemsreplaceupperstrip)rrr-ZqueryhostZlengthkvrrr get_environKs8        zWSGIRequestHandler.get_environcCstjS)N)sysstderr)rrrr get_stderrpszWSGIRequestHandler.get_stderrcCs||jjd|_t|jdkrrrrrrGs%cCsvddlm}|}td|dt|dt|j}x$|D]\}}t|dt||dq:W|dd g|jjd gS) Nr)StringIOz Hello world!)file=z200 OK Content-Typetext/plain; charset=utf-8zutf-8)rCrD)ior@printsortedr1reprgetvalueencode)environZstart_responser@stdouthr6r7rrrrs     cCs|||f|}|j||S)zACreate a new WSGI server listening on `host` and `port` for `app`)r")r5portZappZ server_classZ handler_classr(rrrr s __main__ri@zServing HTTP onrNr z...zhttp://localhost:8000/xyz?abc) r#Z http.serverrrr9Z urllib.parser.Zwsgiref.handlersrplatformrr?__all__r+versionr sys_versionrr rrrr rZhttpdZsocketZ getsocknameZsarFZ webbrowseropenZhandle_requestrrrr s,    B    PKe[ oF}})__pycache__/__init__.cpython-36.opt-2.pycnu[3 \K@sdS)Nrrr(/usr/lib64/python3.6/wsgiref/__init__.pysPKe[_>"("()__pycache__/handlers.cpython-36.opt-2.pycnu[3 \ R @sddlmZmZmZddlmZddlZddlZddlZddddd d gZ d d d ddddgZ dddddddddddddg Z ddZ d d!d"d#d$d%d&d'd(d)h j Zd*d+Zd,d ZGd-ddZGd.ddeZGd/ddeZGd0ddeZGd1d d eZdS)2) FileWrapper guess_scheme is_hop_by_hop)HeadersN BaseHandler SimpleHandlerBaseCGIHandler CGIHandler IISCGIHandler read_environZMonZTueZWedZThuZFriZSatZSunZJanZFebZMarZAprZMayZJunZJulZAugZSepZOctZNovZDecc Cs:tj|\ }}}}}}}}} dt||t|||||fS)Nz#%s, %02d %3s %4d %02d:%02d:%02d GMT)timeZgmtime _weekdayname _monthname) Z timestampZyearZmonthZdayZhhZmmZssZwdyzr(/usr/lib64/python3.6/wsgiref/handlers.pyformat_date_timesr SCRIPT_NAME PATH_INFOZ QUERY_STRINGZREQUEST_METHODZ AUTH_TYPEZ CONTENT_TYPEZCONTENT_LENGTHZHTTPSZ REMOTE_USERZ REMOTE_IDENTcCs6t|p4|jdp4|jdp4|jdo4t|ddS)NZHTTP_ZSSL_Z REDIRECT_ ) _is_request startswith_needs_transcode)krrrrsrc Cstj}d}ydjd|Wntk r4d}YnXi}xtjjD]\}}t|rtjdkrtjj ddj }|j dr|jdj d}q|j d rq|j d rd |kr|jdj d}q|j|dj d}n|j||j d}|||<qFW|S) Nsurrogateescapezutf-8replaceZwin32SERVER_SOFTWAREzmicrosoft-iis/z iso-8859-1zapache/z simplehttp/zpython/3) sysgetfilesystemencodingencode LookupErrorosenvironitemsrplatformgetlowerrdecode)encescr%rvZsoftwarerrrr "s,      c@seZdZd;ZdZdZdZdZdZdZ e Z e Z eZdZdZdrrrTFz1.0Nz500 Internal Server Error Content-Type text/plains;A server error occurred. Please contact the administrator.cCsZy$|j||j|j|_|jWn0y |jWn|jYnXYnXdS)N) setup_environr%start_responseresultfinish_response handle_errorclose)selfZ applicationrrrruns  zBaseHandler.runcCs|jj}|_|j|j|d<|j|d<|j|d<|j|d<|j|d<|j |d<|j |d<|j dk rx|j |d<|j r|j r|jd |j dS) Nz wsgi.inputz wsgi.errorsz wsgi.versionz wsgi.run_oncezwsgi.url_schemezwsgi.multithreadzwsgi.multiprocesszwsgi.file_wrapperr) os_environcopyr% add_cgi_vars get_stdin get_stderr wsgi_version wsgi_run_once get_schemewsgi_multithreadwsgi_multiprocesswsgi_file_wrapper origin_serverserver_software setdefault)r6envrrrr0s          zBaseHandler.setup_environc CsJz:|j s|j r8x|jD]}|j|qW|jWd|jXdS)N)result_is_filesendfiler2writefinish_contentr5)r6datarrrr3s   zBaseHandler.finish_responsecCs t|jS)N)rr%)r6rrrr?szBaseHandler.get_schemec CsJyt|j}Wntttfk r(YnX|dkrFt|j|jd<dSdS)NrzContent-Length)lenr2 TypeErrorAttributeErrorNotImplementedErrorstr bytes_sentheaders)r6Zblocksrrrset_content_lengthszBaseHandler.set_content_lengthcCsd|jkr|jdS)NzContent-Length)rRrS)r6rrrcleanup_headerss zBaseHandler.cleanup_headersc Csh|r2z$|jr&|d|dj|dWdd}Xn|jdk rDtd||_|j||_|j|d}|jS)NrrzHeaders already set!ZStatus) headers_sentwith_tracebackrRAssertionErrorstatus headers_class_convert_string_typerI)r6rYrRexc_inforrrr1s   zBaseHandler.start_responsecCs(t|tkr|Stdj|t|dS)Nz!{0} must be of type str (got {1}))typerPrXformatrepr)r6valuetitlerrrr[s z BaseHandler._convert_string_typecCs|jrx|jr|jd|j|jfjdd|jkrP|jdttjjd|j rd|jkr|jd|j jdn|jd|jjddS)Nz HTTP/%s %s z iso-8859-1ZDatez Date: %s ZServerz Server: %s z Status: %s ) rCclient_is_modern_write http_versionrYr"rRrr rD)r6rrr send_preambles zBaseHandler.send_preamblecCsR|jstdn,|js*t||_|jn|jt|7_|j||jdS)Nzwrite() before start_response())rYrXrVrLrQ send_headersrc_flush)r6rKrrrrIs    zBaseHandler.writecCsdS)NFr)r6rrrrHszBaseHandler.sendfilecCs"|js|jjdd|jndS)NzContent-Length0)rVrRrErf)r6rrrrJ0s zBaseHandler.finish_contentc CsFzt|jdr|jjWdd|_|_|_|_d|_d|_XdS)Nr5rF)hasattrr2r5rRrYr%rQrV)r6rrrr5:s  zBaseHandler.closecCs:|jd|_|j s|jr6|j|jt|jdS)NT)rTrVrCrbrercbytesrR)r6rrrrfGs zBaseHandler.send_headerscCs|j}|dk ot|j|S)N)rB isinstancer2)r6wrapperrrrrGPszBaseHandler.result_is_filecCs|jdjdkS)NZSERVER_PROTOCOLzHTTP/0.9)r%upper)r6rrrrbVszBaseHandler.client_is_modernc CsJz>ddlm}|j}||d|d|d|j||jWdd}XdS)Nr)print_exceptionrrU) tracebackrnr<traceback_limitflush)r6r\rnstderrrrr log_exception[s   zBaseHandler.log_exceptioncCs2|jtj|js.|j|j|j|_|jdS)N) rsr r\rV error_outputr%r1r2r3)r6rrrr4kszBaseHandler.handle_errorcCs$||j|jddtj|jgS)N) error_status error_headersr r\ error_body)r6r%r1rrrrtss zBaseHandler.error_outputcCstdS)N)rO)r6rKrrrrcszBaseHandler._writecCstdS)N)rO)r6rrrrgszBaseHandler._flushcCstdS)N)rO)r6rrrr;szBaseHandler.get_stdincCstdS)N)rO)r6rrrr<szBaseHandler.get_stderrcCstdS)N)rO)r6rrrr:szBaseHandler.add_cgi_vars)rr)r.r/)N)1__name__ __module__ __qualname__r=r@rAr>rCrdrDr r8rrBrrZrprurvrwrYr2rVrRrQr7r0r3r?rSrTr1r[rerIrHrJr5rfrGrbrsr4rtrcrgr;r<r:rrrrr^sT      c@s>eZdZdddZddZddZd d Zd d Zd dZdS)rTFcCs(||_||_||_||_||_||_dS)N)stdinstdoutrrbase_envr@rA)r6r{r|rrr% multithread multiprocessrrr__init__s zSimpleHandler.__init__cCs|jS)N)r{)r6rrrr;szSimpleHandler.get_stdincCs|jS)N)rr)r6rrrr<szSimpleHandler.get_stderrcCs|jj|jdS)N)r%updater})r6rrrr:szSimpleHandler.add_cgi_varscCsb|jj|}|dks |t|kr$dSddlm}|dtx"||d}|sNP|jj|}qr8rrrrrr sc@seZdZdZiZddZdS)r Tc Csjt}|jdd}|jdd}|dj|drD|t|d|d<tj|tjjtj jtj |ddddS)Nrrr/FT)r~r) r r(rrLr rr r{rr|rr)r6r%pathZscriptrrrr$s  zIISCGIHandler.__init__N)rxryrzr>r8rrrrrr s)utilrrrrRrr r$r __all__rrr __contains__rrr rrr r r rrrrs(   <H2PKe[0JJ%__pycache__/util.cpython-36.opt-1.pycnu[3 \ @sxdZddlZddddddgZGd ddZd dZd dZdd dZddZddZdddddddddj Z ddZ dS)z$Miscellaneous WSGI-related UtilitiesN FileWrapper guess_schemeapplication_uri request_urishift_path_infosetup_testing_defaultsc@s2eZdZdZd ddZddZddZd d Zd S) rz1Wrapper to convert file-like objects to iterables cCs"||_||_t|dr|j|_dS)Nclose)filelikeblksizehasattrr )selfr r r$/usr/lib64/python3.6/wsgiref/util.py__init__s zFileWrapper.__init__cCs|jj|j}|r|StdS)N)r readr IndexError)r keydatarrr __getitem__szFileWrapper.__getitem__cCs|S)Nr)r rrr__iter__szFileWrapper.__iter__cCs|jj|j}|r|StdS)N)r rr StopIteration)r rrrr__next__szFileWrapper.__next__N)r)__name__ __module__ __qualname____doc__rrrrrrrrr s  cCs|jddkrdSdSdS) zMReturn a guess for whether 'wsgi.url_scheme' should be 'http' or 'https' ZHTTPSyeson1httpshttpN)rrr)get)environrrrr#scCs|dd}ddlm}|jdr0||d7}nR||d7}|ddkrf|dd kr|d |d7}n|dd kr|d |d7}|||jd pd dd7}|S)z@Return the application's base URI (no PATH_INFO or QUERY_STRING)zwsgi.url_schemez://r)quote HTTP_HOST SERVER_NAMEr SERVER_PORT443:80 SCRIPT_NAME/latin1)encoding) urllib.parser$r")r#urlr$rrrr+s       TcCspt|}ddlm}||jddddd}|jdsF||d d 7}n||7}|rl|jd rl|d |d 7}|S) zBReturn the full request URI, optionally including the query stringr)r$ PATH_INFOz/;=,r-)Zsafer.r+NZ QUERY_STRING?)rr/r$r")r#Z include_queryr0r$ path_inforrrr?s  cCs|jdd}|sdS|jd}dd|dd D|dd <|d}|d=|jdd}tj|d|}|jdr~|dd }| r|jd r|d7}||d<dj||d<|d krd}|S) aZShift a name from PATH_INFO to SCRIPT_NAME, returning it If there are no remaining path segments in PATH_INFO, return None. Note: 'environ' is modified in-place; use a copy if you need to keep the original PATH_INFO or SCRIPT_NAME. Note: when PATH_INFO is just a '/', this returns '' and appends a trailing '/' to SCRIPT_NAME, even though empty path segments are normally ignored, and SCRIPT_NAME doesn't normally end in a '/'. This is intentional behavior, to ensure that an application can tell the difference between '/x' and '/x/' when traversing to objects. r1r2Nr,cSsg|]}|r|dkr|qS).r).0prrr ^sz#shift_path_info..r3r+r6r:r:)r"split posixpathnormpathendswithjoin)r#r5 path_partsnameZ script_namerrrrLs$     cCs|jdd|jdd|jd|d|jddd|kr\d |kr\|jdd |jd d |jd d|jdd|jdd|jddddlm}m}|jd||jd||jdt||ddkr|jddn|ddkr|jdddS)a:Update 'environ' with trivial defaults for testing purposes This adds various parameters required for WSGI, including HTTP_HOST, SERVER_NAME, SERVER_PORT, REQUEST_METHOD, SCRIPT_NAME, PATH_INFO, and all of the wsgi.* variables. It only supplies default values, and does not replace any existing settings for these variables. This routine is intended to make it easier for unit tests of WSGI servers and applications to set up dummy environments. It should *not* be used by actual WSGI servers or applications, since the data is fake! r&z 127.0.0.1ZSERVER_PROTOCOLzHTTP/1.0r%ZREQUEST_METHODZGETr+r1r2r,z wsgi.versionr3rz wsgi.run_oncezwsgi.multithreadzwsgi.multiprocess)StringIOBytesIOz wsgi.inputz wsgi.errorszwsgi.url_schemer!r'r*r r(N)r3r) setdefaultiorBrCr)r#rBrCrrrrus&           r3)Z connectionz keep-alivezproxy-authenticatezproxy-authorizationZteZtrailersztransfer-encodingZupgradecCs t|jS)z?Return true if 'header_name' is an HTTP/1.1 "Hop-by-Hop" header)_hoppishlower)Z header_namerrr is_hop_by_hopsrH)T) rr<__all__rrrrrr __contains__rFrHrrrrs )) PKe[:ܸ(__pycache__/headers.cpython-36.opt-1.pycnu[3 \n@s2dZddlZejdZd ddZGdddZdS) zManage HTTP Response Headers Much of this module is red-handedly pilfered from email.message in the stdlib, so portions are Copyright (C) 2001,2002 Python Software Foundation, and were written by Barry Warsaw. Nz[ \(\)<>@,;:\\"/\[\]\?=]cCsX|dk rPt|dkrP|s"tj|rB|jddjdd}d||fSd||fSn|SdS) z~Convenience function to format and return a key=value pair. This will quote the value if needed or if quote is true. Nr\z\\"z\"z%s="%s"z%s=%s)len tspecialssearchreplace)ZparamvalueZquoter '/usr/lib64/python3.6/wsgiref/headers.py _formatparam s  r c@seZdZdZd%ddZddZddZd d Zd d Zd dZ ddZ ddZ d&ddZ ddZ ddZddZddZddZdd Zd!d"Zd#d$ZdS)'Headersz,Manage a collection of HTTP response headersNcCs.|dk r |ng}t|tk r$td||_dS)Nz+Headers must be a list of name/value tuples)typelist TypeError_headers)selfZheadersr r r __init__s  zHeaders.__init__cCs&t|tkr|Stdjt|dS)zConvert/check value type.z1Header names/values must be of type str (got {0})N)rstrAssertionErrorformatrepr)rr r r r _convert_string_type)s zHeaders._convert_string_typecCs t|jS)z9Return the total number of headers, including duplicates.)rr)rr r r __len__0szHeaders.__len__cCs&||=|jj|j||j|fdS)zSet the value of a header.N)rappendr)rnamevalr r r __setitem__4szHeaders.__setitem__cs0|jjfdd|jD|jdd<dS)zyDelete all occurrences of a header, if present. Does *not* raise an exception if the header is missing. cs g|]}|djkr|qS)r)lower).0kv)rr r @sz'Headers.__delitem__..N)rrr)rrr )rr __delitem__:szHeaders.__delitem__cCs |j|S)aHGet the first header value for 'name' Return None if the header is missing instead of raising an exception. Note that if the header appeared multiple times, the first exactly which occurrence gets returned is undefined. Use getall() to get all the values matching a header field name. )get)rrr r r __getitem__Bs zHeaders.__getitem__cCs|j|dk S)z/Return true if the message contains the header.N)r#)rrr r r __contains__MszHeaders.__contains__cs"|jjfdd|jDS)aqReturn a list of all the values for the named field. These will be sorted in the order they appeared in the original header list or were added to this instance, and may contain duplicates. Any fields deleted and re-inserted are always appended to the header list. If no fields exist with the given name, returns an empty list. cs$g|]}|djkr|dqS)rr)r)rr )rr r r![sz#Headers.get_all..)rrr)rrr )rr get_allRszHeaders.get_allcCs6|j|j}x"|jD]\}}|j|kr|SqW|S)z:Get the first header value for 'name', or return 'default')rrr)rrdefaultkvr r r r#^s  z Headers.getcCsdd|jDS)a*Return a list of all the header field names. These will be sorted in the order they appeared in the original header list, or were added to this instance, and may contain duplicates. Any fields deleted and re-inserted are always appended to the header list. cSsg|] \}}|qSr r )rr(r)r r r r!osz Headers.keys..)r)rr r r keysgsz Headers.keyscCsdd|jDS)a!Return a list of all header values. These will be sorted in the order they appeared in the original header list, or were added to this instance, and may contain duplicates. Any fields deleted and re-inserted are always appended to the header list. cSsg|] \}}|qSr r )rr(r)r r r r!ysz"Headers.values..)r)rr r r valuesqszHeaders.valuescCs|jddS)aGet all the header fields and values. These will be sorted in the order they were in the original header list, or were added to this instance, and may contain duplicates. Any fields deleted and re-inserted are always appended to the header list. N)r)rr r r items{sz Headers.itemscCsd|jj|jfS)Nz%s(%r)) __class____name__r)rr r r __repr__szHeaders.__repr__cCsdjdd|jDddgS)zkstr() returns the formatted headers, complete with end line, suitable for direct HTTP transmission.z cSsg|] }d|qS)z%s: %sr )rr r r r r!sz#Headers.__str__..)joinr)rr r r __str__szHeaders.__str__cCst|jdS)Nz iso-8859-1)rencode)rr r r __bytes__szHeaders.__bytes__cCs:|j|}|dkr2|jj|j||j|f|S|SdS)zReturn first matching header value for 'name', or 'value' If there is no header named 'name', add a new header with name 'name' and value 'value'.N)r#rrr)rrr resultr r r setdefaults  zHeaders.setdefaultcKsg}|dk r |j|}|j|x\|jD]P\}}|j|}|dkrX|j|jddq*|j|}|jt|jdd|q*W|jj|j|dj|fdS)afExtended header setting. _name is the header field to add. keyword arguments can be used to set additional parameters for the header field, with underscores converted to dashes. Normally the parameter will be added as key="value" unless value is None, in which case only the key will be added. Example: h.add_header('content-disposition', 'attachment', filename='bud.gif') Note that unlike the corresponding 'email.message' method, this does *not* handle '(charset, language, value)' tuples: all values must be strings or None. N_-z; )rrr,rr rr1)r_nameZ_valueZ_paramspartsr(r)r r r add_headers    zHeaders.add_header)N)N)r. __module__ __qualname____doc__rrrrr"r$r%r&r#r*r+r,r/r2r4r6r;r r r r r s$       r )Nr)r>recompilerr r r r r r s  PKe[E%%%__pycache__/util.cpython-36.opt-2.pycnu[3 \ @stddlZddddddgZGdddZd dZd dZdd dZd dZddZdddddddddjZ ddZ dS)N FileWrapper guess_schemeapplication_uri request_urishift_path_infosetup_testing_defaultsc@s.eZdZd ddZddZddZdd Zd S) r cCs"||_||_t|dr|j|_dS)Nclose)filelikeblksizehasattrr )selfr r r$/usr/lib64/python3.6/wsgiref/util.py__init__s zFileWrapper.__init__cCs|jj|j}|r|StdS)N)r readr IndexError)r keydatarrr __getitem__szFileWrapper.__getitem__cCs|S)Nr)r rrr__iter__szFileWrapper.__iter__cCs|jj|j}|r|StdS)N)r rr StopIteration)r rrrr__next__szFileWrapper.__next__N)r)__name__ __module__ __qualname__rrrrrrrrr s cCs|jddkrdSdSdS)NZHTTPSyeson1httpshttp)rrr)get)environrrrr#scCs|dd}ddlm}|jdr0||d7}nR||d7}|ddkrf|dd kr|d |d7}n|dd kr|d |d7}|||jd pd dd7}|S)Nzwsgi.url_schemez://r)quote HTTP_HOST SERVER_NAMEr SERVER_PORT443:80 SCRIPT_NAME/latin1)encoding) urllib.parser#r!)r"urlr#rrrr+s       TcCspt|}ddlm}||jddddd}|jdsF||d d7}n||7}|rl|jd rl|d |d 7}|S) Nr)r# PATH_INFOz/;=,r,)Zsafer-r*Z QUERY_STRING?)rr.r#r!)r"Z include_queryr/r# path_inforrrr?s  cCs|jdd}|sdS|jd}dd|dd D|dd <|d}|d=|jdd}tj|d|}|jdr~|dd }| r|jd r|d7}||d<dj||d<|dkrd}|S) Nr0r1r+cSsg|]}|r|dkr|qS).r).0prrr ^sz#shift_path_info..r2r*r5r9r9)r!split posixpathnormpathendswithjoin)r"r4 path_partsnameZ script_namerrrrLs$     cCs|jdd|jdd|jd|d|jddd|kr\d |kr\|jdd |jd d |jd d|jdd|jdd|jddddlm}m}|jd||jd||jdt||ddkr|jddn|ddkr|jdddS)Nr%z 127.0.0.1ZSERVER_PROTOCOLzHTTP/1.0r$ZREQUEST_METHODZGETr*r0r1r+z wsgi.versionr2rz wsgi.run_oncezwsgi.multithreadzwsgi.multiprocess)StringIOBytesIOz wsgi.inputz wsgi.errorszwsgi.url_schemer r&r)rr')r2r) setdefaultiorArBr)r"rArBrrrrus&           r2)Z connectionz keep-alivezproxy-authenticatezproxy-authorizationZteZtrailersztransfer-encodingZupgradecCs t|jS)N)_hoppishlower)Z header_namerrr is_hop_by_hopsrG)T) r;__all__rrrrrr __contains__rErGrrrrs )) PKe[u 99#__pycache__/validate.cpython-36.pycnu[3 \;;@sdZdgZddlZddlZddlZejdZejdZGdddeZ dd Z d d Z d dZ Gd ddZ GdddZGdddZGdddZGdddZddZddZddZddZdd Zd!d"Zd#d$Zd%d&ZdS)'a& Middleware to check for obedience to the WSGI specification. Some of the things this checks: * Signature of the application and start_response (including that keyword arguments are not used). * Environment checks: - Environment is a dictionary (and not a subclass). - That all the required keys are in the environment: REQUEST_METHOD, SERVER_NAME, SERVER_PORT, wsgi.version, wsgi.input, wsgi.errors, wsgi.multithread, wsgi.multiprocess, wsgi.run_once - That HTTP_CONTENT_TYPE and HTTP_CONTENT_LENGTH are not in the environment (these headers should appear as CONTENT_LENGTH and CONTENT_TYPE). - Warns if QUERY_STRING is missing, as the cgi module acts unpredictably in that case. - That CGI-style variables (that don't contain a .) have (non-unicode) string values - That wsgi.version is a tuple - That wsgi.url_scheme is 'http' or 'https' (@@: is this too restrictive?) - Warns if the REQUEST_METHOD is not known (@@: probably too restrictive). - That SCRIPT_NAME and PATH_INFO are empty or start with / - That at least one of SCRIPT_NAME or PATH_INFO are set. - That CONTENT_LENGTH is a positive integer. - That SCRIPT_NAME is not '/' (it should be '', and PATH_INFO should be '/'). - That wsgi.input has the methods read, readline, readlines, and __iter__ - That wsgi.errors has the methods flush, write, writelines * The status is a string, contains a space, starts with an integer, and that integer is in range (> 100). * That the headers is a list (not a subclass, not another kind of sequence). * That the items of the headers are tuples of strings. * That there is no 'status' header (that is used in CGI, but not in WSGI). * That the headers don't contain newlines or colons, end in _ or -, or contain characters codes below 037. * That Content-Type is given if there is content (CGI often has a default content type, but WSGI does not). * That no Content-Type is given when there is no content (@@: is this too restrictive?) * That the exc_info argument to start_response is a tuple or None. * That all calls to the writer are with strings, and no other methods on the writer are accessed. * That wsgi.input is used properly: - .read() is called with zero or one argument - That it returns a string - That readline, readlines, and __iter__ return strings - That .close() is not called - No other methods are provided * That wsgi.errors is used properly: - .write() and .writelines() is called with a string - That .close() is not called, and no other methods are provided. * The response iterator: - That it is not a string (it should be a list of a single string; a string will work, but perform horribly). - That .__next__() returns a string - That the iterator is not iterated over until start_response has been called (that can signal either a server or application error). - That .close() is called (doesn't raise exception, only prints to sys.stderr, because we only know it isn't called when the object is garbage collected). validatorNz^[a-zA-Z][a-zA-Z0-9\-_]*$z [\000-\037]c@seZdZdZdS) WSGIWarningz: Raised in response to WSGI-spec-related warnings N)__name__ __module__ __qualname____doc__rr(/usr/lib64/python3.6/wsgiref/validate.pyrysrcGs|s t|dS)N)AssertionError)Zcondargsrrr assert_~sr cCs(t|tkr|Stdj|t|dS)Nz!{0} must be of type str (got {1}))typestrr formatrepr)valuetitlerrr check_string_types rcsfdd}|S)a When applied between a WSGI server and a WSGI application, this middleware will check for WSGI compliancy on a number of levels. This middleware does not modify the request or response in any way, but will raise an AssertionError if anything seems off (except for a failure to close the application iterator, which will be printed to stderr -- there's no way to raise an exception at that point). cstt|dkdt| d|\}t|gfdd}t|d|d<t|d|d<||}t|dk oz|dkd t|t|S) NzTwo arguments requiredzNo keyword arguments allowedcstt|dkpt|dkd|ft| d|d}|d}t|dkrV|d}nd}t|t|t||t|jdt|S)NrzInvalid number of arguments: %szNo keyword arguments allowedr)r len check_status check_headerscheck_content_typecheck_exc_infoappend WriteWrapper)r kwstatusheadersexc_info)start_responsestart_response_startedrr start_response_wrappers      z;validator..lint_app..start_response_wrapperz wsgi.inputz wsgi.errorsFz>The application must return an iterator, if only an empty list)r r check_environ InputWrapper ErrorWrappercheck_iteratorIteratorWrapper)r renvironr$iterator) application)r"r#r lint_apps  zvalidator..lint_appr)r,r-r)r,r rs )c@s<eZdZddZddZddZddZd d Zd d Zd S)r&cCs ||_dS)N)input)self wsgi_inputrrr __init__szInputWrapper.__init__cGs0tt|dk|jj|}tt|tk|S)Nr)r rr.readr bytes)r/r vrrr r2s zInputWrapper.readcGs0tt|dk|jj|}tt|tk|S)Nr)r rr.readliner r3)r/r r4rrr r5s zInputWrapper.readlinecGsNtt|dk|jj|}tt|tkx|D]}tt|tkq2W|S)Nr)r rr. readlinesr listr3)r/r lineslinerrr r6s   zInputWrapper.readlinesccs x|j}|sdS|VqWdS)N)r5)r/r9rrr __iter__s zInputWrapper.__iter__cCstdddS)Nrz input.close() must not be called)r )r/rrr closeszInputWrapper.closeN) rrrr1r2r5r6r:r;rrrr r&s r&c@s4eZdZddZddZddZddZd d Zd S) r'cCs ||_dS)N)errors)r/ wsgi_errorsrrr r1szErrorWrapper.__init__cCs tt|tk|jj|dS)N)r r rr<write)r/srrr r>szErrorWrapper.writecCs|jjdS)N)r<flush)r/rrr r@szErrorWrapper.flushcCsx|D]}|j|qWdS)N)r>)r/seqr9rrr writeliness zErrorWrapper.writelinescCstdddS)Nrz!errors.close() must not be called)r )r/rrr r;szErrorWrapper.closeN)rrrr1r>r@rBr;rrrr r's r'c@seZdZddZddZdS)rcCs ||_dS)N)writer)r/Z wsgi_writerrrr r1szWriteWrapper.__init__cCstt|tk|j|dS)N)r r r3rC)r/r?rrr __call__szWriteWrapper.__call__N)rrrr1rDrrrr rsrc@seZdZddZddZdS)PartialIteratorWrappercCs ||_dS)N)r+)r/ wsgi_iteratorrrr r1szPartialIteratorWrapper.__init__cCs t|jdS)N)r)r+)r/rrr r:szPartialIteratorWrapper.__iter__N)rrrr1r:rrrr rEsrEc@s4eZdZddZddZddZddZd d Zd S) r)cCs ||_t||_d|_||_dS)NF)original_iteratoriterr+closedcheck_start_response)r/rFrJrrr r1 s zIteratorWrapper.__init__cCs|S)Nr)r/rrr r:szIteratorWrapper.__iter__cCsTt|j dt|j}t|tk r4tdd|f|jdk rPt|jdd|_|S)NzIterator read after closedFz$Iterator yielded non-bytestring (%r)zjThe application returns and we started iterating over its body, but start_response has not yet been called)r rInextr+r r3rJ)r/r4rrr __next__s   zIteratorWrapper.__next__cCs d|_t|jdr|jjdS)NTr;)rIhasattrrGr;)r/rrr r;s zIteratorWrapper.closecCs"|jstjjdt|jddS)Nz/Iterator garbage collected without being closed)rIsysstderrr>r )r/rrr __del__#s zIteratorWrapper.__del__N)rrrr1r:rLr;rPrrrr r)s  r)c Cstt|tkdt||fx d,D]}t||kd |fq$Wx*d-D]"}t||kd||ddfqFWd|krtjdtxF|jD]:}d|krqtt||tkd|t||||fqWtt|dtkd|dft|dd.kd|dt |dt |d|dd/krrBz.wsgi.errors (%r) doesn't have the attribute %s)r@r>rB)r rM)r=rtrrr roqs  rocCsvt|d}|jddd}tt|dkd|t|}t|dkd|t|dksb|dd krrtjd |tdS) NStatusrrrz)Status codes must be three characters: %rdzStatus code is invalid: %r zjThe status string (%r) should be a three-digit integer followed by a single space and a status explanation)rsplitr rrrrjrkr)rZ status_codeZ status_intrrr rws   rcCstt|tkd|t|fi}x|D]}tt|tkd|t|ftt|dk|\}}t|d}t|d}t|jdkd|d||j<td|kod |kd |ttj|d |t|j d  o|j d  d|t j|r(tdd|t j|j dfq(WdS)Nz%Headers (%r) must be of type list: %rz1Individual headers (%r) must be of type tuple: %rrz Header namez Header valuerzyThe Status header cannot be used; it conflicts with CGI script, and HTTP status is not given through headers (value: %r). :z,Header names may not contain ':' or '\n': %rzBad header name: %r-_z#Names may not end in '-' or '_': %rrz#Bad header value: %r (bad char: %r)) r r r7rmrrlower header_researchendswithbad_header_value_regroup)r Z header_namesitemnamerrrr rs0          rcCs~t|d}t|jddd}d }x@|D]8\}}t|d}|jdkr(||krRdStdd|q(W||krztdd |dS) Nrurr0z Header namez content-typezJContent-Type header found in a %s response, which must not return content.z,No Content-Type header found in headers (%s))rr)rrrryr~r )rr codeZNO_MESSAGE_BODYrrrrr rs    rcCs*t|dkpt|tkd|t|fdS)Nz exc_info (%r) is not a tuple: %r)r r rm)r!rrr rsrcCstt|ttf ddS)NzwYou should not return a string as your application iterator, instead return a single-item list containing a bytestring.)r isinstancerr3)r+rrr r(sr()r__all__rerNrjcompilerrWarningrr rrr&r'rrEr)r%rnrorrrrr(rrrr ns.  7#  #APKe[JpKK(__pycache__/simple_server.cpython-36.pycnu[3 \ @s dZddlmZmZddlZddlZddlmZddl m Z dZ ddd d gZ d e Z e d ejjdZe d eZGdddeZGdddeZGdddeZdd Zeefdd ZedkreddeBZejjZededdeddddlZejdejWdQRXdS)a!BaseHTTPServer that implements the Python WSGI protocol (PEP 3333) This is both an example of how WSGI can be implemented, and a basis for running simple web applications on a local machine, such as might be done when testing or debugging an application. It has not been reviewed for security issues, however, and we strongly recommend that you use a "real" web server for production use. For example usage, see the 'if __name__=="__main__"' block at the end of the module. See also the BaseHTTPServer module docs for other API information. )BaseHTTPRequestHandler HTTPServerN) SimpleHandler)python_implementationz0.2 WSGIServerWSGIRequestHandlerdemo_app make_serverz WSGIServer// c@seZdZeZddZdS) ServerHandlerc Cs4z"|jj|jjddd|jWdtj|XdS)Nr r)request_handlerZ log_requestZstatussplitZ bytes_sentrclose)selfr-/usr/lib64/python3.6/wsgiref/simple_server.pyr szServerHandler.closeN)__name__ __module__ __qualname__software_versionZserver_softwarerrrrrr sr c@s4eZdZdZdZddZddZddZd d ZdS) rz7BaseHTTPServer that implements the Python WSGI protocolNcCstj||jdS)z.Override server_bind to store the server name.N)r server_bind setup_environ)rrrrr0s zWSGIServer.server_bindcCsFi}|_|j|d<d|d<t|j|d<d|d<d|d<d|d<dS) NZ SERVER_NAMEzCGI/1.1ZGATEWAY_INTERFACEZ SERVER_PORT REMOTE_HOSTCONTENT_LENGTHZ SCRIPT_NAME) base_environZ server_namestrZ server_port)renvrrrr5s  zWSGIServer.setup_environcCs|jS)N) application)rrrrget_app?szWSGIServer.get_appcCs ||_dS)N)r )rr rrrset_appBszWSGIServer.set_app) rrr__doc__r rrr!r"rrrrr*s  c@s,eZdZdeZddZddZddZdS) rz WSGIServer/cCsT|jjj}|j|d<|j|d<|j|d<d|jkrH|jjdd\}}n |jd}}tj j |d|d<||d <|j }||j d kr||d <|j d |d <|j jd dkr|j j|d<n|j d |d<|j jd}|r||d<xn|j jD]`\}}|jddj}|j}||krqd||kr@|d|d|7<q||d|<qW|S)NZSERVER_PROTOCOLZSERVER_SOFTWAREZREQUEST_METHOD?r rz iso-8859-1Z PATH_INFOZ QUERY_STRINGrrZ REMOTE_ADDRz content-typeZ CONTENT_TYPEzcontent-lengthr-_ZHTTP_,)serverrcopyrequest_versionserver_versioncommandpathrurllibparseZunquoteZaddress_stringZclient_addressZheadersgetZget_content_typeitemsreplaceupperstrip)rrr-ZqueryhostZlengthkvrrr get_environKs8        zWSGIRequestHandler.get_environcCstjS)N)sysstderr)rrrr get_stderrpszWSGIRequestHandler.get_stderrcCs||jjd|_t|jdkrrrrrrGs%cCsvddlm}|}td|dt|dt|j}x$|D]\}}t|dt||dq:W|dd g|jjd gS) Nr)StringIOz Hello world!)file=z200 OK Content-Typetext/plain; charset=utf-8zutf-8)rCrD)ior@printsortedr1reprgetvalueencode)environZstart_responser@stdouthr6r7rrrrs     cCs|||f|}|j||S)zACreate a new WSGI server listening on `host` and `port` for `app`)r")r5portZappZ server_classZ handler_classr(rrrr s __main__ri@zServing HTTP onrNr z...zhttp://localhost:8000/xyz?abc) r#Z http.serverrrr9Z urllib.parser.Zwsgiref.handlersrplatformrr?__all__r+versionr sys_versionrr rrrr rZhttpdZsocketZ getsocknameZsarFZ webbrowseropenZhandle_requestrrrr s,    B    PKe[u 99)__pycache__/validate.cpython-36.opt-1.pycnu[3 \;;@sdZdgZddlZddlZddlZejdZejdZGdddeZ dd Z d d Z d dZ Gd ddZ GdddZGdddZGdddZGdddZddZddZddZddZdd Zd!d"Zd#d$Zd%d&ZdS)'a& Middleware to check for obedience to the WSGI specification. Some of the things this checks: * Signature of the application and start_response (including that keyword arguments are not used). * Environment checks: - Environment is a dictionary (and not a subclass). - That all the required keys are in the environment: REQUEST_METHOD, SERVER_NAME, SERVER_PORT, wsgi.version, wsgi.input, wsgi.errors, wsgi.multithread, wsgi.multiprocess, wsgi.run_once - That HTTP_CONTENT_TYPE and HTTP_CONTENT_LENGTH are not in the environment (these headers should appear as CONTENT_LENGTH and CONTENT_TYPE). - Warns if QUERY_STRING is missing, as the cgi module acts unpredictably in that case. - That CGI-style variables (that don't contain a .) have (non-unicode) string values - That wsgi.version is a tuple - That wsgi.url_scheme is 'http' or 'https' (@@: is this too restrictive?) - Warns if the REQUEST_METHOD is not known (@@: probably too restrictive). - That SCRIPT_NAME and PATH_INFO are empty or start with / - That at least one of SCRIPT_NAME or PATH_INFO are set. - That CONTENT_LENGTH is a positive integer. - That SCRIPT_NAME is not '/' (it should be '', and PATH_INFO should be '/'). - That wsgi.input has the methods read, readline, readlines, and __iter__ - That wsgi.errors has the methods flush, write, writelines * The status is a string, contains a space, starts with an integer, and that integer is in range (> 100). * That the headers is a list (not a subclass, not another kind of sequence). * That the items of the headers are tuples of strings. * That there is no 'status' header (that is used in CGI, but not in WSGI). * That the headers don't contain newlines or colons, end in _ or -, or contain characters codes below 037. * That Content-Type is given if there is content (CGI often has a default content type, but WSGI does not). * That no Content-Type is given when there is no content (@@: is this too restrictive?) * That the exc_info argument to start_response is a tuple or None. * That all calls to the writer are with strings, and no other methods on the writer are accessed. * That wsgi.input is used properly: - .read() is called with zero or one argument - That it returns a string - That readline, readlines, and __iter__ return strings - That .close() is not called - No other methods are provided * That wsgi.errors is used properly: - .write() and .writelines() is called with a string - That .close() is not called, and no other methods are provided. * The response iterator: - That it is not a string (it should be a list of a single string; a string will work, but perform horribly). - That .__next__() returns a string - That the iterator is not iterated over until start_response has been called (that can signal either a server or application error). - That .close() is called (doesn't raise exception, only prints to sys.stderr, because we only know it isn't called when the object is garbage collected). validatorNz^[a-zA-Z][a-zA-Z0-9\-_]*$z [\000-\037]c@seZdZdZdS) WSGIWarningz: Raised in response to WSGI-spec-related warnings N)__name__ __module__ __qualname____doc__rr(/usr/lib64/python3.6/wsgiref/validate.pyrysrcGs|s t|dS)N)AssertionError)Zcondargsrrr assert_~sr cCs(t|tkr|Stdj|t|dS)Nz!{0} must be of type str (got {1}))typestrr formatrepr)valuetitlerrr check_string_types rcsfdd}|S)a When applied between a WSGI server and a WSGI application, this middleware will check for WSGI compliancy on a number of levels. This middleware does not modify the request or response in any way, but will raise an AssertionError if anything seems off (except for a failure to close the application iterator, which will be printed to stderr -- there's no way to raise an exception at that point). cstt|dkdt| d|\}t|gfdd}t|d|d<t|d|d<||}t|dk oz|dkd t|t|S) NzTwo arguments requiredzNo keyword arguments allowedcstt|dkpt|dkd|ft| d|d}|d}t|dkrV|d}nd}t|t|t||t|jdt|S)NrzInvalid number of arguments: %szNo keyword arguments allowedr)r len check_status check_headerscheck_content_typecheck_exc_infoappend WriteWrapper)r kwstatusheadersexc_info)start_responsestart_response_startedrr start_response_wrappers      z;validator..lint_app..start_response_wrapperz wsgi.inputz wsgi.errorsFz>The application must return an iterator, if only an empty list)r r check_environ InputWrapper ErrorWrappercheck_iteratorIteratorWrapper)r renvironr$iterator) application)r"r#r lint_apps  zvalidator..lint_appr)r,r-r)r,r rs )c@s<eZdZddZddZddZddZd d Zd d Zd S)r&cCs ||_dS)N)input)self wsgi_inputrrr __init__szInputWrapper.__init__cGs0tt|dk|jj|}tt|tk|S)Nr)r rr.readr bytes)r/r vrrr r2s zInputWrapper.readcGs0tt|dk|jj|}tt|tk|S)Nr)r rr.readliner r3)r/r r4rrr r5s zInputWrapper.readlinecGsNtt|dk|jj|}tt|tkx|D]}tt|tkq2W|S)Nr)r rr. readlinesr listr3)r/r lineslinerrr r6s   zInputWrapper.readlinesccs x|j}|sdS|VqWdS)N)r5)r/r9rrr __iter__s zInputWrapper.__iter__cCstdddS)Nrz input.close() must not be called)r )r/rrr closeszInputWrapper.closeN) rrrr1r2r5r6r:r;rrrr r&s r&c@s4eZdZddZddZddZddZd d Zd S) r'cCs ||_dS)N)errors)r/ wsgi_errorsrrr r1szErrorWrapper.__init__cCs tt|tk|jj|dS)N)r r rr<write)r/srrr r>szErrorWrapper.writecCs|jjdS)N)r<flush)r/rrr r@szErrorWrapper.flushcCsx|D]}|j|qWdS)N)r>)r/seqr9rrr writeliness zErrorWrapper.writelinescCstdddS)Nrz!errors.close() must not be called)r )r/rrr r;szErrorWrapper.closeN)rrrr1r>r@rBr;rrrr r's r'c@seZdZddZddZdS)rcCs ||_dS)N)writer)r/Z wsgi_writerrrr r1szWriteWrapper.__init__cCstt|tk|j|dS)N)r r r3rC)r/r?rrr __call__szWriteWrapper.__call__N)rrrr1rDrrrr rsrc@seZdZddZddZdS)PartialIteratorWrappercCs ||_dS)N)r+)r/ wsgi_iteratorrrr r1szPartialIteratorWrapper.__init__cCs t|jdS)N)r)r+)r/rrr r:szPartialIteratorWrapper.__iter__N)rrrr1r:rrrr rEsrEc@s4eZdZddZddZddZddZd d Zd S) r)cCs ||_t||_d|_||_dS)NF)original_iteratoriterr+closedcheck_start_response)r/rFrJrrr r1 s zIteratorWrapper.__init__cCs|S)Nr)r/rrr r:szIteratorWrapper.__iter__cCsTt|j dt|j}t|tk r4tdd|f|jdk rPt|jdd|_|S)NzIterator read after closedFz$Iterator yielded non-bytestring (%r)zjThe application returns and we started iterating over its body, but start_response has not yet been called)r rInextr+r r3rJ)r/r4rrr __next__s   zIteratorWrapper.__next__cCs d|_t|jdr|jjdS)NTr;)rIhasattrrGr;)r/rrr r;s zIteratorWrapper.closecCs"|jstjjdt|jddS)Nz/Iterator garbage collected without being closed)rIsysstderrr>r )r/rrr __del__#s zIteratorWrapper.__del__N)rrrr1r:rLr;rPrrrr r)s  r)c Cstt|tkdt||fx d,D]}t||kd |fq$Wx*d-D]"}t||kd||ddfqFWd|krtjdtxF|jD]:}d|krqtt||tkd|t||||fqWtt|dtkd|dft|dd.kd|dt |dt |d|dd/krrBz.wsgi.errors (%r) doesn't have the attribute %s)r@r>rB)r rM)r=rtrrr roqs  rocCsvt|d}|jddd}tt|dkd|t|}t|dkd|t|dksb|dd krrtjd |tdS) NStatusrrrz)Status codes must be three characters: %rdzStatus code is invalid: %r zjThe status string (%r) should be a three-digit integer followed by a single space and a status explanation)rsplitr rrrrjrkr)rZ status_codeZ status_intrrr rws   rcCstt|tkd|t|fi}x|D]}tt|tkd|t|ftt|dk|\}}t|d}t|d}t|jdkd|d||j<td|kod |kd |ttj|d |t|j d  o|j d  d|t j|r(tdd|t j|j dfq(WdS)Nz%Headers (%r) must be of type list: %rz1Individual headers (%r) must be of type tuple: %rrz Header namez Header valuerzyThe Status header cannot be used; it conflicts with CGI script, and HTTP status is not given through headers (value: %r). :z,Header names may not contain ':' or '\n': %rzBad header name: %r-_z#Names may not end in '-' or '_': %rrz#Bad header value: %r (bad char: %r)) r r r7rmrrlower header_researchendswithbad_header_value_regroup)r Z header_namesitemnamerrrr rs0          rcCs~t|d}t|jddd}d }x@|D]8\}}t|d}|jdkr(||krRdStdd|q(W||krztdd |dS) Nrurr0z Header namez content-typezJContent-Type header found in a %s response, which must not return content.z,No Content-Type header found in headers (%s))rr)rrrryr~r )rr codeZNO_MESSAGE_BODYrrrrr rs    rcCs*t|dkpt|tkd|t|fdS)Nz exc_info (%r) is not a tuple: %r)r r rm)r!rrr rsrcCstt|ttf ddS)NzwYou should not return a string as your application iterator, instead return a single-item list containing a bytestring.)r isinstancerr3)r+rrr r(sr()r__all__rerNrjcompilerrWarningrr rrr&r'rrEr)r%rnrorrrrr(rrrr ns.  7#  #APKe[??#__pycache__/handlers.cpython-36.pycnu[3 \ R @sdZddlmZmZmZddlmZddlZddlZddl Z dddd d d gZ d d dddddgZ dddddddddddddg Z dd Z d!d"d#d$d%d&d'd(d)d*h jZd+d,Zd-d ZGd.ddZGd/ddeZGd0ddeZGd1d d eZGd2d d eZdS)3z/Base classes for server/gateway implementations) FileWrapper guess_scheme is_hop_by_hop)HeadersN BaseHandler SimpleHandlerBaseCGIHandler CGIHandler IISCGIHandler read_environZMonZTueZWedZThuZFriZSatZSunZJanZFebZMarZAprZMayZJunZJulZAugZSepZOctZNovZDecc Cs:tj|\ }}}}}}}}} dt||t|||||fS)Nz#%s, %02d %3s %4d %02d:%02d:%02d GMT)timeZgmtime _weekdayname _monthname) Z timestampZyearZmonthZdayZhhZmmZssZwdyzr(/usr/lib64/python3.6/wsgiref/handlers.pyformat_date_timesr SCRIPT_NAME PATH_INFOZ QUERY_STRINGZREQUEST_METHODZ AUTH_TYPEZ CONTENT_TYPEZCONTENT_LENGTHZHTTPSZ REMOTE_USERZ REMOTE_IDENTcCs6t|p4|jdp4|jdp4|jdo4t|ddS)NZHTTP_ZSSL_Z REDIRECT_ ) _is_request startswith_needs_transcode)krrrrsrc Cstj}d}ydjd|Wntk r4d}YnXi}xtjjD]\}}t|rtjdkrtjj ddj }|j dr|jdj d}q|j d rq|j d rd |kr|jdj d}q|j|dj d}n|j||j d}|||<qFW|S) z'Read environment, fixing HTTP variablessurrogateescapezutf-8replaceZwin32SERVER_SOFTWAREzmicrosoft-iis/z iso-8859-1zapache/z simplehttp/zpython/3) sysgetfilesystemencodingencode LookupErrorosenvironitemsrplatformgetlowerrdecode)encescr%rvZsoftwarerrrr "s,      c@s"eZdZdZdddZ ddZ!ddZ"ddZ#d d!Z$d"d#Z%d$d%Z&d&d'Z'd(d)Z(d*d+Z)d,d-Z*d.d/Z+d0d1Z,d2d3Z-d4d5Z.d6d7Z/d8d9Z0d:d;Z1dS)?rz+Manage the invocation of a WSGI applicationrrTFz1.0Nz500 Internal Server Error Content-Type text/plains;A server error occurred. Please contact the administrator.cCsZy$|j||j|j|_|jWn0y |jWn|jYnXYnXdS)zInvoke the applicationN) setup_environr%start_responseresultfinish_response handle_errorclose)selfZ applicationrrrruns  zBaseHandler.runcCs|jj}|_|j|j|d<|j|d<|j|d<|j|d<|j|d<|j |d<|j |d<|j dk rx|j |d <|j r|j r|jd |j dS) z&Set up the environment for one requestz wsgi.inputz wsgi.errorsz wsgi.versionz wsgi.run_oncezwsgi.url_schemezwsgi.multithreadzwsgi.multiprocessNzwsgi.file_wrapperr) os_environcopyr% add_cgi_vars get_stdin get_stderr wsgi_version wsgi_run_once get_schemewsgi_multithreadwsgi_multiprocesswsgi_file_wrapper origin_serverserver_software setdefault)r6envrrrr0s          zBaseHandler.setup_environc CsJz:|j s|j r8x|jD]}|j|qW|jWd|jXdS)a>Send any iterable data, then close self and the iterable Subclasses intended for use in asynchronous servers will want to redefine this method, such that it sets up callbacks in the event loop to iterate over the data, and to call 'self.close()' once the response is finished. N)result_is_filesendfiler2writefinish_contentr5)r6datarrrr3s   zBaseHandler.finish_responsecCs t|jS)z Return the URL scheme being used)rr%)r6rrrr?szBaseHandler.get_schemec CsJyt|j}Wntttfk r(YnX|dkrFt|j|jd<dSdS)z@Compute Content-Length or switch to chunked encoding if possiblerzContent-LengthN)lenr2 TypeErrorAttributeErrorNotImplementedErrorstr bytes_sentheaders)r6Zblocksrrrset_content_lengthszBaseHandler.set_content_lengthcCsd|jkr|jdS)zqMake any necessary header changes or defaults Subclasses can extend this to add other defaults. zContent-LengthN)rRrS)r6rrrcleanup_headerss zBaseHandler.cleanup_headersc Cs|r2z$|jr&|d|dj|dWdd}Xn|jdk rDtd||_|j||_|j|d}t|dksvtd|dd jstd |d d kstd x:|D]2\}}|j|d }|j|d}t | stdqW|j S)z4'start_response()' callable as specified by PEP 3333rrNzHeaders already set!ZStatusz$Status must be at least 4 charactersz(Status message must begin w/3-digit code z+Status message must have a space after codez Header namez Header valuezHop-by-hop headers not allowed) headers_sentwith_tracebackrRAssertionErrorstatus headers_class_convert_string_typerLisdigitrrI)r6r\rRexc_infonamevalrrrr1s$     zBaseHandler.start_responsecCs(t|tkr|Stdj|t|dS)zConvert/check value type.z!{0} must be of type str (got {1})N)typerPr[formatrepr)r6valuetitlerrrr^s z BaseHandler._convert_string_typecCs|jrx|jr|jd|j|jfjdd|jkrP|jdttjjd|j rd|jkr|jd|j jdn|jd|jjddS) z6Transmit version/status/date/server, via self._write()z HTTP/%s %s z iso-8859-1ZDatez Date: %s ZServerz Server: %s z Status: %s N) rCclient_is_modern_write http_versionr\r"rRrr rD)r6rrr send_preambles zBaseHandler.send_preamblecCsft|tkstd|js$tdn,|js>t||_|jn|jt|7_|j||j dS)z+'write()' callable as specified by PEP 3333z)write() argument must be a bytes instancezwrite() before start_response()N) rcbytesr[r\rYrLrQ send_headersri_flush)r6rKrrrrIs    zBaseHandler.writecCsdS)aPlatform-specific file transmission Override this method in subclasses to support platform-specific file transmission. It is only called if the application's return iterable ('self.result') is an instance of 'self.wsgi_file_wrapper'. This method should return a true value if it was able to actually transmit the wrapped file-like object using a platform-specific approach. It should return a false value if normal iteration should be used instead. An exception can be raised to indicate that transmission was attempted, but failed. NOTE: this method should call 'self.send_headers()' if 'self.headers_sent' is false and it is going to attempt direct transmission of the file. Fr)r6rrrrHszBaseHandler.sendfilecCs"|js|jjdd|jndS)z.Ensure headers and content have both been sentzContent-Length0N)rYrRrErm)r6rrrrJ0s zBaseHandler.finish_contentc CsFzt|jdr|jjWdd|_|_|_|_d|_d|_XdS)zClose the iterable (if needed) and reset all instance vars Subclasses may want to also drop the client connection. r5NrF)hasattrr2r5rRr\r%rQrY)r6rrrr5:s  zBaseHandler.closecCs:|jd|_|j s|jr6|j|jt|jdS)z1Transmit headers to the client, via self._write()TN)rTrYrCrhrkrirlrR)r6rrrrmGs zBaseHandler.send_headerscCs|j}|dk ot|j|S)z@True if 'self.result' is an instance of 'self.wsgi_file_wrapper'N)rB isinstancer2)r6wrapperrrrrGPszBaseHandler.result_is_filecCs|jdjdkS)z,True if client can accept status and headersZSERVER_PROTOCOLzHTTP/0.9)r%upper)r6rrrrhVszBaseHandler.client_is_modernc CsJz>ddlm}|j}||d|d|d|j||jWdd}XdS)zLog the 'exc_info' tuple in the server log Subclasses may override to retarget the output or change its format. r)print_exceptionrrUN) tracebackrtr<traceback_limitflush)r6r`rtstderrrrr log_exception[s   zBaseHandler.log_exceptioncCs2|jtj|js.|j|j|j|_|jdS)z>Log current error, and send error output to client if possibleN) ryr r`rY error_outputr%r1r2r3)r6rrrr4kszBaseHandler.handle_errorcCs$||j|jddtj|jgS)aZWSGI mini-app to create error output By default, this just uses the 'error_status', 'error_headers', and 'error_body' attributes to generate an output page. It can be overridden in a subclass to dynamically generate diagnostics, choose an appropriate message for the user's preferred language, etc. Note, however, that it's not recommended from a security perspective to spit out diagnostics to any old user; ideally, you should have to do something special to enable diagnostic output, which is why we don't include any here! N) error_status error_headersr r` error_body)r6r%r1rrrrzss zBaseHandler.error_outputcCstdS)aOverride in subclass to buffer data for send to client It's okay if this method actually transmits the data; BaseHandler just separates write and flush operations for greater efficiency when the underlying system actually has such a distinction. N)rO)r6rKrrrriszBaseHandler._writecCstdS)zOverride in subclass to force sending of recent '_write()' calls It's okay if this method is a no-op (i.e., if '_write()' actually sends the data. N)rO)r6rrrrnszBaseHandler._flushcCstdS)z4Override in subclass to return suitable 'wsgi.input'N)rO)r6rrrr;szBaseHandler.get_stdincCstdS)z5Override in subclass to return suitable 'wsgi.errors'N)rO)r6rrrr<szBaseHandler.get_stderrcCstdS)z>Override in subclass to insert CGI variables in 'self.environ'N)rO)r6rrrr:szBaseHandler.add_cgi_vars)rr)r.r/)N)2__name__ __module__ __qualname____doc__r=r@rAr>rCrjrDr r8rrBrr]rvr{r|r}r\r2rYrRrQr7r0r3r?rSrTr1r^rkrIrHrJr5rmrGrhryr4rzrirnr;r<r:rrrrr^sV      c@sBeZdZdZdddZddZdd Zd d Zd d ZddZ dS)raqHandler that's just initialized with streams, environment, etc. This handler subclass is intended for synchronous HTTP/1.0 origin servers, and handles sending the entire response output, given the correct inputs. Usage:: handler = SimpleHandler( inp,out,err,env, multithread=False, multiprocess=True ) handler.run(app)TFcCs(||_||_||_||_||_||_dS)N)stdinstdoutrxbase_envr@rA)r6rrrxr% multithread multiprocessrrr__init__s zSimpleHandler.__init__cCs|jS)N)r)r6rrrr;szSimpleHandler.get_stdincCs|jS)N)rx)r6rrrr<szSimpleHandler.get_stderrcCs|jj|jdS)N)r%updater)r6rrrr:szSimpleHandler.add_cgi_varscCsb|jj|}|dks |t|kr$dSddlm}|dtx"||d}|sNP|jj|}qr8rrrrrr sc@s eZdZdZdZiZddZdS)r aCGI-based invocation with workaround for IIS path bug This handler should be used in preference to CGIHandler when deploying on Microsoft IIS without having set the config allowPathInfo option (IIS>=7) or metabase allowPathInfoForScriptMappings (IIS<7). Tc Csjt}|jdd}|jdd}|dj|drD|t|d|d<tj|tjjtj jtj |ddddS)Nrrr/FT)rr) r r(rrLr rr rrrrx)r6r%pathZscriptrrrr$s  zIISCGIHandler.__init__N)r~rrrr>r8rrrrrr s)rutilrrrrRrr r$r __all__rrr __contains__rrr rrr r r rrrrs*   <H2PKe[Ͳ KK __init__.pynu["""wsgiref -- a WSGI (PEP 3333) Reference Library Current Contents: * util -- Miscellaneous useful functions and wrappers * headers -- Manage response headers * handlers -- base classes for server/gateway implementations * simple_server -- a simple BaseHTTPServer that supports WSGI * validate -- validation wrapper that sits between an app and a server to detect errors in either To-Do: * cgi_gateway -- Run WSGI apps under CGI (pending a deployment standard) * cgi_wrapper -- Run CGI apps under WSGI * router -- a simple middleware component that handles URL traversal """ PKe[rutil.pynu[PKe[Ut9simple_server.pynu[PKe[X-nn *headers.pynu[PKe[g: R R 4Ehandlers.pynu[PKe[2em;;;; xvalidate.pynu[PKe[/qGYY(__pycache__/headers.cpython-36.opt-2.pycnu[PKe[ݮc\=\=)__pycache__/handlers.cpython-36.opt-1.pycnu[PKe[Ry#T"__pycache__/__init__.cpython-36.pycnu[PKe[Fy[;;"u%__pycache__/headers.cpython-36.pycnu[PKe[Ry)D__pycache__/__init__.cpython-36.opt-1.pycnu[PKe[0JJ)G__pycache__/util.cpython-36.pycnu[PKe[RuBB.[__pycache__/simple_server.cpython-36.opt-2.pycnu[PKe[,YӪ++)bm__pycache__/validate.cpython-36.opt-2.pycnu[PKe[JpKK.\__pycache__/simple_server.cpython-36.opt-1.pycnu[PKe[ oF}})__pycache__/__init__.cpython-36.opt-2.pycnu[PKe[_>"("()ۮ__pycache__/handlers.cpython-36.opt-2.pycnu[PKe[0JJ%V__pycache__/util.cpython-36.opt-1.pycnu[PKe[:ܸ(__pycache__/headers.cpython-36.opt-1.pycnu[PKe[E%%%O __pycache__/util.cpython-36.opt-2.pycnu[PKe[u 99#__pycache__/validate.cpython-36.pycnu[PKe[JpKK(R__pycache__/simple_server.cpython-36.pycnu[PKe[u 99)g__pycache__/validate.cpython-36.opt-1.pycnu[PKe[??#__pycache__/handlers.cpython-36.pycnu[PKe[Ͳ KK %__init__.pynu[PK