defsimple_app(environ, start_response): """Simplest possible application object""" status = '200 OK' response_headers = [('Content-type', 'text/plain')] start_response(status, response_headers) return [HELLO_WORLD]
classAppClass: """Produce the same output, but using a class (Note: 'AppClass' is the "application" here, so calling it returns an instance of 'AppClass', which is then the iterable return value of the "application callable" as required by the spec. If we wanted to use *instances* of 'AppClass' as application objects instead, we would have to implement a '__call__' method, which would be invoked to execute the application, and we would need to create an instance for use by the server or gateway. """
def__init__(self, environ, start_response): self.environ = environ self.start = start_response
# server 函数入口 defrun_with_cgi(application): # 构建environ environ = {k: unicode_to_wsgi(v) for k,v in os.environ.items()} environ['wsgi.input'] = sys.stdin.buffer environ['wsgi.errors'] = sys.stderr environ['wsgi.version'] = (1, 0) environ['wsgi.multithread'] = False environ['wsgi.multiprocess'] = True environ['wsgi.run_once'] = True
if environ.get('HTTPS', 'off') in ('on', '1'): environ['wsgi.url_scheme'] = 'https' else: environ['wsgi.url_scheme'] = 'http'
headers_set = [] headers_sent = []
defwrite(data): out = sys.stdout.buffer
ifnot headers_set: raise AssertionError("write() before start_response()")
elifnot headers_sent: # Before the first output, send the stored headers status, response_headers = headers_sent[:] = headers_set out.write(wsgi_to_bytes('Status: %s\r\n' % status)) for header in response_headers: out.write(wsgi_to_bytes('%s: %s\r\n' % header)) out.write(wsgi_to_bytes('\r\n'))
out.write(data) out.flush() # 构建start_response defstart_response(status, response_headers, exc_info=None): if exc_info: try: if headers_sent: # Re-raise original exception if headers sent raise exc_info[1].with_traceback(exc_info[2]) finally: exc_info = None# avoid dangling circular ref elif headers_set: raise AssertionError("Headers already set!")
headers_set[:] = [status, response_headers]
# Note: error checking on the headers should happen here, # *after* the headers are set. That way, if an error # occurs, start_response can only be re-called with # exc_info set.
return write # 调用Application result = application(environ, start_response) try: for data in result: if data: # don't send headers until body appears write(data) ifnot headers_sent: write('') # send headers now if body was empty finally: ifhasattr(result, 'close'): result.close()
"""Transform iterated output to piglatin, if it's okay to do so Note that the "okayness" can change until the application yields its first non-empty bytestring, so 'transform_ok' has to be a mutable truth value. """
# Reset ok flag, in case this is a repeat call del transform_ok[:]
for name, value in response_headers: if name.lower() == 'content-type'and value == 'text/plain': transform_ok.append(True) # Strip content-length if present, else it'll be wrong response_headers = [(name, value) for name, value in response_headers if name.lower() != 'content-length' ] break
# server if __name__ == '__main__': from wsgiref.simple_server import make_server application = IPBlacklistMiddleware(application) server = make_server('0.0.0.0', 8080, application) server.serve_forever()
try: run_simple(host, port, self, **options) finally: # reset the first request information if the development server # reset normally. This makes it possible to restart the server # without reloader and that stuff from an interactive shell. self._got_first_request = False
classFlask(Scaffold): ... def__call__(self, environ, start_response): """The WSGI server calls the Flask application object as the WSGI application. This calls :meth:`wsgi_app` which can be wrapped to applying middleware.""" return self.wsgi_app(environ, start_response)
defdispatch_request(self): """Does the request dispatching. Matches the URL and returns the return value of the view or error handler. This does not have to be a response object. In order to convert the return value to a proper response object, call :func:`make_response`. .. versionchanged:: 0.7 This no longer does the exception handling, this code was moved to the new :meth:`full_dispatch_request`. """ req = _request_ctx_stack.top.request if req.routing_exception isnotNone: self.raise_routing_exception(req) rule = req.url_rule # if we provide automatic options for this URL and the # request came with the OPTIONS method, reply automatically if ( getattr(rule, "provide_automatic_options", False) and req.method == "OPTIONS" ): return self.make_default_options_response() # otherwise dispatch to the handler for that endpoint return self.view_functions[rule.endpoint](**req.view_args)