先畫一個請求http過程的簡單序列圖:python
bottle是一個支持wsgi的框架。當客戶端發起一個http請求時,http報文會先通過wsgi服務器處理成一個environ 字典,bottle拿到這個字典以後封裝成一個全局的request對象,用戶代碼拿到這個request封裝的信息,進行業務邏輯處理返回response對象,經wsgi服務器處理成http res報文返回給http客戶端.git
bottle的request是用來處理封裝environ字典的,這個字典是由wsgi服務器生成的。environ裏都有些什麼呢。一個簡單的辦法是跑一下 python -m wsgiref.simple_server,這時會打開默認瀏覽器,發起一個本地8000端口的http get請求,在頁面上會看到這一個get請求通過wsgi服務器處理以後生成的environ字典的內容,具體每個字段什麼意思能夠翻閱一個pep3333的這個章節https://www.python.org/dev/peps/pep-3333/#environ-variables,bottle的默認開發服務器也是wsgiref.simple_server。這裏聊一下GET,POST請求的處理過程。github
在剛纔打開的頁面裏,你能夠看到這個get請求的兩個關鍵key-value,一個是REQUEST_METHOD = 'GET', 另一個是QUERY_STRING = 'abc'(這裏不討論header裏的內容)。到源碼裏看一下bottle是如何處理這兩個keyvalue的。bottle是使用Bottle類的對象做爲wsgi協議函數的,因此Bottle的對象是callable的,Bottle會實現__call__方法。調用過程是Bottle.__call__ --> Bottle.wsgi --> Bottle._handle--> request.bind,使用environ字典初始化生成一個全局的request對象。定位到BaseRequest.GET方法就能夠看到,GET是query的一個別名。 query方法在self.environ增長一個key 'bottle.get',而後對QUERY_STRING進行了解析,通過裝飾器返回一個類字典的只讀對象供用戶使用。用戶代碼就能夠經過request.GET拿到GET請求的請求參數了。瀏覽器
POST請求的數據都是放在body裏進行行提交的,假如用戶提交的是表單,這裏關注environ中的四個key-value:服務器
REQUEST_METHOD = 'POST' CONTENT_LENGTH = '' CONTENT_TYPE = 'multipart/form-data; boundary=----WebKitFormBoundary5N9kIKpwXYrgi5jb' wsgi.input = <_io.BufferedReader name=636>
前三個不在多說。wsgi.input是wsgi服務器生成的一個文件對象經過environ傳給了bottle,bottle就是經過這個file對象讀取body中內容而後進行解析,查看BaseRequest.POST方法,在self._body 裏對environ['wsgi.input']進行處理返回一個BytesIO()對象,而後藉助cgi.FieldStorage類型解析body數據,返回表單鍵值對及文件對象。 能夠跑一下這個代碼https://github.com/kagxin/recipes/blob/master/bottle/wsgi_server.py 這個代碼使用,postman等客戶端工具發起GET和POST請求查看environ變量的內容。定位到demo_app裏到wsgiref.simple_server裏看一下demo_app 和 主函數就知道 python -m wsigref.simple_server爲何是剛纔的現象。simple_server是使用原來的HttpServer BaseHTTPRequestHandler,進行http協議的報文解析,在原有的解析內容中增長一些wsgi須要的key-value獲得了wsgi標準的environ。app