1 class WSGIServer(simple_server.WSGIServer): 2 ????"""BaseHTTPServer that implements the Python WSGI protocol""" 3 ?4 ????request_queue_size = 10 5 ?6 ????def __init__(self, *args, ipv6=False, allow_reuse_address=True, **kwargs): 7 ????????if ipv6: 8 ????????????self.address_family = socket.AF_INET6 9 ????????self.allow_reuse_address = allow_reuse_address10 ????????super().__init__(*args, **kwargs)11 12 ????def handle_error(self, request, client_address):13 ????????if is_broken_pipe_error():14 ????????????logger.info("- Broken pipe from %s\n", client_address)15 ????????else:16 ????????????super().handle_error(request, client_address)17 18 class WSGIRequestHandler(simple_server.WSGIRequestHandler):19 ????protocol_version = ‘HTTP/1.1‘20 21 ????def address_string(self):22 ????????# Short-circuit parent method to not call socket.getfqdn23 ????????return self.client_address[0]24 25 ????def log_message(self, format, *args):26 ????????extra = {27 ????????????‘request‘: self.request,28 ????????????‘server_time‘: self.log_date_time_string(),29 ????????}30 ????????if args[1][0] == ‘4‘:31 ????????????# 0x16 = Handshake, 0x03 = SSL 3.0 or TLS 1.x32 ????????????if args[0].startswith(‘\x16\x03‘):33 ????????????????extra[‘status_code‘] = 50034 ????????????????logger.error(35 ????????????????????"You‘re accessing the development server over HTTPS, but "36 ????????????????????"it only supports HTTP.\n", extra=extra,37 ????????????????)38 ????????????????return39 40 ????????if args[1].isdigit() and len(args[1]) == 3:41 ????????????status_code = int(args[1])42 ????????????extra[‘status_code‘] = status_code43 44 ????????????if status_code >= 500:45 ????????????????level = logger.error46 ????????????elif status_code >= 400:47 ????????????????level = logger.warning48 ????????????else:49 ????????????????level = logger.info50 ????????else:51 ????????????level = logger.info52 53 ????????level(format, *args, extra=extra)54 55 ????def get_environ(self):56 ????????# Strip all headers with underscores in the name before constructing57 ????????# the WSGI environ. This prevents header-spoofing based on ambiguity58 ????????# between underscores and dashes both normalized to underscores in WSGI59 ????????# env vars. Nginx and Apache 2.4+ both do this as well.60 ????????for k in self.headers:61 ????????????if ‘_‘ in k:62 ????????????????del self.headers[k]63 64 ????????return super().get_environ()65 66 ????def handle(self):67 ????????self.close_connection = True68 ????????self.handle_one_request()69 ????????while not self.close_connection:70 ????????????self.handle_one_request()71 ????????try:72 ????????????self.connection.shutdown(socket.SHUT_WR)73 ????????except (socket.error, AttributeError):74 ????????????pass75 76 ????def handle_one_request(self):77 ????????"""Copy of WSGIRequestHandler.handle() but with different ServerHandler"""78 ????????self.raw_requestline = self.rfile.readline(65537)79 ????????if len(self.raw_requestline) > 65536:80 ????????????self.requestline = ‘‘81 ????????????self.request_version = ‘‘82 ????????????self.command = ‘‘83 ????????????self.send_error(414)84 ????????????return85 86 ????????if not self.parse_request(): ?# An error code has been sent, just exit87 ????????????return88 89 ????????handler = ServerHandler(90 ????????????self.rfile, self.wfile, self.get_stderr(), self.get_environ()91 ????????)92 ????????handler.request_handler = self ?????# backpointer for logging & connection closing93 ????????handler.run(self.server.get_app())
WSGIServer的父类是wsgiref.simple_server.WSGIServer, wsgiref.simple_server.WSGIServer的父类是http.server.HTTPServer,http.server.HTTPServer的父类是socketserver.TCPServer;
WSGIRequestHandler的父类是wsgiref.simple_server.WSGIRequestHandler,wsgiref.simple_server.WSGIRequestHandler的父类是http.server.BaseHTTPRequestHandler,
http.server.BaseHTTPRequestHandler的父类是socketserver.StreamRequestHandler,socketserver.StreamRequestHandler的父类是socketserver.BaseRequestHandler
def run(addr, port, wsgi_handler, ipv6=False, threading=False, server_cls=WSGIServer): ???server_address = (addr, port) ???if threading: ???????httpd_cls = type(‘WSGIServer‘, (socketserver.ThreadingMixIn, server_cls), {}) ???else: ???????httpd_cls = server_cls ???httpd = httpd_cls(server_address, WSGIRequestHandler, ipv6=ipv6) ?实例化WSGIserver ???if threading: ???????# ThreadingMixIn.daemon_threads indicates how threads will behave on an ???????# abrupt shutdown; like quitting the server by the user or restarting ???????# by the auto-reloader. True means the server will not wait for thread ???????# termination before it quits. This will make auto-reloader faster ???????# and will prevent the need to kill the server manually if a thread ???????# isn‘t terminating correctly. ???????httpd.daemon_threads = True ???httpd.set_app(wsgi_handler) ???httpd.serve_forever() ?#这里调用TCPserver的父类BaseServer的serve_forever方法
在socketserver.BaseServer.serve_forever中
1 ????def serve_forever(self, poll_interval=0.5): 2 ????????"""Handle one request at a time until shutdown. 3 ?4 ????????Polls for shutdown every poll_interval seconds. Ignores 5 ????????self.timeout. If you need to do periodic tasks, do them in 6 ????????another thread. 7 ????????""" 8 ????????self.__is_shut_down.clear() 9 ????????try:10 ????????????# XXX: Consider using another file descriptor or connecting to the11 ????????????# socket to wake this up instead of polling. Polling reduces our12 ????????????# responsiveness to a shutdown request and wastes cpu at all other13 ????????????# times.14 ????????????with _ServerSelector() as selector:15 ????????????????selector.register(self, selectors.EVENT_READ)16 17 ????????????????while not self.__shutdown_request:18 ????????????????????ready = selector.select(poll_interval)19 ????????????????????# bpo-35017: shutdown() called during select(), exit immediately.20 ????????????????????if self.__shutdown_request:21 ????????????????????????break22 ????????????????????if ready:23 ????????????????????????self._handle_request_noblock() ?在这里调用process_request方法24 25 ????????????????????self.service_actions()26 ????????finally:27 ????????????self.__shutdown_request = False28 ????????????self.__is_shut_down.set()
在process_request方法中调用finish_request方法去实例化WSGIRequestHandler
1 ????def process_request(self, request, client_address):2 ????????"""Call finish_request.3 4 ????????Overridden by ForkingMixIn and ThreadingMixIn.5 6 ????????"""7 ????????self.finish_request(request, client_address)8 ????????self.shutdown_request(request)
在finish_request中实例化WSGIRequestHandler
???def finish_request(self, request, client_address): ???????"""Finish one request by instantiating RequestHandlerClass.""" ???????self.RequestHandlerClass(request, client_address, self) ?#这个self是WSGIserver实例化的对象
class BaseRequestHandler: ?#实例化WSGIRequestHandler必须先初始化BaseRequestHandler类 ???"""Base class for request handler classes. ???This class is instantiated for each request to be handled. ?The ???constructor sets the instance variables request, client_address ???and server, and then calls the handle() method. ?To implement a ???specific service, all you need to do is to derive a class which ???defines a handle() method. ???The handle() method can find the request as self.request, the ???client address as self.client_address, and the server (in case it ???needs access to per-server information) as self.server. ?Since a ???separate instance is created for each request, the handle() method ???can define other arbitrary instance variables. ???""" ???def __init__(self, request, client_address, server): ???????self.request = request ???????self.client_address = client_address ???????self.server = server ???????self.setup() ???????try: ???????????self.handle() ?#这个类没有实现handle方法,所以需要我们自己去实现 ???????finally: ???????????self.finish() ???def setup(self): ???????pass ???def handle(self): ???????pass ???def finish(self): ???????passclass StreamRequestHandler(BaseRequestHandler): ???"""Define self.rfile and self.wfile for stream sockets.""" ???# Default buffer sizes for rfile, wfile. ???# We default rfile to buffered because otherwise it could be ???# really slow for large data (a getc() call per byte); we make ???# wfile unbuffered because (a) often after a write() we want to ???# read and we need to flush the line; (b) big writes to unbuffered ???# files are typically optimized by stdio even when big reads ???# aren‘t. ???rbufsize = -1 ???wbufsize = 0 ???# A timeout to apply to the request socket, if not None. ???timeout = None ???# Disable nagle algorithm for this socket, if True. ???# Use only when wbufsize != 0, to avoid small packets. ???disable_nagle_algorithm = False ???def setup(self): ???????self.connection = self.request ???????if self.timeout is not None: ???????????self.connection.settimeout(self.timeout) ???????if self.disable_nagle_algorithm: ???????????self.connection.setsockopt(socket.IPPROTO_TCP, ??????????????????????????????????????socket.TCP_NODELAY, True) ???????self.rfile = self.connection.makefile(‘rb‘, self.rbufsize) ???????if self.wbufsize == 0: ???????????self.wfile = _SocketWriter(self.connection) ???????else: ???????????self.wfile = self.connection.makefile(‘wb‘, self.wbufsize) ???def finish(self): ???????if not self.wfile.closed: ???????????try: ???????????????self.wfile.flush() ???????????except socket.error: ???????????????# A final socket error may have occurred here, such as ???????????????# the local error ECONNABORTED. ???????????????pass ???????self.wfile.close() ???????self.rfile.close()
在handle方法中
1 class WSGIRequestHandler(BaseHTTPRequestHandler): 2 ?3 ????server_version = "WSGIServer/" + __version__ 4 ?5 ????def get_environ(self): 6 ????????env = self.server.base_environ.copy() 7 ????????env[‘SERVER_PROTOCOL‘] = self.request_version 8 ????????env[‘SERVER_SOFTWARE‘] = self.server_version 9 ????????env[‘REQUEST_METHOD‘] = self.command10 ????????if ‘?‘ in self.path:11 ????????????path,query = self.path.split(‘?‘,1)12 ????????else:13 ????????????path,query = self.path,‘‘14 15 ????????env[‘PATH_INFO‘] = urllib.parse.unquote(path, ‘iso-8859-1‘)16 ????????env[‘QUERY_STRING‘] = query17 18 ????????host = self.address_string()19 ????????if host != self.client_address[0]:20 ????????????env[‘REMOTE_HOST‘] = host21 ????????env[‘REMOTE_ADDR‘] = self.client_address[0]22 23 ????????if self.headers.get(‘content-type‘) is None:24 ????????????env[‘CONTENT_TYPE‘] = self.headers.get_content_type()25 ????????else:26 ????????????env[‘CONTENT_TYPE‘] = self.headers[‘content-type‘]27 28 ????????length = self.headers.get(‘content-length‘)29 ????????if length:30 ????????????env[‘CONTENT_LENGTH‘] = length31 32 ????????for k, v in self.headers.items():33 ????????????k=k.replace(‘-‘,‘_‘).upper(); v=v.strip()34 ????????????if k in env:35 ????????????????continue ???????????????????# skip content length, type,etc.36 ????????????if ‘HTTP_‘+k in env:37 ????????????????env[‘HTTP_‘+k] += ‘,‘+v ????# comma-separate multiple headers38 ????????????else:39 ????????????????env[‘HTTP_‘+k] = v40 ????????return env41 42 ????def get_stderr(self):43 ????????return sys.stderr44 45 ????def handle(self):46 ????????"""Handle a single HTTP request"""47 48 ????????self.raw_requestline = self.rfile.readline(65537) ?#读取游览器发来的请求包文起始49 ????????if len(self.raw_requestline) > 65536: ?#判断数据长度是否大于6553650 ????????????self.requestline = ‘‘51 ????????????self.request_version = ‘‘52 ????????????self.command = ‘‘53 ????????????self.send_error(414) ??#发送414错误54 ????????????return55 56 ????????if not self.parse_request(): # An error code has been sent, just exit57 ????????????return58 59 ????????handler = ServerHandler(60 ????????????self.rfile, self.wfile, self.get_stderr(), self.get_environ()61 ????????) ?#rfile相当于socket中的recv,wfile相当于socket中的send, ??get_atderr是系统的标准错误输出句柄, get_environ是先将下划线开头的头部字段删除,再调用父类的get_envrion方法将请求的头部字段加上HTTP_,再添加一些公共字段62 ????????handler.request_handler = self ?????# backpointer for logging63 ????????handler.run(self.server.get_app())
在run中
1 ????def run(self, application): 2 ????????"""Invoke the application""" 3 ????????# Note to self: don‘t move the close()! ?Asynchronous servers shouldn‘t 4 ????????# call close() from finish_response(), so if you close() anywhere but 5 ????????# the double-error branch here, you‘ll break asynchronous servers by 6 ????????# prematurely closing. ?Async servers must return from ‘run()‘ without 7 ????????# closing if there might still be output to iterate over. 8 ????????try: 9 ????????????self.setup_environ() ?#设置环境,将系统环境拷贝,然后将传入的环境变量扩展进该环境内同时增加一些WSGI通用环境10 ????????????self.result = application(self.environ, self.start_response)#设置完环境后开始执行我们传入的handler对象11 ????????????self.finish_response()12 ????????except:13 ????????????try:14 ????????????????self.handle_error()15 ????????????except:16 ????????????????# If we get an error handling an error, just give up already!17 ????????????????self.close()18 ????????????????raise ??# ...and let the actual server figure it out.
也就是执行以下代码
1 class WSGIHandler(base.BaseHandler): 2 ????request_class = WSGIRequest 3 ?4 ????def __init__(self, *args, **kwargs): 5 ????????super(WSGIHandler, self).__init__(*args, **kwargs) 6 ????????self.load_middleware() 7 ?8 ????def __call__(self, environ, start_response): 9 ????????set_script_prefix(get_script_name(environ))10 ????????signals.request_started.send(sender=self.__class__, environ=environ)11 ????????request = self.request_class(environ)12 ????????response = self.get_response(request)13 ????????response._handler_class = self.__class__14 15 ????????status = ‘%d %s‘ % (response.status_code, response.reason_phrase)16 ????????response_headers = [(str(k), str(v)) for k, v in response.items()]17 ????????for c in response.cookies.values():18 ????????????response_headers.append((str(‘Set-Cookie‘), str(c.output(header=‘‘))))19 ????????start_response(force_str(status), response_headers)20 ????????if getattr(response, ‘file_to_stream‘, None) is not None and environ.get(‘wsgi.file_wrapper‘):21 ????????????response = environ[‘wsgi.file_wrapper‘](response.file_to_stream)22 ????????return response
django的web server的源代码流程
原文地址:https://www.cnblogs.com/arrow-kejin/p/10361341.html