Differences between revisions 3 and 23 (spanning 20 versions)
Revision 3 as of 2006-08-22 06:03:52
Size: 6161
Editor: HuangYi
Comment:
Revision 23 as of 2008-12-25 04:11:17
Size: 1902
Editor: ZoomQuiet
Comment:
Deletions are marked like this. Additions are marked like this.
Line 7: Line 7:
[[Include(/AbtWSGI)]]
Line 8: Line 9:
wsgi 是一个 web 组件的接口规范.
wsgi将 web 组件分为三类: web服务器,web中间件,web应用程序.
其目标是提高web组件的可重用性.
wsgi 的设计目标是适合尽可能广泛的web应用, 较原始.
== 相关资料 ==
'''http://wsgi.org/'''
Line 13: Line 12:
典型场景:  理解WSGI::
  * PEP 333 -- Python Web Server Gateway Interface v1.0
   * http://www.python.org/dev/peps/pep-0333/
  * WSGI-Gateway or Glue? - 动态感觉 静观其变 - 歪酷博客 Ycool Blog
   * http://xlp223.ycool.com/post.1639120.html
  * [http://pythonpaste.org/ Paste] ["PasteQuickIn"] 为编写基于WSGI的应用程序或框架提供一个良好的基础, 比如:提供wsgi web服务器,常用wsgi中间件 等.
  * [http://www-128.ibm.com/developerworks/library/wa-wsgi/ Mix and match Web components with Python WSGI]
   * 中译版本 [:/MixMatchWebComponentsWithPyWSGI:使用PyWSGI混合WEB组件]
  * [http://xlp223.yculblog.com/post.2566634226.html Why so many Python web frameworks?(中译版本)]
  * [http://xlp223.yculblog.com/post.2566639120.html WSGI-Gateway or Glue?(中译版本)]
Line 15: Line 23:
{{{#!python
  app = A_WSGI_Application(...)
  app = Middleware1(app, ...)
  app = Middleware2(app, ...)
  ...
  server(app).serve_forever()
}}}

== 相关页面 ==

 * [http://www.python.org/peps/pep-0333.html Python Web Server Gateway Interface v1.0 PEP333]
 * http://wsgi.org/
 * [http://pythonpaste.org/ Paste] ["PasteQuickIn"] 为编写基于WSGI的应用程序或框架提供一个良好的基础, 比如:提供wsgi web服务器,常用wsgi中间件 等.

== 例子 ==
=== WSGI应用程序 ===
{{{#!python
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']
 实用WSGI::
  * 用 Python WSGI 混和并匹配 Web 组件
   * http://www-128.ibm.com/developerworks/cn/web/wa-wsgi/index.html
  * PyLons 对 WEB服务网关接口(WSGI)的支持
   * http://wiki.woodpecker.org.cn/moin/PyLons/wsgi
 WSGI框架::
  * Frameworks - WSGI Wiki
   * http://www.wsgi.org/wsgi/Frameworks
  * A Pylons controller with MoinMoin as a WSGI callable - PylonsCookbook - PythonWeb
   * http://wiki.pylonshq.com/display/pylonscookbookA+Pylons+controller+with+MoinMoin+as+a+WSGI+callable
  * WsgiRequestPatch - MoinMoin
   * http://moinmoin.wikiwikiweb.de/WsgiRequestPatch
Line 40: Line 37:
class AppClass:
    """Produce the same output, but using a class
Line 43: Line 38:
    (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.
== 规范 ==
=== WSGI应用程序 ===
[[Include(/AppWSGI)]]
Line 48: Line 42:
    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.
    """
=== WSGI服务器 ===
[[Include(/SrvWSGI)]]
=== WSGI中间件 ===
[[Include(/MidWSGI)]]
Line 55: Line 47:
    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"
}}}
=== WSGI服务器 ===
{{{#!python
import os, sys

def 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()
}}}
=== WSGI中间件 ===
{{{#!python
from piglatin import piglatin

class 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
            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 gateway
from foo_app import foo_app
run_with_cgi(Latinator(foo_app))
}}}
== 规范细节 ==
[[Include(/DetailsWSGI)]]
Line 199: Line 51:

=== 深思WSGI ===
[[Include(/AskWSGI,,from="^##startInc$",to="^##endInc$")]]

TableOfContents

简介

Include(/AbtWSGI)

相关资料

http://wsgi.org/

理解WSGI
实用WSGI
WSGI框架

规范

WSGI应用程序

Include(/AppWSGI)

WSGI服务器

Include(/SrvWSGI)

WSGI中间件

Include(/MidWSGI)

规范细节

Include(/DetailsWSGI)

讨论

深思WSGI

Include(/AskWSGI,,from="^##startInc$",to="^##endInc$")

WSGI (last edited 2009-12-25 07:17:11 by localhost)