目录

  • 目录
  • WSGI 简介
  • 为什么需要 WSGI 这个规范
  • WSGI 如何工作
    • WSGI的角色
    • Server 如何调用 Application
    • application 的两个参数
    • application 对象的返回值
    • 再谈Server如何调用application
  • WSGI 中间件
  • WSGI的实现和部署
  • 参考资料

WSGI 简介

WSGI(Web Server Gateway Interface) Web 服务器网关接口。从名称上来看WSGI就是一个网关,作用就是在协议之间进行转换。具体而言,WSGI 是一个规范,它遵循这种规范将一个Web组件抽象成三个部件层:Web Server + Web Middleware + Web Application。除此之外,它还定义了 Web Server 如何与 Python 写的 Web Application进行交互,使得 Python 写的 Web Application 可以和 Web Server 能够对接起来。现在一般会使用 Apache + wsgi_mod 的组合来实现Web Services。

为什么需要 WSGI 这个规范?

在 Web Services 处理方案中,有一个方案是目前应用最广泛的:
- 部署一个 Web Server(Apache) 专门用来处理 HTTP 协议层面相关的事情,EG. 如何在一个 HOST 上提供多个不同的虚拟主机:单IP多域名,单IP多端口等。

  • 部署一个用各种语言开发( Java, PHP, Python, Ruby等 )出来的 Application,这个 Application 会接收从 Web Server 上传递过来的 Client Request,处理请求完成后,再 Return 给 Web Server,最后由 Web Server Response 给 Client 。

那么,Web Server 和 Application 之间就就需要解决交互的问题。而为了解决这个问题,就定义 Web Server 和 Application 之间交互的规范。EG. Java 的 Servlet,Python 的 WSGI 等。定义这些规范的目的是为了定义统一的标准,提升程序的可移植性。

WSGI 如何工作?

WSGI 相当于 Web Server 和 Python Application 之间的桥梁。其存在的目的有两个:
1. 让 Web Server 知道如何调用 Python Application,并且将 Client Request 传递给 Application。
2. 让 Python Application 能理解 Client Request 并执行对应操作,以及将执行结果返回给 Web Server,最终响应到Client。

当处理一个 WSGI 请求时,Server 为 Application 提供 上下文信息 和一个 回调函数, Application 处理完请求之后,使用 Server 所提供的回调函数返回相对应请求的响应。

WSGI的角色

  • Web Server end(也称之为 Server 或 Gateway)
  • Web Application end(也称之为 Application 或 Framework),WSGI Application End 的规范一般是通过具体的框架(Django/Web.py)来实现的。

Server 首先会接收到User Request,然后根据规范调用 Application 并将预处理过的 Request 传递给 Application。由 Application 处理完 Request 之后将结果返回给 Web Server,最后 Web Server 将结果封装成 HTTP Response 并响应给 User。 (重要的事情,已经是第三遍了)

Server 如何调用 Application?

每个 Application 的入口都只有一个,就是说 Server 只能通过这一个入口调用 Application 并将 Client Request 传递给 Application。所以 Server 需要知道如何找到这一个 Application 的入口:

这是由一个 Python Module(一般由框架提供) 决定的,并且这个 Python Module 中需要包含由一个名称为 application 的可调用对象(该对象无论是 Function/Class 都可以)。而这一个可调用的 application 对象就是 Application 的唯一入口了。WSGI 定义了 application 对象的样式:

def application(environ, start_response):    #该函数需要提供两个形参pass

EXAMPLE:假设 Application 的入口文件为 /var/www/index.py ,那么首先我们需要在 Server 中配置好这一路径(让 Server 能够找到这个 Python Module),然后在 index.py 这个文件中写入下面的 Application 入口实现代码:

#使用 web.py 框架时的样式
import web   #由 web.py 框架提供了可调用对象 application() 作为 Application 的入口urls = ('/.*', 'hello',
)class hello(object):def GET(self):return "Hello, world."app = web.application(urls, globals()).wsgifunc()#Server 会根据配置找到这个文件,然后调用这个 application 对象
#因为 application 对象是唯一的入口,所以不管 Client Request 的路径和数据是什么, Server 都会调用这个对象来处理,具体的 Client Request 的处理过程交由 application 对象来完成,框架的使用者一般不需要关心这个对象内部是如何工作的,框架已经对其做了封装。

application 的两个参数

Application 处理 Request 和 Response 都与 application 对象的两个参数(environ、start_response)有关。

  • environ:其引用指向一个Dict类型对象,一般存放了下列类型的数据

    • 所有和 Client 相关的上下文 Informations,这样 application 对象就可以通过 environ 参数知道 Client Request 希望访问或操作的资源是什么,还能够知道 Requuest Client 中携带了什么数据等等。
    • 一些 CGI(通用网管接口规范)中定义的环境变量
    • 至少包含了其他7个 WSGI 规范所定义的环境变量
    • 还可能包含了一些OS的环境变量以及 Web Server 相关的环境变量

CGI 规范中要求的数据成员

REQUEST_METHOD: 请求方法,String类型,'GET', 'POST','PUT','DELETE'等
SCRIPT_NAME: HTTP请求的URL_Path中的用于查找到application对象的部分(EG. Web服务器可以根据URL_Path的一部分来决定请求由哪个虚拟主机来处理这个请求)
PATH_INFO: HTTP请求的URL_Path中剩余的部分,也就是application对象要处理的部分
QUERY_STRING: HTTP请求中的查询字符串,URL中'?'后面紧跟的内容
CONTENT_TYPE: HTTP headers头部中的 content-type 内容
CONTENT_LENGTH:HTTP headers中的 content-length 内容
SERVER_NAME 和 SERVER_PORT: 服务器主机名和端口,这两个值和前面的SCRIPT_NAME, PATH_INFO拼起来可以得到完整的URL路径 EG. http://www.jmilkfan.com:80/virtual/private
SERVER_PROTOCOL: HTTP协议版本,HTTP/1.0或者HTTP/1.1
HTTP_: 和HTTP请求中的headers对应

WSGI 规范中要求的成员

wsgi.version: 表示WSGI版本,一个元组(1, 0),表示版本1.0
wsgi.url_scheme: http或者https
wsgi.input: 一个类文件的输入流,application可以通过这个获取HTTP request body
wsgi.errors: 一个输出流,当 Application 出错时,可以将错误信息写入这里
wsgi.multithread: 当application对象可能被多个线程同时调用时,这个值需要为True
wsgi.multiprocess: 当application对象可能被多个进程同时调用时,这个值需要为True
wsgi.run_once: 当server期望application对象在进程的生命周期内只被调用一次时,该值为True
  • start_resposne :start_resposne的引用指向一个回调函数(在 Server 中定义),这个回调函数会接受两个必选参数(status,resposne_headers)和一个可选参数(exc_info)。EG. start_resposne(status,resposne_headers,exc_info=None)
    当 application 对象根据 environ 参数的 Info 执行完 Client Request 的业务逻辑之后,需要返回结果给 Server 。而且 HTTP Response 需要包含 status、headers、body 等元素,所以在 application 对象将 body 作为返回值 return 之前,需要先调用 start_response()将 status、headers 先返回给 Server,同时也是告诉Server,application 对象要开始返回 body 了。当Web Server 接受完这些元素之后,就可以将这些元素封装成为 HTTP Response 响应给 Client。

    • status: 一个字符串,表示HTTP响应状态的字符串
    • response_headers: 是一个包含了以元组(header_name, header_value)作为元素的列表类型对象,分别表示HTTP响应的 headers 及其内容。
    • exc_info(可选): 在出现错误时使用,返回相关错误信息给浏览器

回调函数:就是一个通过函数指针(变量的引用)调用的函数。如果你把函数的指针(引用)作为参数传递给另一个函数,当这个指针(引用)被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。所以 application 对象会在执行完请求的操作之后才会使用参数 start_response ,回调该变量指向的函数,以此来将 status、headers return 给 Server 。

body = []
status_headers == [None,None]def status_response(status,headers):status_headers[:] = [status,headers]return body.append(status_headers)

application 对象的返回值

application对象的返回值 body 用于 HTTP 响应,如果没有 body 返回,那么可以返回 None。如果有 body 返回,那么要求返回 body 必须是一个可迭代的对象。Server 通过遍历这个可迭代对象可以获得 body 的全部内容。
EXAMPLE:

def application(environ, start_response):  #status = '200 OK'response_headers = [('Content-type', 'text/plain')]start_response(status, response_headers)  #将 body == ['hello, world'] 作为返回值 return 之前,先调用 start_response(status, response_headers) 将 status、headers 先返回给 Serverreturn ['hello, world']

再谈Server如何调用application

Server 通过配置和 Python Module 来找到 Application 的入口,在找到 application 对象之后,Server 会通过将 Client Request 所有的 Info 和一些符合规范的参数信息传递给 application 对象作为实参,以此来实现 Server 将客户端请求传递给 Application。然后 application 对象执行业务逻辑,在返回 body 之前需要调用start_resposne()回调函数将HTTP响应所需要的信息返回。最后返回一个可迭代的对象 body ,Server 最后通过遍历来获取完整的 Body 数据。

注意:environ 和 start_response() 是需要在Server中的生成和定义的。

WSGI 中间件

WSGI Middleware 也是 WSGI 规范的一部分。 Middleware 是一个运行在 Server 和 Application 之间的应用。它同时具备了 Server 和 Application 的角色功能,对于 Server 来说,它是一个 Application;对于 Application来说,它是一个 Server。*middleware并不修改 Server 端和 Application 端的规范,只是同时实现了这两个角色的功能而已,因此它可以在两端之间起协调作用。而且 Middleware 可以将 Cllient HTTP Request 路由给不同的 Application 。*

Middleware 是如何工作的:
1.Server 收到客户端的 HTTP 请求后,生成了environ_s,并且已经定义了start_response_s
2.Server 调用 Middleware 的 application 对象,传递的参数是environ_sstart_response_s
3.Middleware 会根据 environ 执行业务逻辑,生成environ_m,并且已经定义了start_response_m
4.Middleware 再调用 Application 的 application 对象,传递参数是environ_mstart_response_m。Application 的 application 对象处理完成后,会调用 start_response_m 并且返回结果给 Middleware,存放在 result_m 中。
5.Middleware 处理 result_m,然后生成 result_s,接着调用 start_response_s,并返回结果 result_s给 Server 端。Server 端获取到 result_s 后就可以发送结果给客户端了。

从上面的流程可以看出middleware应用的几个特点:
1. Server认为middleware是一个application。
2. Application认为middleware是一个server。
3. Middleware可以有多层。

我们可以将 WSGI Middleware 了理解为 Server 和 Application 交互的一层包装,经过不同的 Middleware ,便拥有了不同的功能,EG. URL 路由转发、权限认证。因为Middleware能过处理所有通过的 request 和 response,所以要做什么都可以,没有限制。比如可以检查 request 是否有非法内容,检查 response 是否有非法内容,为 request 加上特定的 HTTP header 等。这些不同的 Middleware 组合便形成了 WSGI 的框架,比如我们将要介绍的 Paste。

WSGI的实现和部署

要使用WSGI,需要分别实现 Server 角色和 Application 角色。

  • Application 端一般是由Python的各种框架(Django, web.py)来实现的,一般开发者不需要关心 WSGI 的实现,框架会提供接口让开发者获取 HTTP 请求的内容以及发送 HTTP 响应。

  • Server 端的实现会比较复杂一点,这个主要是因为软件架构的原因。一般常用的Web服务器,如Apache和nginx,都不会内置WSGI的支持,而是通过扩展插件来完成。EG. Apache + mod_wsgi来支持WSGI。 Apache 和 mod_wsgi 之间通过程序内部接口传递信息,mod_wsgi 会实现 WSGI 的 Server端、进程管理以及对 application 的调用。Nginx + uWSGI,用 nginx 的协议将请求封装好,发送给应用服务器,应用服务器会实现 WSGI 的 Server 端、进程管理以及对 application 的调用。

参考资料

WSGI 简介
《Openstack 设计与实现》

Web 开发规范 — WSGI相关推荐

  1. Web开发和WSGI

    1. Web开发 CS即客户端.服务器编程.客户端.服务端之间需要使用Socket,约定协议.版本(往往使用的协议是TCP或者UDP),指定地址和端口,就 可以通信了. 客户端.服务端传输数据,数据可 ...

  2. 前端代码开发规范。web开发规范。web开发注意事项。前端开发如何写出更规范的代码

    一.图片观看: 二.文字描述: 1,web开发基本原则:     1.结构html,样式css,行为js:三者要分离,尽量确保文档和模板只包含HTML结构,样式都放到样式表里,行为都放到脚本里;   ...

  3. Python web 开发:部署一个3行代码的wsgi app

    通过前面的两篇: Python Web开发:从 wsgi 开始 Python Web开发:开发wsgi中间件 我们已经知道我们平时开发的 django.flask 等 python web 项目本质上 ...

  4. 前端传中文文件名_前端工程师需要掌握哪些知识,web前端开发规范总结

    Web前端作为开发团队中不可或缺的一部分,需要按照相关规定进行合理编写(一部分不良习惯可能给自己和他人造成不必要的麻烦).不同公司不同团队具有不同的规范和文档.下面是根据不同企业和团队的要求进行全面详 ...

  5. 汇总Web前端开发工程师需要注意的一些开发规范

    对于正在从事Web前端开工作的人来说,了解Web前端开发规范是很重要的.因为只有这样才能保证高效快速的完成工作,今天小千就来和大家分享一下新手初学Web前端需要注意的Web前端开发规范有哪些!希望对小 ...

  6. python web开发 网络编程 HTTP协议、Web服务器、WSGI接口

    文章目录 1. HTTP协议 2. Web服务器 3. 静态服务器 创建 web_server.py 4. WSGI 接口 4.1 CGI 通用网关接口 4.2 WSGI 4.3 定义 WSGI 接口 ...

  7. (16)WEB前端开发规范之HTML规范

    一.WEB前端开发规范目的 为提高团队协作效率, 便于后台人员添加功能及前端后期优化维护, 输出高质量的文档, 特制订此文档: 本规范文档一经确认, 前端开发人员必须按本文档规范进行前台页面开发: 本 ...

  8. Domino Web开发规则之一:Notes命名规范

    所有的设计元素的命名都分成两部分,名称和别名,规定名称用中文命名,别名用英文,别名尽量使用简写,以WEB开发时不会产生较长的URL为前提,提高HTTP Request的响应速度.中文名称前面加上字母A ...

  9. Web前端开发规范文档(转)

    本文处之:http://www.w3cfuns.com/blog-1-534.html 规范目的 为提高团队协作效率, 便于后台人员添加功能及前端后期优化维护, 输出高质量的文档, 特制订此文档. 本 ...

最新文章

  1. 《机器学习实战》笔记(02):k-近邻算法
  2. 【转载】简直可爱极了的即时通讯
  3. JSP的九大内置对象
  4. 全国所有省份行政区域名标准(全国省份2字母拼音缩写标准参考)
  5. 怎样手工清除autorun病毒
  6. 《创业维艰》详细的思维导图
  7. 【数据分析案例】留存率分析方法
  8. #计算机专业权威期刊#
  9. 转Genymetion
  10. 用CCS搭建简单的F28069M工程并控制LED闪烁
  11. matlab均衡的算法有哪些,从Matlab到Python的算法均衡
  12. 保险业首季度保费收入猛增五成
  13. obj[key]和0bj.['key']
  14. RT-Thread物联网操作系统介绍:6、线程挂起和恢复
  15. 苏黎世联邦理工学院计算机怎么样,苏黎世联邦理工学院计算机
  16. 系分 - 计算机网络
  17. WebService客户端三种调用方式整理
  18. 面向对象三大特征之封装
  19. Mixly15:触摸式开关
  20. 如何搭建直播平台?直播平台搭建需要注意什么?...

热门文章

  1. 计算机网络管理云红艳电子版,计算机网络管理pdf
  2. idea不区分大小写设置_我的 IntelliJ IDEA 一直都是这么设置的,效果很棒!
  3. axure中备注线_琉璃:璇玑小本子上,别人名字都有备注唯独司凤没有,意义很浪漫...
  4. windows命令大全_必收藏!电脑快捷键、组合键大全
  5. 给PS4装上Linux,然后用Xbox手柄打任天堂游戏?网友:这场面我没见过
  6. 只是pip安装输错字母,你就可能中了挖矿病毒
  7. 不是所有图像都值16x16个词,清华与华为提出动态ViT
  8. 别再打字聊bug了,GitHub支持“视频留言”!手机也可以的那种
  9. 清华唐杰:GPT-3表示能力已经接近人类了,但它有一个阿喀琉斯之踵 | MEET 2021...
  10. 嬴彻科技拿下SemanticKITTI榜单两项第一