声明:这篇文章只是为了整体理解WSGI,会忽略很多细节,要详细了解请参看文后的参考资料

WSGI概述

WSGI全称是Python Web Server Gateway Interface(Python Web服务网关接口)仅针对名字可以做出一下总结:

  • 1、Python Web Server Gateway Interface:这个规范是针对Python的
  • 2、Python Web Server Gateway Interface:这个规范是针对Web服务相关的
  • 3、Python Web Server Gateway Interface:这个规范是针对服务网关处的
  • 4、Python Web Server Gateway Interface:这个规范是一种接口定义,不是具体实现

上面这样按照字面文本切分来理解也许是错的,但是在这里用来梳理理解我认为还是可以的。首先条目1、2、4应该是没问题,比较难理解的是3。3比较难理解是因为在我们的日常学习、开发的经历中,gateway/网关这一个词的准确指代是不明确、不固定的,这个词非常笼统与抽象,业务逻辑上集束处可以被成为网关,协议转换处可以被成为网关,权限分层处可以被称为网关……在基础的HTTP架构里,网关原本是用于称呼协议代理转换的那一部分,比如我们平常通过网页首发QQ邮件,浏览器后服务商后台进行通讯使用的是HTTP(S)协议,可e-mail常规协议是smtp、pop3这些,所以在中间一般经历了HTTP(S)到stmp等协议的转换,这一部分就是传统上基于HTTP服务架构中的网关。那么WSGI中的网关是什么意思呢?是不是协议转换?答案是否定的。在WSGI中所谓的网关是Web服务器与Web应用之间的衔接处,他使用的是类CGI之中网关的意思,就是Web服务器和动态Web程序之间的衔接。静态Web站点需要的软件程序只有Web服务器,Web服务器对文件系统进行相应的映射提供静态资源服务(HTML、图片等),但是动态网站需要处理业务逻辑的程序,业务逻辑程序通过不同的输出渲染输出不同的结果再由Web服务器传送给上游客户端。这样就产生了Web服务器和业务程序衔接的问题,就产生了cgi、fast-cgi。而WSGI是用来统一Web服务器和Python Web应用/框架之间接口的规范。

其实根据上面的描述可以看到业务逻辑程序概念上和网络传输没有关系,比如我们用Flask写的Web程序其实只是业务逻辑,真正处理HTTP网络传输的是Web服务器,只不过Flask为了便于开发自身携带了一个开发型Web服务器。

那WSGI有什么优势呢?为什么要有WSGI呢?首先要说明的是没有WSGI也是可以的,但是如果没有WSGI,每一个Web应用就要有单独的Web服务器,或者对某一个Web服务器做各种的兼容性的改动;有了WSGI规范,那么凡是支持该规范接口的Web服务器和Web应用就可以搭配使用提供服务。

WSGI规范主要骨架

刨去细节,从整体上看,WSGI对三方的规范:Web服务器规范、Web应用规范、中间件规范

Web服务器规范:

服务器必须提供两样东西: 一是environ环境字典,二是start_response可调用函数

其中:

  • environ 字典必须包涵一定的数据项,类似于CGI environment

    • environ包含的字段样例如下
    • environ['wsgi.input'] = sys.stdin.buffer
    • environ['wsgi.errors'] = sys.stderr
    • environ['wsgi.version'] = (1, 0)
    • environ['wsgi.url_scheme'] = 'https'
    • ...
  • start_response是接受两个参数的回调函数
    • 参数status: 包涵标准的HTTP状态字符串 例如:200 OK
    • 参数response_headers:标准HTTP响应头列表

服务器像下面这样将包含HTTP请求信息传递给Web应用/框架:

iterable = simple_app(environ, start_response)
for data in iterable:
pass
# send data to client

可以看出构建响应头、调用start_response并构建数据一可迭代的形式返回是应用/框架的责任,通过HTTP将响应头和数据传递给上游是Web服务器的责任。

Web应用/框架规范

Web应用/框架必须是可调用的,可以是类、函数或者对象, __init__参数、 __call__参数或者函数必须如上面调用的样子

  • 一个environ对象
  • 一个可调用的start_response

Web应用/框架必须在返回数据之前调用start_response

Web应用/框架应该以可迭代的形式返回数据,比如:列表

一个简单的WSGI应用的例子

def app(environ, start_response):
status = '200 OK'
response_headers = [('Content-type','text/plain')]
start_response(status, response_headers)
return ['Hello world!\n']

中间件规范:

中间件组建必须同时遵守Web服务端和Web应用断的规范要求,并添加了一些轻微的限制

中间件应尽可能透明

下面是一个简单的将字符串全部转换成大写的中间件

class Upperware:
def __init__(self, app):
self.wrapped_app = app def __call__(self, environ, start_response): # 这里遵循应用端规范
# 下面两个遵循服务端规范
for data in self.wrapped_app(environ, start_response):
yield data.upper()

一个完整的WSGI应用运行样例

# coding:utf-8

"""使用python内带的wsgiref简单服务器作Web服务器"""

from wsgiref.simple_server import make_server
from urlparse import parse_qs def simple_app(environ, start_response):
status = '200 OK'
response_headers = [('Content-type', 'text/plain')]
start_response(status, response_headers)
return ['Hello World'] class Upperware:
def __init__(self, app):
self.wrapped_app = app def __call__(self, environ, start_response):
for data in self.wrapped_app(environ, start_response):
yield data.upper() def main(environ, start_response):
print environ
params = parse_qs(environ.get('QUERY_STRING', ''))
if 'true' in params.get('mid', []):
app = Upperware(simple_app)
else:
app = simple_app
return app(environ, start_response) if __name__ == "__main__":
srv = make_server('localhost', 9797, main)
srv.serve_forever()
#https://www.programcreek.com/python/example/65645/wsgiref.simple_server.WSGIServer
# httpd_cls = type(str('WSGIServer'), (socketserver.ThreadingMixIn, WSGIServer), {})
# server_address = (addr, port)
# httpd = httpd_cls(server_address, WSGIRequestHandler, ipv6=False)
# httpd.daemon_threads = True
# httpd.set_app(wsgi_handler)
# httpd.serve_forever()

如果以mid=true为参数的话访问(不限路径),就会使得中间件生效,返回文本全部大写,若不带该参数或该参数不为‘true’,中间件就不会生效。

再重复提一句:构建响应头、调用start_response并构建数据一可迭代的形式返回是应用/框架的责任(业务逻辑),通过HTTP将响应头和数据传递给上游是Web服务器的责任(网络传输)。,Web框架要处理的不是HTTP传输问题,是应用逻辑构建问题,比如说路由系统、上下文、模板渲染等等。还有就是现实世界也不是非此即彼,比如说Web服务器也可以直接构建路由系统,Web服务器和Web框架的编写是技术活,也是力气活(需要实现很多规范的细节)

声明:这篇文章只是为了简单整体理解WSGI我自己的一点浅薄之见,要详细了解请参看文后的参考资料

参考资料

理解PEP333-WSGI的更多相关文章

  1. python Web开发你要理解的WSGI & uwsgi详解

    原文:https://www.jb51.net/article/144852.htm WSGI协议 首先弄清下面几个概念: WSGI:全称是Web Server Gateway Interface,W ...

  2. 如何理解Nginx, WSGI, Flask(Django)之间的关系

    如何理解Nginx, WSGI, Flask(Django)之间的关系 值得指出的是,WSGI 是一种协议,需要区分几个相近的名词: uwsgi 同 wsgi 一样也是一种协议,uWSGI服务器正是使 ...

  3. 如何理解Nginx, WSGI, Flask之间的关系

    概览 之前对 Nginx,WSGI(或者 uWSGI,uwsgi),Flask(或者 Django),这几者的关系一存存在疑惑.通过查阅了些资料,总算把它们的关系理清了. 总括来说,客户端从发送一个 ...

  4. 浅析uWSGI、uwsgi、wsgi

    WSGI协议 首先弄清下面几个概念: WSGI:全称是Web Server Gateway Interface,WSGI不是服务器,python模块,框架,API或者任何软件,只是一种规范,描述web ...

  5. wsgi&nginx-理解

    WSGI协议 首先弄清下面几个概念:WSGI:全称是Web Server Gateway Interface,WSGI不是服务器,python模块,框架,API或者任何软件,只是一种规范,描述web ...

  6. wsgi & cgi的一些概念解释

    可以看这里 https://www.zhihu.com/question/19998865 如何理解 CGI, WSGI?修改 写补充说明 举报 添加评论 分享 • 邀请回答 默认排序 按时间排序 1 ...

  7. CGI,WSGI区别

    WSGI 参考link:https://jingtyu.gitbooks.io/learning-openstack/content/351-usgi.html(本人的gitbook) 个人理解: w ...

  8. 网关协议:CGI和WSGI

    通常服务器程序分为web服务器和应用程序服务器.web服务器是用于处理HTML文件,让客户可以通过浏览器进行访问,主流的web服务器有Apache.IIS.Nginx.lighthttpd等.应用服务 ...

  9. wsgi和asgi的关系

    什么是WSGI #CGI CGI(Common Gateway Interface,通用网关接口),定义客户端与Web服务器的交流方式的一个程序,例如正常情况下客户端发送过来一个请求,根据HTTP协议 ...

  10. 2020年是时候更新你的技术武器库了:Asgi vs Wsgi(FastAPI vs Flask)

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_167 也许这一篇的标题有那么一点不厚道,因为Asgi(Asynchronous Server Gateway Interface) ...

随机推荐

  1. MDX 查询原型

    本篇文章记录 SBS 中 MDX 查询原型,可以根据这些查询原型来解决实际项目中的问题. 1. 查询在 2004年1月2日 - 2004年3月1日之间购买过 Bikes 产品的用户. SELECT ( ...

  2. Linux中使用Vim快速更换文档中Windows换行符为Linux平台

    一.简述 平时我们把Windows编写好的sh文件放在linux上跑时,经常出现换行符的问题.快速切换的解决方法如下: 二.解决 vim test.sh :set ff? 如果出现fileforma= ...

  3. centos7安装配置mysql5.6

    1. 下载mysql的repo源 $ wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm 2. 安装mysql-co ...

  4. 从网上找的Android实用代码,记录备用

    1.获取应用程序下所有Activity public static ArrayList<String> getActivities(Context ctx) { ArrayList< ...

  5. MySQL 大致测试更新时间

    1:需求:把一个2千万条数据的一个表,随机更新其中的二十行需要大致多久? DROP TABLE IF EXISTS test20; CREATE TABLE test20( id INT AUTO_I ...

  6. 【Zookeeper】源码分析之网络通信(二)之NIOServerCnxn

    一.前言 前面介绍了ServerCnxn,下面开始学习NIOServerCnxn. 二.NIOServerCnxn源码分析 2.1 类的继承关系 public class NIOServerCnxn ...

  7. MySql之修改操作与进阶

    一:更新特定行 UPDATE tableName SET 列名 = 值,列名 = 值... WHERE 条件; 二:使用子查询更新数据 UPDATE tableName SET 列名 = SELECT ...

  8. C#面试题(转载)

    原文地址:100道C#面试题(.net开发人员必备)  https://blog.csdn.net/u013519551/article/details/51220841 1. .NET和C#有什么区 ...

  9. ORA-214 signalled during: ALTER DATABASE MOUNT 问题

    数据库服务器移动了位置,后来再连其数据库发现提示无法连接,大致为“无法为所有新实例创建连接...”,查看alert日志发现有如下错误: starting up 1 dispatcher(s) for ...

  10. Bash 中的特殊字符大全【转】

    Linux下无论如何都是要用到shell命令的,在Shell的实际使用中,有编程经验的很容易上手,但稍微有难度的是shell里面的那些个符号,各种特殊的符号在我们编写Shell脚本的时候如果能够用的好 ...