转自: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的更多相关文章

  1. python wsgi PEP333 中文翻译

    PEP 333 中文翻译 首先说明一下,本人不是专门翻译的,英文水平也不敢拿来献丑.只是这是两年前用python的时候为了自己学习方便而翻译的,记录着笔记自己看看而已.最近翻出来看看觉得还是放出来吧. ...

  2. python wsgi 简介

    wsgi全称是"Web Server Gateway Interfacfe",web服务器网关接口,wsgi在python2.5中加入,是web服务器和web应用的标准接口,任何实 ...

  3. Python——eventlet.wsgi

    eventlet 的 wsgi 模块提供了一种启动事件驱动的WSGI服务器的简洁手段,可以将其作为某个应用的嵌入web服务器,或作为成熟的web服务器,一个这样的web服务器的例子就是 Spawnin ...

  4. uwsgi/uWSGI/WSGI简介

    参考文章 uWSGI是一个Web服务器,它实现了WSGI协议.uwsgi.http等协议.Nginx中HttpUwsgiModule的作用是与uWSGI服务器进行交换.z WSGI是一种Web服务器网 ...

  5. Python WSGI v1.0 中文版(转)

    add by zhj: WSGI全称Web Server Gateway Interface,即Web网关接口.其实它并不是OSI七层协议中的协议,它就是一个接口而已,即函数,而WSGI规定了该接口的 ...

  6. Python的Web编程[1] -> Web服务器[0] -> Web 服务器与 CGI / WSGI

    Web服务器 / Web Server 对于Web来说,需要建立一个Web服务器,必须建立一个基本的服务器和一个处理程序, 基本服务器的主要作用是,在客户端和服务器端完成必要的HTTP交互, 处理程序 ...

  7. Nginx、WSGI、 uWSGI、 uwsgi的区别

    当我们部署完一个应用程序,浏览网页时具体的过程是怎样的呢?首先我们得有一个 Web 服务器来处理 HTTP 协议的内容,Web 服务器获得客户端的请求,交给应用程序,应用程序处理完,返回给 Web 服 ...

  8. python nginx+uwsgi+WSGI 处理请求详解

    https://blog.csdn.net/a519640026/article/details/76157976 请求从 Nginx 到 uwsgi 到 django 交互概览 作为python w ...

  9. [原]Paste.deploy 与 WSGI, keystone 小记

    Paste.deploy 与 WSGI, keystone 小记 名词解释: Paste.deploy 是一个WSGI工具包,用于更方便的管理WSGI应用, 可以通过配置文件,将WSGI应用加载起来. ...

随机推荐

  1. Codeforces 455C Civilization(并查集+dfs)

    题目链接:Codeforces 455C Civilization 题目大意:给定N.M和Q,N表示有N个城市,M条已经修好的路,修好的路是不能改变的.然后是Q次操作.操作分为两种.一种是查询城市x所 ...

  2. [docker]docker run指定entrypiont

    指定entrypiont 错误的姿势 docker run -itd -v /tmp/:/tmp/ jdk-ori 'java -jar /tmp/sms.jar' 正确的姿势1 docker run ...

  3. 字符串操作:int 转 string

    strstream ss; string ch; ss<<i; ss>>ch;

  4. 操作XmlDocument时,出现"System.OutOfMemoryException"异常,如何解决加载大数据的情况?

    System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.at System.St ...

  5. oozie搭建手册

    环境准备 mave安装 1.下载并上传maven,然后解压 tar -zxvf apache-maven-3.3.9-bin.tar.gz -C /home 2.配置环境变量 vi /etc/prof ...

  6. Nginx指令概述

    指令概述 配置指令是一个字符串,可以用单引号或者双引号括起来,也可以不括.但是如果配置指令包含空格,一定要引起来. 指令参数 指令的参数使用一个或者多个空格或者TAB字符与指令分开.指令的参数有一个或 ...

  7. C++ 4种强制类型转换

    C++的四种强制类型转换为:static_cast.const_cast.reinterpret_cast和dynamic_cast 类型转换的一般形式:cast-name(expression); ...

  8. poj3041 Asteroids 匈牙利算法 最小点集覆盖问题=二分图最大匹配

    /** 题目:poj3041 Asteroids 链接:http://poj.org/problem?id=3041 题意:给定n*n的矩阵,'X'表示障碍物,'.'表示空格;你有一把枪,每一发子弹可 ...

  9. 企业Shell面试题5:解决DOS攻击生产案例

    企业Shell面试题5:解决DOS攻击生产案例 写一个Shell脚本解决DOS攻击生产案例. 请根据web日志或者或者网络连接数,监控当某个IP并发连接数或者短时内PV达到100(读者根据实际情况设定 ...

  10. linux远程控制windows

    我的开发环境是linux,但是需要同时维护windows和linux的服务器,所以有时需要在linux系统下也能远程控制windows的机器. rdesktop是一款开源的远程连接工具,它通过实现了R ...