wsgi pep333
转自:https://www.aliyun.com/jiaocheng/444966.html?spm=5176.100033.1.11.559a7C
- 摘要:wsgi介绍参考:pep333wsgi有两个interface:server/gateway和application/framework。server会调用一个由app提供的可callable对象。而app怎么提供这个对象给server,就由server决定了。有些server需要app写一个script来创建一个对象给server,有些server就直接根据config或者其它机制来调用这个对象。除了纯粹的server和app,wsgi还可以加入midlleware部件。m
- wsgi介绍
参考:pep 333
wsgi 有两个interface:server/gateway和application/framework。server会调用一个由app提供的可callable 对象。而app怎么提供这个对象给server,就由server决定了。有些server需要app写一个script 来创建一个对象给server,有些server就直接根据config或者其它机制来调用这个对象。
除了纯粹的server和app,wsgi还可以加入midlleware部件。middleware组件对于server就相当于一个app,对于app来说就是个server,可以提供可扩展的api,导航等其它有用的功能。
app
app 就是一个可调用的接受两个参数的对象。它可以是一个函数,一个类,一个带有_call_的对象。app可以多次被server调用。
下面两个是app的例子,一个是函数,一个是类。def simple_app(environ, start_response): """Simplest possible
application object""" status = '200 OK' response_headers =
[('Content-type', 'text/plain')] start_response(status,
response_headers) return ['Hello world!/n']class AppClass:
"""Produce the same output, but using a class (Note: 'AppClass' is
the "application" here, so calling it returns an instance of
'AppClass', which is then the iterable return value of the
"application callable" as required by the spec. If we wanted to
use *instances* of 'AppClass' as application objects instead, we
would have to implement a '__call__' method, which would be invoked
to execute the application, and we would need to create an instance
for use by the server or gateway. """ def __init__(self,
environ, start_response): self.environ = environ
self.start = start_response def __iter__(self): status = '200
OK' response_headers = [('Content-type', 'text/plain')]
self.start(status, response_headers) yield "Hello world!/n"
server
server每次从client接受一个http请求就调用一次app。为了说明,下面一个简单的调用一个app对象的cgi gateway。但是下面这个例子对于错误处理是不足的,正常情况错误要输出到server log 上。
import os, sysdef run_with_cgi(application): environ =
dict(os.environ.items()) environ['wsgi.input'] = sys.stdin
environ['wsgi.errors'] = sys.stderr environ['wsgi.version']
= (1, 0) environ['wsgi.multithread'] = False
environ['wsgi.multiprocess'] = True environ['wsgi.run_once'] =
True if environ.get('HTTPS', 'off') in ('on', '1'):
environ['wsgi.url_scheme'] = 'https' else:
environ['wsgi.url_scheme'] = 'http' headers_set = [] headers_sent =
[] def write(data): if not headers_set: raise
AssertionError("write() before start_response()") elif not
headers_sent: # Before the first output, send the stored
headers status, response_headers = headers_sent[:] =
headers_set sys.stdout.write('Status: %s/r/n' % status)
for header in response_headers:
sys.stdout.write('%s: %s/r/n' % header)
sys.stdout.write('/r/n') sys.stdout.write(data)
sys.stdout.flush() def start_response(status, response_headers,
exc_info=None): if exc_info: try: if
headers_sent: # Re-raise original exception if
headers sent raise exc_info[0], exc_info[1],
exc_info[2] finally: exc_info = None #
avoid dangling circular ref elif headers_set: raise
AssertionError("Headers already set!") headers_set[:] = [status,
response_headers] return write result = application(environ,
start_response) try: for data in result: if data:
# don't send headers until body appears write(data)
if not headers_sent: write('') # send headers now if
body was empty finally: if hasattr(result, 'close'):
result.close()
middleware
middleware 可以提供如下列几种功能:
- 根据url,把请求转发到不同app处理
- 允许多个app在同一进程使用
- 通过网络中转发请求,实现负载均衡
- 实现内容预处理,例如添加XSL 样式middleware其实对于server就是个app
对于app就是一个server。middlerware可以写得跟app一样接受两个同样的参数,env和start_response,这样middleware就对于server相当于一个app,只要在middleware像server调用app一样再调用app就可以了,而对于app,middleware就相当于server调用它。下面是一个用Joe Strout’s piglatin.py将text/plain的response转化为pig Latin的middleware
from piglatin import piglatinclass LatinIter: """Transform iterated
output to piglatin, if it's okay to do so Note that the "okayness"
can change until the application yields its first non-empty string,
so 'transform_ok' has to be a mutable truth value. """ def
__init__(self, result, transform_ok): if hasattr(result,
'close'): self.close = result.close self._next =
iter(result).next self.transform_ok = transform_ok def
__iter__(self): return self def next(self): if
self.transform_ok: return piglatin(self._next()) else:
return self._next()class Latinator: # by default, don't
transform output transform = False def __init__(self,
application): self.application = application def
__call__(self, environ, start_response): transform_ok = []
def start_latin(status, response_headers, exc_info=None): #
Reset ok flag, in case this is a repeat call del
transform_ok[:] for name, value in response_headers:
if name.lower() == 'content-type' and value == 'text/plain':
transform_ok.append(True) # Strip
content-length if present, else it'll be wrong
response_headers = [(name, value) for name, value
in response_headers if name.lower() !=
'content-length' ] break
write = start_response(status, response_headers, exc_info)
if transform_ok: def write_latin(data):
write(piglatin(data)) return write_latin
else: return write return
LatinIter(self.application(environ, start_latin), transform_ok)# Run
foo_app under a Latinator's control, using the example CGI gatewayfrom
foo_app import foo_apprun_with_cgi(Latinator(foo_app))
细节说明
app必须是接受两个参数,environ和start_response(参数名可以另取,就是一定要代入两个参数)
environ是一个类dict的对象,里面包含cgi-style的环境变量。这个对象必须是使用Python内置的dict对象(不能是子对象或其它),而app能根据自身需求修改这个environ。这个dict也必须包含一些wsgi需要的变量和server需要确认的变量。
start_response是一个可以调用的接受两个必须参数和一个可选参数的对象,这三个参数分别是:status,response_header和exc_info。但是参数不一定要取这些名称。app一定可以用这些参数调用start_response。
satus是一种以”999 Message here”字符串形式给出的。response_header是一个以(header_name,
header_value)tuple形式组成的list,用来描述http reaponse
header。可选的exc_info是用来处理错误信息的,错误信息通过exc_info展现给浏览器。start_response一定要返回一个write(body_data)可调用的需要一个参数的对象:一个写进http response body的字符串
当app被server调用的时候,app一定要返回一个可iterable yielding 0或者字符串。这样的app可以通过很多方式去实现,例如返回一个list的字符串或者app写成一个返回字符串的生成器,或者app写成一个可以iterable 的类。
server一定要以unbuffered形式把生成的字符串发送出去后,再去生成另外的。
server一定要把生成的字符串当做是二进制队列。app负责要把所有的字符串转化成对client可读的形式。
如果app返回的iterable有close()方法,那么server在处理完一个请求后一定要调用这个方法,不管这个请求是否正确处理完或者因为错误停止。
最后,server不能直接使用由app提供的iterable中的所有参数,除非参数是指定给server使用的。
environ variables
environ是根据cgi需要的定义的,下面这些参数是一定要提供的,除非他们的值为空。
REQUEST_METHOD
The HTTP request method, such as "GET" or "POST" . This cannot ever be an empty string, and so is always required.
SCRIPT_NAME
The initial portion of the request URL's "path" that corresponds to the
application object, so that the application knows its virtual
"location". This may be an empty string, if the application corresponds
to the "root" of the server.
PATH_INFO
The remainder of the request URL's "path", designating the virtual
"location" of the request's target within the application. This may be
an empty string, if the request URL targets the application root and
does not have a trailing slash.
QUERY_STRING
The portion of the request URL that follows the "?" , if any. May be empty or absent.CONTENT_TYPE
The contents of any Content-Type fields in the HTTP request. May be empty or absent.
CONTENT_LENGTH
The contents of any Content-Length fields in the HTTP request. May be empty or absent.SERVER_NAME , SERVER_PORT
When combined with SCRIPT_NAME and PATH_INFO , these variables can be
used to complete the URL. Note, however, that HTTP_HOST , if present,
should be used in preference to SERVER_NAME for reconstructing the
request URL. See the URL Reconstruction section below for more detail.
SERVER_NAME and SERVER_PORT can never be empty strings, and so are
always required.
SERVER_PROTOCOL
The version of the protocol the client used to send the request.
Typically this will be something like "HTTP/1.0" or "HTTP/1.1" and may
be used by the application to determine how to treat any HTTP request
headers. (This variable should probably be called REQUEST_PROTOCOL ,
since it denotes the protocol used in the request, and is not
necessarily the protocol that will be used in the server's response.
However, for compatibility with CGI we have to keep the existing name.)
HTTP_ Variables
Variables corresponding to the client-supplied HTTP request headers
(i.e., variables whose names begin with “HTTP_” ). The presence or
absence of these variables should correspond with the presence or
absence of the appropriate HTTP header in the request.
除了要提供cgi需要的参数,另外还有一些系统的环境变量和一些wsgi需要的参数也要包含在里面。
Variable Value wsgi.version wsgi.version The tuple (1, 0) , representing WSGI version 1.0. wsgi.url_scheme A string representing the “scheme” portion of the URL at which
the application is being invoked. Normally, this will have the value
“http” or “https” , as appropriate.wsgi.input An input stream (file-like object) from which the HTTP request
body can be read. (The server or gateway may perform reads on-demand as
requested by the application, or it may pre- read the client’s request
body and buffer it in-memory or on disk, or use any other technique for
providing such an input stream, according to its preference.)wsgi.errors An output stream (file-like object) to which error output can be
written, for the purpose of recording program or other errors in a
standardized and possibly centralized location. This should be a “text
mode” stream; i.e., applications should use “/n” as a line ending, and
assume that it will be converted to the correct line ending by the
server/gateway.For many servers, wsgi.errors will be the server’s main
error log. Alternatively, this may be sys.stderr , or a log file of some
sort. The server’s documentation should include an explanation of how
to configure this or where to find the recorded output. A server or
gateway may supply different error streams to different applications, if
this is desired.wsgi.multithread This value should evaluate true if the application object may be
simultaneously invoked by another thread in the same process, and should
evaluate false otherwise.wsgi.multiprocess This value should evaluate true if an equivalent application
object may be simultaneously invoked by another process, and should
evaluate false otherwise.wsgi.run_once This value should evaluate true if the server or gateway expects
(but does not guarantee!) that the application will only be invoked this
one time during the life of its containing process. Normally, this will
only be true for a gateway based on CGI (or something similar).
wsgi pep333的更多相关文章
- python wsgi PEP333 中文翻译
PEP 333 中文翻译 首先说明一下,本人不是专门翻译的,英文水平也不敢拿来献丑.只是这是两年前用python的时候为了自己学习方便而翻译的,记录着笔记自己看看而已.最近翻出来看看觉得还是放出来吧. ...
- python wsgi 简介
wsgi全称是"Web Server Gateway Interfacfe",web服务器网关接口,wsgi在python2.5中加入,是web服务器和web应用的标准接口,任何实 ...
- Python——eventlet.wsgi
eventlet 的 wsgi 模块提供了一种启动事件驱动的WSGI服务器的简洁手段,可以将其作为某个应用的嵌入web服务器,或作为成熟的web服务器,一个这样的web服务器的例子就是 Spawnin ...
- uwsgi/uWSGI/WSGI简介
参考文章 uWSGI是一个Web服务器,它实现了WSGI协议.uwsgi.http等协议.Nginx中HttpUwsgiModule的作用是与uWSGI服务器进行交换.z WSGI是一种Web服务器网 ...
- Python WSGI v1.0 中文版(转)
add by zhj: WSGI全称Web Server Gateway Interface,即Web网关接口.其实它并不是OSI七层协议中的协议,它就是一个接口而已,即函数,而WSGI规定了该接口的 ...
- Python的Web编程[1] -> Web服务器[0] -> Web 服务器与 CGI / WSGI
Web服务器 / Web Server 对于Web来说,需要建立一个Web服务器,必须建立一个基本的服务器和一个处理程序, 基本服务器的主要作用是,在客户端和服务器端完成必要的HTTP交互, 处理程序 ...
- Nginx、WSGI、 uWSGI、 uwsgi的区别
当我们部署完一个应用程序,浏览网页时具体的过程是怎样的呢?首先我们得有一个 Web 服务器来处理 HTTP 协议的内容,Web 服务器获得客户端的请求,交给应用程序,应用程序处理完,返回给 Web 服 ...
- python nginx+uwsgi+WSGI 处理请求详解
https://blog.csdn.net/a519640026/article/details/76157976 请求从 Nginx 到 uwsgi 到 django 交互概览 作为python w ...
- [原]Paste.deploy 与 WSGI, keystone 小记
Paste.deploy 与 WSGI, keystone 小记 名词解释: Paste.deploy 是一个WSGI工具包,用于更方便的管理WSGI应用, 可以通过配置文件,将WSGI应用加载起来. ...
随机推荐
- Codeforces 455C Civilization(并查集+dfs)
题目链接:Codeforces 455C Civilization 题目大意:给定N.M和Q,N表示有N个城市,M条已经修好的路,修好的路是不能改变的.然后是Q次操作.操作分为两种.一种是查询城市x所 ...
- [docker]docker run指定entrypiont
指定entrypiont 错误的姿势 docker run -itd -v /tmp/:/tmp/ jdk-ori 'java -jar /tmp/sms.jar' 正确的姿势1 docker run ...
- 字符串操作:int 转 string
strstream ss; string ch; ss<<i; ss>>ch;
- 操作XmlDocument时,出现"System.OutOfMemoryException"异常,如何解决加载大数据的情况?
System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.at System.St ...
- oozie搭建手册
环境准备 mave安装 1.下载并上传maven,然后解压 tar -zxvf apache-maven-3.3.9-bin.tar.gz -C /home 2.配置环境变量 vi /etc/prof ...
- Nginx指令概述
指令概述 配置指令是一个字符串,可以用单引号或者双引号括起来,也可以不括.但是如果配置指令包含空格,一定要引起来. 指令参数 指令的参数使用一个或者多个空格或者TAB字符与指令分开.指令的参数有一个或 ...
- C++ 4种强制类型转换
C++的四种强制类型转换为:static_cast.const_cast.reinterpret_cast和dynamic_cast 类型转换的一般形式:cast-name(expression); ...
- poj3041 Asteroids 匈牙利算法 最小点集覆盖问题=二分图最大匹配
/** 题目:poj3041 Asteroids 链接:http://poj.org/problem?id=3041 题意:给定n*n的矩阵,'X'表示障碍物,'.'表示空格;你有一把枪,每一发子弹可 ...
- 企业Shell面试题5:解决DOS攻击生产案例
企业Shell面试题5:解决DOS攻击生产案例 写一个Shell脚本解决DOS攻击生产案例. 请根据web日志或者或者网络连接数,监控当某个IP并发连接数或者短时内PV达到100(读者根据实际情况设定 ...
- linux远程控制windows
我的开发环境是linux,但是需要同时维护windows和linux的服务器,所以有时需要在linux系统下也能远程控制windows的机器. rdesktop是一款开源的远程连接工具,它通过实现了R ...