前面说到通过新建Handler类来处理请求
默认情况下Handler类为WSGIRequestHandler
class WSGIRequestHandler(BaseHTTPRequestHandler): server_version = "WSGIServer/" + __version__ def get_environ(self): env = self.server.base_environ.copy() env['SERVER_PROTOCOL'] = self.request_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.unquote(path) 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.typeheader is None: env['CONTENT_TYPE'] = self.headers.type else: env['CONTENT_TYPE'] = self.headers.typeheader length = self.headers.getheader('content-length') if length: env['CONTENT_LENGTH'] = length for h in self.headers.headers: k,v = h.split(':',1) 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() 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())
WSGIRequestHandler继承自BaseHTTPServer模块的BaseHTTPRequestHandler
BaseHTTPRequestHandler继承自SocketServer模块的StreamRequestHandler
StreamRequestHandler继承自同一模块的BaseRequestHandler
class BaseRequestHandler: def __init__(self, request, client_address, server): self.request = request self.client_address = client_address self.server = server self.setup() try: self.handle() finally: self.finish() def setup(self): pass def handle(self): pass def finish(self): pass
在BaseRequestHandler的__init__方法中, 发现新建Handler对象时, 会调用self.handler处理请求, 处理完后调用self.finish。
沿着继承链发现WSGIRequestHandler和BaseHTTPRequestHandler都定义了hanlder方法, WSGIRequestHandler中的定义优先
class WSGIRequestHandler(BaseHTTPRequestHandler): server_version = "WSGIServer/" + __version__ def handle(self): """Handle a single HTTP request""" self.raw_requestline = self.rfile.readline() 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())
在handler方法中, 新建了ServerHandler类实例, 再调用实例的run方法
再次建立ServerHandler类实例的原因是为了符合WSGI接口. 前面运行的程序的作用是建立了服务器, 服务器在指定端口监听, 接收来自客户端的连接, 读取客户端的请求. 现在开始处理客户端的请求, 但是处理的方式有很多种, 你也可以自己写一个程序解析客户端的请求, 生成响应并返回给客户端.
但是符合WSGI接口的处理方式是: 底层程序解析好客户端的请求并生成environ字典, 这个字典表示客户端请求的各种信息. 另外定义start_response函数, 该函数用于向客户端发送响应起始行和响应头. 底层程序将environ, start_response传给编写好的app, app运行生成响应. 这就是符合WSGI接口的响应方式, 下面的程序可以清楚的显示.
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
在handler的run方法中, 首先调用setup_environ创建了self.environ。
紧接着的语句: self.result = application(self.environ, self.start_response)说明定义的app必须是一个可调用对象,调用app的时候传入了self.environ, self.start_response两个参数。调用app返回的结果存放在self.result中,在finish_response调用中,将self.result返回给用户,至此用户的请求响应完毕