WSGI接口
了解了HTTP协议和HTML文档,我们其实就明白了一个Web应用的本质就是:
1、浏览器发送一个HTTP请求;
2、服务器收到请求,生成一个HTML文档;
3、服务器把HTML文档作为HTTP响应的Body发送给浏览器;
4、浏览器收到HTTP响应,从HTTP Body取出HTML文档并显示。
所以,最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回。Apache、Nginx、Lighttpd等这些常见的静态服务器就是干这件事情的。
如果要动态生成HTML,就需要把上述步骤自己来实现。不过,接受HTTP请求、解析HTTP请求、发送HTTP响应都是苦力活,如果我们自己来写这些底层代码,还没开始写动态HTML呢,就得花个把月去读HTTP规范。
实际生产中,python 程序是放在服务器的 http server(比如 apache, nginx 等)上的。现在的问题是服务器程序怎么把接受到的请求传递给 python 呢,怎么在网络的数据流和 python 的结构体之间转换呢?这就是 wsgi 做的事情:一套关于程序端和服务器端的规范,或者说统一的接口。
正确的做法是底层代码由专门的服务器软件实现,我们用Python专注于生成HTML文档。因为我们不希望接触到TCP连接、HTTP原始请求和响应格式,所以,需要一个统一的接口,让我们专心用Python编写Web业务。
这个接口就是WSGI:Web Server Gateway Interface。
WSGI接口定义非常简单,它只要求Web开发者实现一个函数,就可以响应HTTP请求。
WSGI(Web Server Gateway Interface) 的任务就是把上面的数据在 http server 和 python 程序之间简单友好地传递。它是一个标准,被定义在PEP 333。需要 http server 和 python 程序都要遵守一定的规范,实现这个标准的约定内容,才能正常工作。
应用程序端
WSGI 规定每个 python 程序(Application)必须是一个可调用的对象(实现了__call__函数的方法或者类),接受两个参数environ(WSGI 的环境信息) 和start_response(开始响应请求的函数),并且返回 iterable。几点说明:
1、environ和start_response由 http server 提供并实现
2、environ变量是包含了环境信息的字典
3、Application内部在返回前调用start_response
4、start_response也是一个 callable,接受两个必须的参数,status(HTTP状态)和response_headers(响应消息的头)
5、可调用对象要返回一个值,这个值是可迭代的。
说了这么多的概念,再来看看代码的实现:
服务器程序端
上面已经说过,标准要能够确切地实行,必须要求程序端和服务器端共同遵守。上面提到,envrion和start_response都是服务器端提供的。下面就看看,服务器端要履行的义务。
1、准备environ参数
2、定义start_response函数
3、调用程序端的可调用对象
再来看看代码的实现:
Django与WSGI
根据Python的惯例,Django不是一个完整的Web后端框架,它只负责开发WSGI应用程序 ,在生产环境中Django应用应当与一个WSGI服务器配套,由WSGI服务器负责网络通讯部分。
WSGI,全称Web Server Gateway Interface,或者 Python Web Server Gateway Interface ,是为 Python 语言定义的Web服务器和Web应用程序之间的一种简单而通用的接口。
WSGI将Web服务分成两个部分:服务器和应用程序。WGSI服务器只负责与网络相关的两件事:接收浏览器的 HTTP请求、向浏览器发送HTTP应答;而对HTTP请求的具体处理逻辑,则通过调用WSGI应用程序进行。
实现一个WSGI应用,只需要满足3个要求:
是可调用的,比如是一个函数,或者是一个可调用类(具有__call__方法)的实例
WSGI应用应当返回一个可迭代(iterable)的值,比如字符串列表
WSGI应用在返回之前,应当调用WSGI服务器传入的start_response函数发送状态码和HTTP报文头