Differences between revisions 4 and 17 (spanning 13 versions)
Revision 4 as of 2006-08-22 06:17:40
Size: 6247
Editor: HuangYi
Comment:
Revision 17 as of 2006-08-24 04:57:45
Size: 856
Editor: ZoomQuiet
Comment:
Deletions are marked like this. Additions are marked like this.
Line 7: Line 7:

wsgi 是一个 web 组件的接口规范.
wsgi将 web 组件分为三类: web服务器,web中间件,web应用程序.
其目标是提高web组件的可重用性.
wsgi 的设计目标是适合尽可能广泛的web应用, 较原始.

典型场景:

{{{#!python
  app = A_WSGI_Application(...)
  app = Middleware1(app, ...)
  app = Middleware2(app, ...)
  ...
  server(app).serve_forever()
}}}
[[Include(/AbtWSGI)]]
Line 28: Line 14:
 * [http://www-128.ibm.com/developerworks/library/wa-wsgi/ Mix and match Web components with Python WSGI]
  * 中译版本 [:/MixMatchWebComponentsWithPyWSGI:使用PyWSGI混合WEB组件]
Line 30: Line 18:
[[Include(/AppWSGI)]]
Line 31: Line 21:
[[Include(/SrvWSGI)]]
Line 32: Line 23:

== 例子 ==
=== 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']
[[Include(/MidWSGI)]]
Line 44: Line 26:
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"
}}}
=== 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)]]

TableOfContents

简介

Include(/AbtWSGI)

相关页面

规范

WSGI应用程序

Include(/AppWSGI)

WSGI服务器

Include(/SrvWSGI)

WSGI中间件

Include(/MidWSGI)

规范细节

Include(/DetailsWSGI)

讨论

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