So you want to how web.py works?
In this article, I will walk through the web.py’s simple server, which is adopted from CherryPy.
Things you need to know
what is a web server?
In my words, a web server is simply a request/response manager.
It listens to comming requests from the client, and dispatches requests to the appropriate application based on the rules.
Then it gets responses back from the same application and send back to the client later.
There are a couple of things we need to go deeper.
- What is a request?
When a user clicks a link or post a form, a request has been created. How?
Well, the client will try to make a connection to the server based on the TCP/IP protocol. (sorry, I won’t go down the HTTP level at this article.)
When the connection has been established, it means that we can talk to the server.What?you can think that we get a bridge to the server. So we can send things to the server or get things from it.
We divide these requests into different groups based on their types, like POST, GET, HEAD and so on. It may be more clear when we talk about it from a different angle. Let’s see what makes a GET request.
Suppose we use wget to make a GET request.
And here is the request data:
GET / HTTP/1.1\r\n User-Agent: Wget/1.4 (darwin12.3.0)\r\n Accept: */*\r\n Host: douban.com\r\n Connection: Keep-Alive\r\n \r\n
- How does a request come to the server?
The request would be packaged in a packet via the internet protocol, being encoded into bits, then transformed into an optical signal, finally sent to the server with the help of an optical cable.
When the request packet arrives at the server, the packet would be unpackaged back to the request data.
Have a look at OSI_model.
- what are the rules?
The rules are defined by us. You can simply judge that if the request data contain ‘Host: douban.com’, then the server should dispatch the request to the A application.
- what is the response?
- when the A application gets the request, it would change it to a direct (in python words). And the application would do some stuff on it based on the request type, Host info and so on.
- When all these have been done, it would give a dict back. And we call this dict ‘a response’.
- The server gets the response and gives it back to the client.
- How do the server and application communicate with each other?
It may be strange that we ask such a question. Why?
Just imagine that you are the framework maker, and you write a func or a class to get a request or push back a response to the server,like Nginx.
And some other framework maker also writes some func(which may be so different from yours) to do the same things.
Things are going to be a mess!! We need a specification to guide people to write such code. And now we have some stuff like cgi, wsgi.
How do these things happen in webpy?
- CherryPyserver in general
In fact, webpy does not implement its own server. It just adopts another framework’s server, the crazy
From the image below, you can see that there are several classes which workes together to make a server.
From the above chat, we can tell that the CherryPyWSGIServer is inherited from HTTPServer.
And it uses the HTTPConnection class to represent comming requests,
and handles them by the ThreadPool class.
The WSGIGateWay1.0 is used to get the request environment information, and correct responses to the server according to the WSGI specification.
- In a little detail
In fact, when we develop a webpy app, we would write some code like these:
import web, cgi, settings import storage, search, db import simplejson urls = ( '^/$', 'do_index', ) app = web.application(urls, globals()) render = web.template.render(settings.TEMPLATE_FOLDER, base='base') class do_index: def GET(self): files = db.slave.select('ms_files', order='date desc', limit=5) return render.index(files) if __name__ == "__main__": app.run()
app.run() is executed, a web server has been set up, which is our
CherryPyWSGIServer an instance in default.
And the wsgi specification has defined rules about the talk convention between the server and the application. In my words, it would be like these:
Server: hey,App.When we talk to each other,you should give me a func. App: ok,Server.But what is a func? Server: well,the func should accpet a enviroment dict and a callback func. It is supposed to be like `func(env,callback)`. And what? The func result should be a yield like object. And the callback should be called like `callback(status,headers)`. App: Ok,you mean that i can get all the request info from the env dict? Server: Not all the request info.The wsgi has told me that i should put key-value pair like the path_info ,request_address,post_data etc in it. So you can always expect that the same things without worries. App: Hmm....So,after i have finished the request process,i should call the callback? Server: Yes!But don't forget to return a yield like object. App: well,it's easy.