WSGI

□未翻訳

□翻訳中

□翻訳完了(細田謙二)

■レビュー(中垣健志)

WSGI

web2pyとWSGIは愛憎の関係にあります。私 たちの観点では、WSGIは、ポータブルな方法でWebサーバーがWebアプリケーションに接続するためのプロトコルとして開発されたものと見ていて、私 たちはそれをその目的で使用しています。web2pyはコア部分において1つのWSGIアプリケーションです:gluon.main.wsgibase。一 部の開発者は、WSGIをミドルウェア通信プロトコルとしての限界へと推し進め、Webアプリケーションを多数の層からなるたまねぎのように開発していま す(各層は、全体的なフレームワーク上で独立に開発されたWSGIミドルウェアからなります)。web2pyはこのような構造を内部で採用していません。これは、フレームワークのコアとなる機能(クッキーやセッション、エラー、トランザクション、ディスパッチの処理)は、それらを1つの包括的な層で扱ったほうが、速度とセキュリティの面でよりよく最適化できると、私たちは感じているからです。

web2py and WSGI have a love-hate relationship. Our perspective is that WSGI was developed as a protocol to connect web servers to web applications in a portable way and we use it for that purpose. web2py at its core is a WSGI application: gluon.main.wsgibase. Some developers have pushed WSGI to its limits as a protocol for middleware communications and develop web applications as an onion with many layers (each layer being a WSGI middleware developed independently on the entire framework). web2py does not adopt this structure internally. This is because we feel the core functionality of a frameworks (handling cookies, session, errors, transactions, dispatching) can be better optimized for speed and security if they are handled by a single comprehensive layer.

それでもなお、web2pyではサードパーティのWSGIアプリケーションとミドルウェアは、次の3通りの方法で(もしくはそれらの組み合わせで)、使用することができます。

Yet web2py allows you to use third party WSGI applications and middleware in three ways (and their combinations):

  • "wsgihandler.py"ファイルを編集し、任意のサードパーティ製のWSGIミドルウェアを取り込むことができます。

  • You can edit the file "wsgihandler.py" and include any third party WSGI middleware.

  • アプリケーション内の任意の指定したアクションに対し、サードパーティ製のWSGIミドルウェアを接続することができます。

  • You can connect third party WSGI middleware to any specific action in your apps.

  • アクションからサードパーティ製のWSGIアプリを呼び出すことができます。

  • You can call a third party WSGI app from your actions.

唯一の制限は、サードパーティ製のミドルウェアを用いてweb2pyのコア機能を置き換えることはできないことです。

The only limitation is that you cannot use third party middleware to replace core web2py functions.

外部ミドルウェア

External Middleware

"wsgibase.py"ファイルを考慮します:

Consider the file "wsgibase.py":

1.

2.

3.

4.

5.

6.

7.

8.

9.

#...

LOGGING = False

#...

if LOGGING:

application = gluon.main.appfactory(wsgiapp=gluon.main.wsgibase,

logfilename='httpserver.log',

profilerfilename=None)

else:

application = gluon.main.wsgibase

LOGGINGがTrueに設定されているとき、gluon.main.wsgibaseはミドルウェアの関数gluon.main.appfactoryによってラップされます。それにより"httpserver.log"ファイルへのロギング機能が提供されます。同じようにして、任意のサードパーティ製のミドルウェアを追加することができます。詳細については、公式のWSGIドキュメントを参照してください。

When LOGGING is set to True, gluon.main.wsgibase is wrapped by the middleware functiongluon.main.appfactory. It provides logging to the "httpserver.log" file. In a similar fashion you can add any third party middleware. We refer to the official WSGI documentation for more details.

内部ミドルウェア

Internal Middleware

コ ントローラの任意のアクション(たとえばindex)と任意のサードパーティ製のミドルウェアのアプリケーション(たとえば、出力を大文字に変換する MyMiddleware)が与えられたとき、web2pyのデコレータを用いて、ミドルウェアをそのアクションに適用することができます。これはその例です:

Given any action in your controllers (for example index) and any third party middleware application (for example MyMiddleware, which converts output to upper case), you can use a web2py decorator to apply the middleware to that action. Here is an example:

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

11.

class MyMiddleware:

"""converts output to upper case"""

def __init__(self,app):

self.app = app

def __call__(self,environ, start_response):

items = self.app(environ, start_response)

return [item.upper() for item in items]

@request.wsgi.middleware(MyMiddleware)

def index():

return 'hello world'

すべてのサードパーティ製のミドルウェアが、このメカニズムで動作することは保障できません。

We cannot promise that all third party middleware will work with this mechanism.

WSGIアプリケーションの呼び出し

Calling WSGI Applications

WSGIアプリをweb2pyアクションから呼び出すことは簡単です。これはその例です:

It is easy to call WSGI app from a web2py action. Here is an example:

1.

2.

3.

4.

5.

6.

7.

8.

9.

10.

11.

12.

13.

14.

15.

def test_wsgi_app(environ, start_response):

"""this is a test WSGI app"""

status = '200 OK'

response_headers = [('Content-type','text/plain'),

('Content-Length','13')]

start_response(status, response_headers)

return ['hello world!\n']

def index():

"""a test action that call the previous app and escapes output"""

items = test_wsgi_app(request.wsgi.environ,

request.wsgi.start_response)

for item in items:

response.write(item,escape=False)

return response.body.getvalue()

この場合、indexアクションはtest_wsgi_appを呼んで、戻り値を返す前にそれをエスケープします。index自身はWSGIアプリではなく、普通のweb2pyのAPI(ソケットに書き込むresponse.writeなど)を使用する必要があります。

In this case the index action calls test_wsgi_app and escapes the returned value before returning it. Notice that index is not itself a WSGI app and it must use the normal web2py API (such as response.write to write to the socket.