Home > Article > Backend Development > Bottle source code reading notes (1): WSGI
Bottle is a Python web framework. The entire framework has only one file, less than 4k lines of code, and no dependencies other than the Python standard library. However, it includes common functions of web frameworks such as routing, templates, and plug-ins. There is no better time than reading the Bottle source code to understand what a web framework is and how it works. Since Bottle is a framework that supports WSGI, before reading the source code, let's first understand what WSGI is.
Note: The Bottle version used in this article is 0.12.13.
##General web servers can only handle static pages. If dynamic content is involved, the server needs to interact with server languages such as Java/Python/Ruby and hand over the content to them for processing. Since most web servers are written in C, they cannot directly execute the server language, so a bridge is needed between the two (in practical applications, an application server is usually added between the web server and the WSGI application to support WSGI) . In Python, WSGI is such a bridge. The implementation of WSGI is divided into two parts, one is the server and the other is the application. Let’s take a look at what each of them looks like and how the two work together.
1 class Server: 2 3 def __init__(self, server_address): 4 self.server_address = server_address 5 6 def set_app(self, application): 7 self.app = application 8 9 def serve_forever(self):10 while True:11 # socket.accept()12 if request_comein():13 self.handle_request()14 15 def handle_request(self):16 request_data = self.get_request()17 self.parse_request(request_data)18 environ = self.get_environ()19 result = self.application(environ, self.start_response)20 self.send_response(result)21 22 def start_response(self, status, headers, exc_info):23 pass24 25 def get_environ(self):26 pass27 28 def get_request(self):29 pass30 31 def parse_request(self, text):32 pass33 34 def send_response(self, message):35 pass36 37 38 def make_server(host, port, app, server=Server):39 server = server((host, port))40 server.set_app(app)41 return server42 43 def simple_app(environ, start_response):44 status = '200 OK'45 response_headers = [('Content-type', 'text/plain')]46 start_response(status, response_headers)47 return 'Hello World!'48 49 if __name__ == '__main__':50 server = make_server('localhost', 8080, simple_app)51 server.serve_forever()
Due to space limitations, this server model omits many details. If you want a simple and operational WSGI server, you can refer to Let's Build A Web here Server.Part 2.
After receiving the request, the server parses the information in the request message and saves the result in a dictionary named environ. Then the application application (environ, start_response) is called with environ and the start_response function that processes header information as parameters. Finally, the results of the application are composed into a new response and sent back to the client.
On the application side, a WSGI application is a callable object. It can be a function, method, class, or an instance with a __call__ method. The above application is a function.
When various servers and applications/frameworks are developed in accordance with WSGI standards, we can freely combine different servers and frameworks according to our needs.
Bottle's simplest applicationAfter briefly understanding WSGI, we return to Bottle to observe what a Bottle application looks like, how to run it, and how to follow our What is the difference between models.
1 from bottle import Bottle, run2 3 app = Bottle()4 5 @app.route('/hello')6 def hello():7 return 'Hello World!'8 9 run(app, host='localhost', port=8080, server='wsgiref')
Now run this program and use the browser to access the address 'localhost:8080/hello' and you will see 'Hello World!'.
#1. Unlike the above applications, the Bottle application is an instance. According to WSGI regulations, the Bottle object must implement the __call__ method:
1 def __call__(self, environ, start_response):2 ''' Each instance of :class:'Bottle' is a WSGI application. '''3 return self.wsgi(environ, start_response)
So this Bottle.wsgi method is the entrance for the server to call the Bottle application, and it is also the entrance for us to read Entry to the source code.
2. @app.route() This decorator binds a function to a URL. When we access 'localhost:8080/hello', the hello function will be called.
3. Bottle's default server is wsgiref (a simple implementation of WSGI in the Python standard library). Of course, Bottle has also written adapters for many servers. You only need to change the value of server, and the run() function will find the corresponding adapter based on the name of the server. No need to write additional code.
run function and adapter part code:
1 def run(app=None, server='wsgiref', host='127.0.0.1', port=8080, 2 interval=1, reloader=False, quiet=False, plugins=None, 3 debug=None, **kargs): 4 if server in server_names: 5 server = server_names.get(server) 6 if isinstance(server, basestring): 7 server = load(server) 8 if isinstance(server, type): 9 server = server(host=host, port=port, **kargs)10 if not isinstance(server, ServerAdapter):11 raise ValueError("Unknown or unsupported server: %r" % server)12 ...13 server.run(app)14 15 class MeinheldServer(ServerAdapter):16 def run(self, handler):17 from meinheld import server18 server.listen((self.host, self.port))19 server.run(handler)Finally
In this article, we A brief introduction to how servers and applications interact under the WSGI standard. In the next article, we will continue to focus on this simplest application and talk about the routing functions related to @app.route().
The above is the detailed content of Bottle source code reading notes (1): WSGI. For more information, please follow other related articles on the PHP Chinese website!