PEP 3333を日本語訳しました

## この記事の概要

自分でwebサーバを作ってみようと思っていろいろと勉強しています。

仕事ではDjangoを使っているので、言語はやっぱりPythonです。となると、Python製のwebサーバとアプリを接続するためのWSGI規格についても知る必要があります。

PEP 3333はWSGI規格を定義した公式のドキュメントで、PEP 333の後継にあたります。言語的な訓練も兼ねてこれを翻訳してみました。

* 訳していない箇所もありますが、規格の定義に関しては網羅してあります。
* 書き方に一貫性がないところも多いです。
* 間違いがありましたら編集リクエストをください。

[原文はこちら](https://www.python.org/dev/peps/pep-3333/)

↓以下が本文です↓

## 概要

このドキュメントは、webサーバとPython製webアプリ（またはフレームワーク）をつなぐ標準のインターフェイスを定めるものです。目標は、webアプリとさまざまなwebサーバの互換性を向上させることです。

## 理由と目的（PEP 333より）

Pythonのすごいところは、少し数えただけでも、Zope, Quixote, Webware, SkunkWeb, PSO, Twisted Webといったwebアプリ用フレームワークがたくさんあることです。このような膨大な選択肢はPythonの新しいユーザにとっては悩みのタネかもしれません。なぜなら、たいていはwebフレームワークごとに使えるwebサーバが限られてくるし、その逆もしかりだからです。

それとは対象的に、Javaにはたくさんのフレームワークがありますが、「サーブレット」というAPIのおかげで、その仕様さえサポートしてれば、どんなwebフレームワークをどんなwebサーバ上で動かすことも可能です。

このようなAPIがPython向けwebサーバ（これはMudusaのようにPythonで書かれていても、mod_pythonのように埋め込まれていても、CGIやFastCGIのように外部からPythonを実行しても構いません）に備わり、普及すれば、フレームワークとwebサーバの選定が独立するので、ユーザは自由に適切な組み合わせが選べるし、開発者は自分の専門領域に集中できます。

以上のような理由から、このPEPは、webサーバとwebアプリ（フレームワーク）をつなぐ、シンプルで汎用的なインターフェイスを提案します。それがPython Web Server Gateway Interface (WSGI)です。

とはいえ、WSGI規格が存在するだけでは、Python製webアプリのサーバーとフレームワークをとりまく状況は変わりません。
WSGIが効果を発揮するためには、サーバーとフレームワークの開発者たちが実装を行う必要があります。

しかし、既存のサーバやフレームワークでWSGIをサポートしているものは存在しないので、WSGIに対応した開発者はすぐにちょっとした称賛を受けるでしょう。
なのでWSGIは **かならず** 簡単に実装でき、開発者の初期投資が十分低くなければいけません。

そのため、サーバーとフレームワークの *両方の* 実装をシンプルにすることが、WSGIの効用を高めるために絶対に必要であり、仕様策定の原則的な指標になります。

しかし注意しなければいけないのは、フレームワークの開発者にとってシンプルな実装が、webアプリの開発者にとっても便利とは限らないということです。WSGIは「簡素だけど実用的」なインターフェイスのみを提供するものです。なぜなら、レスポンスオブジェクトやクッキーのような便利機能は、既存のフレームワークがとっくに対応しているからです。繰り返しますが、WSGIの目標は、既存のサーバとアプリ（フレームワーク）の相互接続を楽にすることであり、新しいwebフレームワークを作ることではありません。

また、現行のPythonで利用できない機能を、WSGIが必要とすることもない、ということにも留意してください。だから、この規格において、新しい標準ライブラリモジュールが提案されたり要求されたりすることはありません。WSGIが必要とするのはバージョン2.2.2以上のPythonのみです。（しかしながら、将来のバージョンにおいて、標準ライブラリがこのwebサーバ向けインターフェイスをサポートするのはすばらしいことです）

既存の、あるいは将来のフレームワークやサーバが実装しやすいのに加えて、リクエストの前処理やレスポンスの後処理、その他の機能を持つWSGI依存の「ミドルウェア」も簡単に作成できるようにするべきです。こうしたコンポーネントは、サーバからアプリのように見え、アプリにとってはサーバのように振る舞います。

もしミドルウェアがシンプルかつ強力で、WSGIがサーバとフレームワーク界隈で普及していれば、まったく新しいタイプのPython製webアプリフレームワークの可能性がひらけるでしょう。つまり、疎結合な複数のWSGIミドルウェアで構成されたフレームワークです。それどころか、既存のフレームワークの開発者たちさえ、自分たちのフレームワークの機能をそのような形で提供するようになるでしょう。モノリシックなフレームワークではなく、よりライブラリに近い形です。これによりアプリ開発者は、ひとつのフレームワークの長所と短所をすべて受け入れるのではなく、「最高品質」のコンポーネントを特定の機能ごとに選ぶことができるようになります。

もちろん、これを書いている現在からすると、その日は疑いもなく遠いでしょう。
いまのところ、WSGIの短期的な目標は、どんなフレームワークをどんなサーバー上でも使えるようにすることです。

最後に、このバージョンのWSGIは、アプリをサーバ（またはゲートウェイ）と共に「デプロイ」する際の、特定の方法を規定するものではない、ということにも触れておかなければいけません。現在、これはサーバーまたはゲートウェイが実装の中で定義するべきものです。さまざまなデプロイ要件をもつWSGIサーバやフレームワークが十分な実戦経験を積んだら、また別のPEPの中で標準化されるでしょう。


## 規格概要

WSGIインターフェイスには２つの側面があります。「サーバ」あるいは「ゲートウェイ」側と「アプリ」あるいは「フレームワーク」側です。サーバ側は、アプリ側から提供されるcallableオブジェクトを実行します。そのオブジェクトがどのように提供されるかは、サーバ（ゲートウェイ）が決めることです。ある種のサーバ（ゲートウェイ）の場合、アプリをデプロイする人がスクリプトを書く必要があります。その中で、サーバ（ゲートウェイ）のインスタンスを作成し、アプリオブジェクトを渡します。
別のサーバ（ゲートウェイ）では、設定ファイルや他の方法で、アプリオブジェクトをインポートしたり取得したりする方法を指定するものもあります。

「純粋」なサーバ（ゲートウェイ）やアプリ（フレームワーク）に加えて、両サイドを実装する「ミドルウェア」を作ることもできます。そうしたコンポーネントは、サーバ側から見るとアプリのように、アプリ側から見るとサーバのように振る舞います。そして、APIの拡張、コンテンツの変換、ナビゲーションやその他の便利な機能を提供してくれます。

この規格書の中で、「callable」は「関数、メソッド、クラス、インスタンスで、 `__call__` メソッドを持つもの」という意味で使われます。それぞれのサーバ（ゲートウェイ）やアプリが、自分たちの要件に合った方法でcallableを実装することができます。逆に、callableを実行する側は、どのようなcallableが与えられるかに依存しては **いけません** [must not] 。Callableはただ呼ばれる [called] だけであり、中身を知る必要はありません。

### 文字列型についての注意

一般的にHTTPはバイト列を扱います。つまりこの規格はほとんどバイト列についてのものということです。

とはいえ、こうしたバイト列の内容はある種のテキスト的な解釈が必要になることがよくあります。Pythonにおいては、文字列がテキストを扱う上で一番便利な方法です。

しかしPythonの多くのバージョンや実装では、文字列はバイト列ではなくUnicodeです。このため、APIの使いやすさと、HTTPにおけるバイト列とテキストの変換の正確さは、慎重にバランスさせる必要があります。特に、異なる `str` 型の実装を持つPython実装へのコードの移行をサポートする場合はそれが顕著です。

こうした理由から、WSGIは２つの「文字列」を定義しています。

* 「ネイティブ」文字列（常に `str` 型という命名）。リクエスト/レスポンスのヘッダーやメタデータとして使用されます。

* 「バイト列」（Python 3では `bytes` 、その他では `str` ）。リクエストやレスポンスのbodyで使用されます（たとえばPOST/PUTの入力データやHTMLページなど）。

しかし、勘違いをしないように気をつけてください。たとえPythonの「内部で」 `str` 型がUnicodeだったとしても、ネイティブ文字列の *中身* は依然としてLatin-1エンコーディングに変換できなければいけません。（詳細はこのドキュメントで後述される「Unicode問題」の項を参照ください。）

まとめるとこういうことです。このドキュメントで「文字列」という単語があれば、それは「ネイティブ」文字列です。つまり、内部でバイト列であろうとUnicodeであろうと、 `str` 型のオブジェクトを指します。「バイト列」についての言及は、「Python 3なら `bytes`で、Python 2以下なら `str`」と考えてください。

そして、確かにHTTPはある意味「単なるバイト列」ですが、Pythonのデフォルトの `str` 型がなんであっても使用できる便利なAPIをたくさん備えています。

### アプリ・フレームワーク側

アプリオブジェクトは単なるcallableオブジェクトで、２つの引数が渡されます。「オブジェクト」という用語を、いわゆるオブジェクトインスタンスと誤解しないようにしましょう。関数、メソッド、クラス、インスタンスで `__call__` メソッドを持つものなら、すべてアプリオブジェクトとして有効です。アプリオブジェクトは２回以上呼ばれることが可能である必要があります。なぜなら、全てのサーバやゲートウェイは（CGIを除いて）そのような連続のリクエストをする可能性があるからです。

（註： 「アプリ」オブジェクトとは呼んでいますが、アプリ開発者がWSGIをweb制作APIとして使う、という意味に誤解しないようにしましょう。アプリ開発者は、すでにある高レベルのフレームワークを使ってアプリ制作を行います。WSGIはフレームワークやサーバ開発者のためのツールであり、アプリ開発者を直接サポートするためのものではありません。）

アプリオブジェクトとして、２つの例を挙げます。１つは関数で、もう１つはクラスです。

```python
HELLO_WORLD = b"Hello world!\n"

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]

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
```

## サーバ・ゲートウェイ側

サーバ（ゲートウェイ）は、アプリに対するリクエストをHTTPクライアントから受け取るごとに、callableなアプリを１度実行します。説明のために、アプリオブジェクトを受け取る関数として実装された、シンプルなCGIゲートウェイを用意しました。この単純な例ではエラー処理に限界があることに注意してください。なぜなら、デフォルトではキャッチされなかった例外は `sys.stderr` に流れ、webサーバにロギングされるからです。

```python
import os, sys

enc, esc = sys.getfilesystemencoding(), 'surrogateescape'

def unicode_to_wsgi(u):
    # Convert an environment variable to a WSGI "bytes-as-unicode" string
    return u.encode(enc, esc).decode('iso-8859-1')

def wsgi_to_bytes(s):
    return s.encode('iso-8859-1')

def run_with_cgi(application):
    environ = {k: unicode_to_wsgi(v) for k,v in os.environ.items()}
    environ['wsgi.input']        = sys.stdin.buffer
    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):
        out = sys.stdout.buffer

        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
                out.write(wsgi_to_bytes('Status: %s\r\n' % status))
                for header in response_headers:
                    out.write(wsgi_to_bytes('%s: %s\r\n' % header))
                out.write(wsgi_to_bytes('\r\n'))

        out.write(data)
        out.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[1].with_traceback(exc_info[2])
            finally:
                exc_info = None     # avoid dangling circular ref
        elif headers_set:
            raise AssertionError("Headers already set!")

        headers_set[:] = [status, response_headers]

        # Note: error checking on the headers should happen here,
        # *after* the headers are set.  That way, if an error
        # occurs, start_response can only be re-called with
        # exc_info set.

        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()
```

### ミドルウェア： ２役を演じるコンポーネント

ひとつのオブジェクトが、アプリに対してはサーバとして振る舞いつつ、サーバに対してはアプリとして振る舞うこともあります。このような「ミドルウェア」コンポーネントは以下のような機能を持つことができます。

* 目的のURLに応じて、 `environ` を書き換えたあと、リクエストを別のアプリオブジェクトにルーティングする

* 同じプロセスのなかで、複数のアプリ（フレームワーク）を並べて実行 [run side-by-side] できるようにする

* ネットワークごしにリクエストを転送し、ロードバランシングやリモート処理を行う

* XSLスタイルシートの適用など、コンテンツに対する後処理を行う

ミドルウェアの存在は基本的に、サーバ（ゲートウェイ）とアプリ（フレームワーク）の双方から不可視であり、特別な対応を必要としてはいけません。ミドルウェアをアプリに組み込む場合、サーバに対してはミドルウェアがまるでアプリであるかのように認識させ、アプリを実行する際にはミドルウェアがサーバであるかのように設定しておく必要があります。もちろん「アプリ」というのも、実は別のアプリを包み込むミドルウェア、つまり「ミドルウェアスタック」なのかもしれません。

大部分において、ミドルウェアはWSGIにおけるサーバとアプリの両方の制限と要件に従う必要があります。しかし場合によってはミドルウェアの要件は「純粋な」サーバやアプリよりも厳しい場合があります。これについてはこの規格書のなかで後述されます。

冗談みたいな例ですが、以下のミドルウェアはJoe Stroutの `piglatin.py` を使って、 `text/plain` レスポンスを似非ラテン語に変換しています。（註： 「本当の」ミドルウェアはもっと確実な方法でcontent typeをする必要がありますし、content encodingも確認しなければいけません。また、この単純な例では単語がブロック境界 [block boundary] で分割される可能性を無視しています。）

```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 bytestring, 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())   # call must be byte-safe on Py3
        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))   # call must be byte-safe on Py3
                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))
```

## 規格詳細

アプリオブジェクトは２つの位置引数を受けつける必要があります。わかりやすさのために `environ` と `start_response` という名前がついていますが、実際はこれと同じ名前である必要はありません。
サーバ（ゲートウェイ）はアプリオブジェクトを（キーワード引数でなく） **かならず** 位置引数で実行する必要があります。（たとえば、前述の `result = application(environ, start_response` のような呼び出し方です）

`environ` 引数は、CGI形式の環境変数を含んだ辞書オブジェクトです。このオブジェクトは **かならず** Pythonの組み込み型である辞書（サブクラスや `UserDict` や他の辞書を真似たものではありません）でなくてはいけませんし、アプリはその辞書を好きな方法で変更できる必要があります。この辞書にはWSGIに必須な特定の変数（後述）が入っていなくてはいけません。また、サーバ独自の拡張変数をあとで述べるような命名形式で入れることもできます。

`start_response` 引数はcallableであり、２つの必須位置引数と１つの任意引数をとります。わかりやすさのために`status` , `response_headers` そして `exc_info` と命名されていますが、かならずしもこうした名前である必要はありません。ただ、アプリが `start_response` を実行するときは **かならず** 位置引数でおこなう必要があります（例えば `start_response(status, response_headers)` のように）。

`status` 引数はHTTPステータスの文字列であり、 `"999 Message hre"` という形式です。`response_headers` はリストであり、中身はHTTPレスポンスヘッダーを示す `(header_name, header_value)` というタプルです。任意引数である `ecx_info` については、以降の「start_response() Callable」と「例外処理」の項で詳説されています。
これはアプリがエラーをキャッチしたときにのみ使われ、エラーメッセージをブラウザに表示するためのものです。

`start_response` callableは、１つの位置引数を取る `write(body_data)` callableを返す必要があります。この引数は、HTTPレスポンスbodyの一部として書き込まれるバイト列です。（註： `write()` callableは、すでにある特定のフレームワークにとって必須な出力APIをサポートするためだけに存在します。なので、避けられるのであれば、新しいアプリやフレームワークが使う必要はありません。詳細は「バッファリングとストリーミング」の項を参照ください。）

サーバから実行されるとき、アプリオブジェクトは0以上のバイト列をyieldするイテラブルを返さなければいけません。これを実現する方法はいくつも考えられます。たとえば、アプリが文字列のリストを返したり、アプリを、文字列をyieldするジェネレータ関数にするといった方法です。またアプリを、イテラブルなインスタンスを作るクラスとして実装したりすることもできます。
どのような方法で実現するにしても、アプリオブジェクトは常に、0以上の文字列をyieldするイテラブルを返す必要があります。

サーバ（ゲートウェイ）は返ってきた文字列を、 バッファに貯めずに送る必要があります。つまり、すべての文字列を１回のリクエストですべて送信しなければいけません。言言いかえると、アプリは自分自身でバッファリングを行うべき [ **should** ] ということです。アプリの出力方法については、以下の「バッファリングとストリーミング」の項を参照ください。

サーバ（ゲートウェイ）は、その文字列をバイナリ列としてあつかうべきです。特に、行末についてはその逆でないよう気をつけましょう。文字列がクライントむけの正しいフォーマットになっているかを保証するのは、アプリ側の責任です。サーバ（ゲートウェイ）は、HTTP用のエンコーディングを適用したり、他にもbyte-rangeの送信のような、HTTP機能を実現する処理を行うことができます [ **may** ] 。詳細は以下の「その他のHTTP機能」を参照してください。

`len(iterable)` が実行が可能な場合、その結果をサーバ側が精確なものとして信頼できる必要があります。つまり、アプリの返却したイテラブルが実行可能な `__len__()` メソッドを持っていた場合、 **かならず** 正しい値を返す必要があるということです。（この値が一般的にどのような用途に使われるかについては、「Content-lengthヘッダーのあつかいかた」の項を参照してください）

アプリの返却したイテラブルが `close()` メソッドを持っていた場合、サーバ（ゲートウェイ）は現在のリクエストへの対応終了時に **かならず** 呼び出す必要があります。これはリクエストへの対応が正常に終了しても、イテレーション中にアプリ側エラーによって中断しても、ブラウザからの接続が早期に切断されても同様です。（アプリによるリソースの解放を助けることが目的です。この規約は、PEP 342におけるジェネレータや、`close()` メソッドを持つその他のイテラブルを補完するものです。）

ジェネレータやその他のカスタムイテレータを返すアプリは、これらがすべて消費されること前提にするべきではありません [ **should not** ] 。サーバによって早期に閉じられる可能性もある [ **may** ] からです。

（註： アプリの `start_response()` の実行は、 **かならず** イテラブルが最初のbody文字列を生成する前に行う必要があります。そうすることでbodyを読み込む前にサーバがヘッダーを送ることができるからです。しかし、この実行はイテラブルの最初のイテレーションで行われる可能性もあります [ **may** ] 。なのでサーバは、イテラブルのイテレーションを開始するまでは、 `start_response()` がすでに呼ばれているとみなしてはいけません [ **must not** ] 。

最後に、サーバ（ゲートウェイ）は、アプリから返却されたイテラブルの、その他のアトリビュートを直接使ってはいけません [ **must not** ] 。ただし、`wsgi.file_wrapper` から返される「ファイルラッパー」といった、サーバ（ゲートウェイ）固有の型のインスタンスは除きます（「任意のプラットフォーム固有ファイル操作」を参照ください）。たいていの場合、これまでに示されたアトリビュートと、PEP234で定義されたイテレーションAPIのみが使用可能です。

### `environ` 変数

`environ` 辞書は、Common Gateway Interface規格に定義された以下のCGI環境変数を含んでいる必要があります。以下の変数は **かならず** 存在している必要があります。ただし、値が空文字であり、また以下に註記もされていない場合、省略することも **可能** [ may ] です。

`REQUEST_METHOD`

`GET` や `POST` のようなHTTPリクエストメソッド。This
cannot ever be an empty string, and so is always required.

`SCRIPT_NAME`

リクエストURL「パス」のなかで、アプリオブジェクトに対応する初めの部分です。これによりアプリは自分自身の仮想「ロケーション」を知ることができます。アプリケーションがサーバの「ルート」に位置する場合、空文字でも構いません [ **may** ] 。

`PATH_INFO`

リクエストURL「パス」の残りの部分です。アプリ内の仮想「ロケーション」を指定します。リクエストURLがアプリのルートであり、末尾のスラッシュがない場合は空文字でも構いません [ **may** ] 。

`QUERY_STRING`

リクエストURLのうち、 `"?"` の後に続く部分です。
空文字、あるいは存在しない可能性があります。

`CONTENT_TYPE`

HTTPリクエストにおける `Content-Type` の中身です。
空文字、あるいは存在しない可能性があります。

`CONTENT_LENGTH`

HTTPリクエストにおける `Content-Length` の中身です
空文字、あるいは存在しない可能性があります。

`SERVER_NAME` , `SERVER_PORT`


これらの変数を `SCRIPT_NAME` `PATH_INFO` と組み合わせることで、URLを完成させることができます。しかし、 `HTTP_HOST` が存在する場合、 `SERVER_NAME` よりもそちらを優先してURLを再構築するべきです。詳細は「URLの再構築」の項をご覧ください。`SERVER_NAME` と `SERVER_PORT` は絶対に空文字にはならないため、必須項目です。

`SERVER_PROTOCOL`

クライアントがそのリクエストを送るために使っているプロトコルのバージョンです。
これはたいてい `"HTTP/1.0"` または `HTTP/1.1` であり、アプリがHTTPリクエストヘッダーをどのように処理するかを決めるために使用されます。（この変数はおそらく `REQUEST_PROTOCOL` と呼ばれるべきでしょう。なぜならリクエストで使われているプロトコルを示すものであり、サーバからのレスポンスに使われるプロトコルと同じであるとは限らないからです。しかし、CGIとの互換性を保つために既存の名前を使う必要があります。）

`HTTP_` 変数

クライアントから送られるHTTPリクエストのヘッダーに対応する変数です（これらの変数の名前は `HTTP_` から始まります）。これらの変数の在・不在は、リクエスト内の対応するHTTPヘッダーの在・不在と同じです。

サーバ（ゲートウェイ）は、可能なかぎり多くのCGI変数を渡すべきです [ **should** ] 。さらに、SSLが有効な場合、サーバ（ゲートウェイ）は、できるだけ多くのApache SSL変数（`HTTPS=on` や `SSL_PROTOCOL` など）を渡すべきです [ **should** ]。 しかし、先ほどリストアップされたもの以外のCGI変数を使用するアプリは、それらをサポートしないwebサーバ上でかならず動作するとは限りません。たとえば、ファイルを配信しないwebサーバは意味のある `DOCUMENT_ROOT` や `PATH_TRANSLATED` を渡すことができません。

WSGI対応サーバ（ゲートウェイ）は、どのような変数を提供するのかを、定義とともにドキュメント化するべきです [ **should** ] 。アプリはどんな変数が必須なのかを確認し、そうした変数が提供されていない場合の対処法を決めておくべきです [ **should** ] 。

註：欠けている変数、たとえば認証が行われていない状態での `REMOTE_USER` などは、 `environ` 辞書に含めるべきではありません。そして、CGI定義の変数が存在する場合、かならずネイティブ文字列を使うように注意してください。*どんな* CGI変数であれ、 `str` 以外の型を使用するのはこの規格からの逸脱です。

CGIに定義された変数に加え、 `environ` 辞書は、OSの任意の「環境変数」を含むことができます [ **may** ] し、以下のようにWSGIに定義された変数を **かならず** 含まなければいけません。

`wsgi.version`

WSGIバージョン1.0を示すタプル `(1, 0)`

`wsgi.url_scheme`

 アプリが実行されるURLのうち、「スキーマ」を示す部分の文字列。ふつう、これは `"http"` か `"https"` の適切なほうの値が入ります。

`wsgi.input`

HTTPリクエストbodyを読むことのできる入力ストリーム（file-likeオブジェクト）です。サーバ（ゲートウェイ）は、アプリの要求に応じて読み取ることもできますし、先に読んでおいてメモリやディスクに保存しておくこともできますし、好みに応じて他のどのような方法で入力ストリームを渡しても構いません。

`wsgi.errors`

エラー出力を書き込むことができる出力ストリーム（file-likeオブジェクト）です。これは、プログラム上やその他の箇所で発生したエラーを、標準化された形式で、場合によっては特定の場所にまとめて記録するためのものです。
これは「テキストモード」のストリームである必要があります。つまり、アプリ側は `"\n" ` を改行に使い、のちにサーバ（ゲートウェイ）側で適切な形式に変換するということです。

（`str` がUnicodeである環境では、エラーストリームは任意のUnicodeを例外を投げることなく受け付けて出力する **べき** です。しかしストリームのエンコーディングで使用できない場合は別の文字で代用することが可能です。）

多くのサーバにとって、 `wsgi.erros` はメインのエラーログになるはずです。別の方法としては、 `sys.stderr` やログファイルを用いることもできます。サーバのドキュメントは、設定方法と記録場所について説明をする必要があります。サーバ（ゲートウェイ）は、必要であればアプリごとに別のエラー出力を提供することもできます。

`wsgi.multithread`

アプリオブジェクトが、同じプロセス内の別のスレッドで同時に実行される場合、この値はtrueであり、そうでなければfalseです。

`wsgi.multiprocess`

同じ働きをするアプリオブジェクトが、別のプロセスから実行される場合、この値はtrueであり、そうでなければfalseです。

`wsgi.run_once`

プロセスの生存期間のなかで、サーバ（ゲートウェイ）が、アプリを１度だけ実行することが期待される（しかし保証されない）場合、この値はtrueです。一般に、この値がtrueになるのは、CGI（またはそれに類するもの）に依拠したゲートウェイのみです。

最後に、 `environ` 辞書はサーバ側で定義された変数も持つことができます。これらの変数は、小文字、数字、ドット、アンダースコアのみを使用し、サーバ（ゲートウェイ）の名前でユニークにプリフィックスされているべきです。たとえば `mod_python` なら、 `mod_python.some_variable` のように変数を定義するとよいでしょう。

### 入力とエラーストリーム

サーバが提供する入力とエラーのストリームは、以下のメソッドを実装している必要があります。

| Method | Stream | Notes |
| ---- | ---- | ---- |
| `read()size` | `input` | 1 |
| `readline()` | `input` | 1, 2 |
| `readlines(hint)` | `input` | 1, 3 |
| `__iter__()` | `input` | |
| `flush()` | `errors` | 4 |
| `write(str)` | `errors` | |
| `writelines(seq)` | `errors` | |

各メソッドの意味はPython Library Referenceに記載されているとおりですが、上記の表に示された註には気をつけてください。

#### 1

サーバはクライアントの指定した `Content_Length` のサイズを超えて読みこむ必要はありませんし、アプリ側がそれ以上読み込もうとした場合は、サーバ側はファイルの終端に達したとみなすべき [should] です。
アプリは `CONTENT_LENGTH` で指定されたデータ量を越えて読み込もうとするべきではありません [ **should not** ] 。

サーバは `read()` を引数なしで実行できるようにし、クライアントの入力ストリームの残り全てを返すようにするべき [should] です。

空の、または読み尽くされた入力ストリームを読み込もうとする場合、サーバはつねに空のバイト列を返すべき [should] です。

#### 2

サーバは任意引数の `size` を取る `readline()` をサポートするべき [should] です。ただ、これは WSGI 1.0では省略することが可能でした。

（WSGI 1.0では、実装が複雑になるわりにはあまり実用されないという理由で、size引数はサポートされていませんでした。しかし、 `cgi` モジュールがそれを使うようになったため、実用的なサーバーはなんにせよサポートを始める必要があります）

#### 3

`readlines()` の受け付ける引数である `hint` は、実装する側にとっても呼び出す側にとっても任意です。アプリ側は提供してもいいですし、サーバ（ゲートウェイ）側は無視することができます。

#### 4

`errors` ストリームを巻き戻すことはないので、サーバ（ゲートウェイ）はバッファリングすることなく即座に書き込み処理をおこなうことができます。
なので、この場合 `flush()` メソッドはno-opになります。しかし、アプリの移植性を維持するなら、出力がバッファリングされていないとか、 `flush()` がno-opであると決めつけることはできません。出力が確実に書き込まれていることを保証したい場合、かならず `flush()` を呼ぶ必要があります。（たとえば、複数プロセスが同じエラーログに書き込むさいに、データが混じってしまうことを避けたいときなど）

この規格にしたがうサーバは、上記のメソッドを **かならず** サポートしている必要があります。この規格にしたがうアプリは、上記以外のメソッドや、前述した `input` `errors` オブジェクトの属性以外は **絶対に** 使ってはいけません。特に、これらのストリームが `close()` メソッドを持っていたとしても、アプリは **絶対に** 閉じようとしてはいけません。

### `start_response()` Callable

アプリオブジェクトに渡される２つ目の引数は、 `start_resnpose(status, response_headers, exc_info=None)` という形式のcallableです。
（他のWSGI callableと同様に、引数はキーワードでなく位置指定で渡される必要があります。）`start_response` callableはHTTPレスポンスを開始するために実行され、かならず `write(body_data)` callableを返す必要があります（後述の「バッファリングとストリーミング」の項を参照ください）。

`status` 引数は、 `"200 OK"` や `"404 Not Found"` のようなHTTPステータスの文字列です。つまり、Status-CodeとReason-Phreseが上記のような順番でならび、１つのスペースが挟まり、両端に空白や他の文字がくっついていない文字列です。
（詳しくはRFC 2616のセクション6.1.1を参照ください。）この文字列は **絶対に** 制御文字を含んでいてはいけませんし、 キャリッジリターン、ラインフィード、またはその両方で終端してはいけません。

`response_headers` 引数は、 `(header_name, header_value)` というタプルのリストです。これはかならずPythonのリストである必要があります。つまり、 `type(response_heanders) is ListType` であり、サーバはその中身を好きなように変更することができます [ **may** ] 。それぞれの `header_name` は有効なHTTPヘッダーのフィールド名（RFC 2616, Section 4.2で定義されています）でなければいけませんし、終端にコロンや他の記号をつけてはいけません。

それぞれの `header_value` は **どんな** 制御記号も、キャリッジリターンやラインフィードも例外なく、途中であれ終端であれ **絶対に** 含んでいてはいけません。
（こうした規定は、サーバ、ゲートウェイあるいはその中間でレスポンスを変更するソフトウェアが、応答ヘッダーを調べたり変更するさいの、パース作業の複雑さを軽減するためのものです。）

一般的に、正しいヘッダーがクライアントに送られることを保証するのは、サーバ（ゲートウェイ）側の役割です。アプリがHTTP（またはその他の有効な規格）に定義された必須のヘッダーを省略した場合、サーバ（ゲートウェイ）は **かならず** 補う必要があります。たとえば、 `Date` や `Server` といったヘッダーはふつうサーバ（ゲートウェイ）から提供されるものです。

（サーバやゲートウェイを作成している人へ。HTTPヘッダーの命名は小文字と大文字を区別しません。なので、アプリから渡されたヘッダーを調べるときはそのことを肝に命じておきましょう。）

HTTP/1.1以降、アプリやミドルウェアは、「ホップバイホップ」機能やヘッダー、HTTP/1.0における同様の機能、またクライアントとwebサーバの接続の持続性に影響をあたえるヘッダーを使用することは禁止されています。これらの機能は実際のwebサーバのあつかう領域であり、サーバ（ゲートウェイ）は、アプリがこれらを送ってくる場合は致命的なエラーとみなし、例外を投げるべき [ **should** ] です。「ホップバイホップ」機能やヘッダーの詳細については、以下の「その他のHTTP機能」の項を参照ください。

サーバは `start_response` が呼ばれた際にヘッダーのエラーをチェックする **べき** です。これによってアプリが走っている間にエラーを投げることができます。

しかし、 `start_response` callableは **絶対に** レスポンスヘッダーを実際に送信してはいけませんそうではなく、ひとまずはサーバ（ゲートウェイ）のために保管しておかなければならず、送信が可能になるのは、アプリが最初のイテレーションを終えて空文字以外の文字列を生成した後、あるいはアプリが最初に `write()` callableを実行したとき **のみ** です。言いかえると、実際のbodyデータが使用できるようになるまで、またはアプリの返したイテラブルを読み尽くすまで、レスポンスヘッダーは送信してはいけない、ということです。（このルールの唯一の例外は、レスポンスヘッダーのなかで、`Content_Length` がゼロと明示されている場合です。）

このようにレスポンスヘッダー送信を遅延させるのは、バッファリングされた非同期アプリが、最後の最後まで、当初意図していた出力をエラー出力で上書きできるようにするためです。たとえば、bodyがアプリのバッファ内で生成されている最中にエラーが発生した場合、アプリはレスポンスのステータスを"200 OK"から"500 Internal Error"に変更する必要があるでしょう。

`exc_info()` 引数は、もし渡されているのなら、Pythonの `sys.exc_info()` のタプルです。この引数は、 `start_response` がエラーハンドラによって呼ばれているときのみ、アプリから返されます。`exc_info` が返され、そしてHTTPヘッダーがまだ出力されていない場合、 `start_response` はすでに保存されているHTTPレスポンスヘッダーを新しいものに書き換える必要があります。そうすることで、エラー発生時に、アプリが出力に関して「心変わり」することができます。

しかし、 `exc_info` が返され、すでにHTTPヘッダーが送信されている場合、 `start_resnponse` は **かならず** 例外を投げ、 **できれば** [should] `exc_info` タプルを使って再送出するべきです。つまり以下のようにします。

```python
raise exc_info[1].with_traceback(exc_info[2])
```

このコードは、アプリ側で捉えられた例外を再送出し、原則的にはアプリを中断させます。（HTTPヘッダーがすでに送信されたあとにエラーを出力するのは、アプリにとって安全ではありません。）`start_response` が `exc_info` 引数とともに呼ばれた場合、 アプリは `start_response` から投げられた例外を **絶対に** 捕捉してはいけません。かわりに、そうした例外はサーバ（ゲートウェイ）に伝搬するにまかせしょう。詳細は以下の「例外処理」の項を参照してください。

アプリは、 `exc_info` 引数が与えられている場合に限り、 `start_response` を２回以上呼ぶことが可能 [may] です。より詳しくいえば、アプリが実行されてすでに `start_response` が呼ばれているにもかかわらず、 `start_response` を `exc_info` 引数なしで再度呼ぶのは致命的なエラーです。これは、`start_response` の最初の呼び出しがエラーを投げてしまうケースを含みます。（正しいロジックの説明は上記のCGIゲートウェイの例を参照ください。）

註： `start_response` を実装するサーバ、ゲートウェイ、ミドルウェアは、関数実行の期間を越えて `exc_info` への参照を保持するべきではありません。これはトレースバックとそれに関わるフレームの循環参照を避けるためです。もっともシンプルなやり方は以下のようなものです。

```python
def start_response(status, response_headers, exc_info=None):
    if exc_info:
            try:
                # do stuff w/exc_info here
            finally:
                exc_info = None    # Avoid circular ref.
```

前述のCGIゲートウェイのコードはこのテクニックを使った別の例です。

### `Content-Length` ヘッダーの扱いかた

アプリが `Content-Length` ヘッダーを返す場合、サーバーはヘッダーが示すより多くのデータを送信する **べきではありません** し、すでに十分なデータが送信されている場合はレスポンスのイテレーションをやめる **べき**です。また、アプリがそのデータ量を越えて `write()` を実行しようとする場合は例外を投げるべきです。（もちろん、アプリが `Content-Length` に対応する *十分な* データ量を返さない場合、サーバは接続を閉じてログやその他の方法でエラーを通知する **べき** です。）

アプリが `Content-Length` ヘッダーを返さない場合、サーバ（ゲートウェイ）はいくつかの方法のうち１つで対応することができます。もっとも単純なのは、レスポンスの終了とともに、クライアントとの接続を閉じることです。

しかし特定の状況において、サーバ（ゲートウェイ）は `Content-Length` ヘッダーを追加するか、最低でもクライアントとの接続を保ちつづける必要があります。アプリが `write()` callableを呼ばず、 `len()` が1のイテラブルを返す場合、サーバはそのイテラブルの返す最初のバイト列の長さが `Content-Length` であると自動的にみなすことができます。

また、サーバとクライアントの両方がHTTP/1.1の「chunked encoding」に対応している場合、サーバは `write()` の呼び出しごとのチャンクや、イテラブルの生成するバイト列を、chunked encodingで送信することが **可能** です。この場合、 `Content-Length` ヘッダーはそれぞれのチャンクごとに生成します。これにより、サーバは必要であればクライアントとの接続をキープすることができます。この場合、サーバはRFC2616を遵守する必要があることに留意してください。さもなければ、`Content-Length` の不在に対応する他の方法を選びましょう。

（註： アプリやミドルウェアは、出力に対して `Transfer-Encoding` に類するものを **絶対に** 適用してはいけません。例えばチャンク化やgzip化などです。「ホップバイホップ」と同様に、こうしたエンコーディングは実際のwebサーバやゲートウェイの範疇だからです。詳細は「その他のHTTP機能」を参照ください。

### バッファリングとストリーミング

一般的に、アプリが最良のスループットを発揮するのは、（適切なサイズの）出力をバッファリングして一度にすべて送信する場合です。これはZopeのような既存のフレームワークで一般的な方法です。出力はStringIOのようなオブジェクトに貯められ、レスポンスヘッダーとともに一挙に送信されます。

WSGIにおけるアプローチでは、アプリはバイト列のレスポンスbodyを、単一のイテラブル（リストなど）に投入して返却するだけです。この方法は、メモリに容易に収まる程度のHTMLを描画するような、アプリに大半の機能に適しています。

しかし巨大なファイルや、（multipartのserver pushなどの）HTTPストリーミングといった特殊用途の場合、アプリは小さなブロックに分けて出力しなくてはならない場合があります（たとえば巨大なファイルをメモリに読み込みたくないときなど）。また、レスポンスのうち一部の生成に時間がかかるが、他の部分は先に返してしまいたい場合もあります。

これらのケースでは、アプリはイテレータ（多くの場合ジェネレータ）を返し、それがブロックごとの内容を出力していくというのが一般的です。こうしたブロックはmultipart境界（server pushの場合）と同時に、あるいは時間のかかる作業（ディスク上の別のブロックを読み込むような）の直前に分割される可能性があります。

WSGIサーバ、ゲートウェイ、ミドルウェアはどんなブロックの送信も **絶対に** 遅らせてはいけません。ブロックをクライアントへすべて送信するか、アプリが次のブロックを生成している間も送信を続けることを **かならず** 保証しなければいけません。
サーバ（ゲートウェイ）またはミドルウェアは、この保証をするために次の３つの方法のうち１つを選ぶことができます。

1. アプリにコントロールが移る前に、すべてのブロックをOSに送る（そしてすべてのO/Sバッファをフラッシュするよう要請する）。

2. アプリが次のブロックを生成している間、別のスレッドでブロックの送信を続ける。

3. （ミドルウェアのみ）すべてのブロックを親ゲートウェイまたは親サーバに送る。

このような保証をすることで、WSGIはアプリの出力データ送信が特定の箇所で行き詰まらないようにできます。これは、たとえばmultipart server pushストリーミングのように、データをmultipart境界に挟んでクライアントに送信しなければいけない場合、正常な動作のために欠かせないことです。

ミドルウェアによるブロック境界の扱いかた

非同期のアプリとサーバをよりよくサポートするため、ミドルウェアは、アプリのイテラブルから複数の値を取得しようと待機しては **絶対に** いけません。ミドルウェアが出力を行う前に、アプリからのデータを集積する必要がある場合、、**かならず** 空のバイト列をyieldする必要があります。

この要件を別の言い方にするならば、アプリが１つの値をyieldするたび、ミドルウェアは **かならず、最低でも１つの値をyieldしなければならない** ということです。ミドルウェアがyieldする値を持たない場合、バイト列をyieldする必要があります。 

この要件は、非同期アプリとサーバが協力し、同時に複数のアプリのインスタンスを走らせるときに必要なスレッドの数を削減するために必要です。

同時にこの要件は、ミドルウェアは、アプリが返却したイテラブルを受け取ったら、 **かならず** すぐにイテラブルを返却しなければいけない、ということも意味します。また、ミドルウェアが、アプリのyieldしたデータを送信するために `write()` callableを使うことは禁止されています。ミドルウェアが親サーバの `write()` callableを使ってデータを送信するのは、アプリもミドルウェアの提供した `write()` callableを使った場合のみです。

### `write()` Callable

いくつかの既存のアプリフレームワークのAPIは、WSGIとは違う方法でバッファリングしない出力をサポートしています。具体的には、バッファリングしないデータブロックを書き込むための「write」関数やメソッドを提供したり、または、バッファリングされた「write」関数とバッファのフラッシュを行うための「flush」機構を提供しています。

残念ながらこうしたAPIは、スレッドやその他の特殊な機構がない限り、WSGIアプリが返す「イテラブル」な値を使用して実装することはできません。

なのでこれらのフレームワークが重要なAPIを使用しつづけられるように、WSGIには、`start_response` から返却される `write()` という特別なcallableがあります。

新しいWSGIアプリやフレームは、必須でないのなら `write()` callableを使用する **べきではありません** 。`write()` callableは厳密にいうと、どうしても必要なストリーミングAPIをサポートするための一種のハックです。一般的に、アプリは自分の出力をイテラブルとして返すべきです。こうすることで、webサーバと同じPythonスレッド内に別のタスクをはさむことができ、全体としてスループットの向上が期待できるからです。

`write()` callableは `start_response()` callableの返り値であり、１つの引数をとります。これはHTTPレスポンスbodyの一部として書き込まれるバイト列であり、イテラブルからyieldされた場合と完全に同じあつかいをうけます。言いかえると、 `write()` が返却されるよりも前に、渡されたバイト列はすべてクライアントに送られているか、アプリの処理が進む間に送信できるように、バッファに入れておく必要があるということです。

レスポンスbodyをすべて `write()` から生成するとしても、アプリは **かならず** イテラブルオブジェクトを返す必要があります。
返却されるイテラブルは空でも構いません [ **may** ] （つまり中身のあるバイト列をyieldしない）。しかし、もし中身のあるバイト列をyield *する* のであれば、その出力はサーバ（ゲートウェイ）に通常と同じようにあつかわれる必要があります（つまり送信されるか、即座にキューに入れられる必要がある）。アプリは、自分の返したイテラブルのなかから `write()` を **絶対に** 実行してはいけません。なので、イテラブルからyieldされたバイト列は、`write()` に渡されたバイト列がすべてクライアントに送られた後に送信されます。

### Unicode問題

HTTPがUnicodeを直接サポートしていないので、この規格も同様にサポートしません。エンコーディングやデコーディングはアプリによって処理される必要があります。つまり、サーバとやりとりする際の文字列の型は、かならず `str` か `bytes` でなくてはならず、 `unicode` であってはいけません。文字列オブジェクトが必要な場所で `unicode` オブジェクトを使った際の挙動は定義されていません。

また、httpステータスやレスポンスヘッダーとして `start_response()` に渡される文字列は、 **かならず** RFC2616で指定されたエンコーディングに従う必要があります。
つまり、ISO-8859-1の文字か、RFC 2047 MIMEエンコーディングのどちらかでなくてはいけません。

`str` や `StringType` 型をUnicodeベースであつかっているPythonプラットフォーム（たとえばJython, IronPython, Python3など）の場合、この規格書のなかで使用されているすべての「文字列」は、ISO-8859-1エンコーディング（`\u0000` から `\n00FF` まで）で表現できるコードポイントのみ使用できます。このほかのUnicode文字やコードポイントをふくむ文字列を渡すことは、アプリの致命的なエラーです。
同様に、サーバ（ゲートウェイ）も上記以外のUnicode文字を **絶対に** 渡してはいけません。

繰り返しますが、この規格書で「文字列」として言及されているすべてのオブジェクトは **かならず** `str` か `StringType` であり、**絶対に** `unicode` や `UnicodeType` ではありません。そして、たとえ使用しているプラットフォーム上で `str` や `StringType` 8bitより大きい文字を使用できたとしても、この規格書における「文字列」は下位8bitのみを使用します。

この規格書で「バイト列」として言及されている値（つまり `write()` に渡される `wsgi.input` から読み出される値や、アプリからyieldされる値）については、**かならず** Python 3では `bytes` 、それより前のバージョンでは `str` でなければいけません。

### エラー処理

一般的に、アプリは内部で発生したエラーを捕捉し、ブラウザ上に親切なメッセージを表示する **べき** です。（なにが「親切」かは状況に応じてアプリが決めることです。）

しかし、そのようなメッセージを表示するためには、すでにアプリがブラウザにデータを送ってしまっていては問題があります。レスポンスを破壊するおそれがあるからです。これを避けるため、WSGIは、アプリがエラーメッセージを送信するか、さもなければ自動的に停止する機構を提供します。 `start_response` に渡される `exc_info` のことです。以下がその使用例です。

```python
try:
    # regular application code here
    status = "200 Froody"
    response_headers = [("content-type", "text/plain")]
    start_response(status, response_headers)
    return ["normal body goes here"]
except:
    # XXX should trap runtime issues like MemoryError, KeyboardInterrupt
    #     in a separate handler before this bare 'except:'...
    status = "500 Oops"
    response_headers = [("content-type", "text/plain")]
    start_response(status, response_headers, sys.exc_info())
    return ["error body goes here"]
```

例外発生時にまだなにも出力されていない場合、 `start_response` の呼び出しは正常にリターンし、アプリはエラー内容をブラウザに送信をします。しかし、すでになんらかの出力がブラウザに送信されてしまっている場合、 `start_response` は渡された例外を再送出します。アプリの動作を中断させるため、この例外はアプリによって捕捉される **べきではありません** 。サーバ（ゲートウェイ）はこの（致命的な）例外を補足し、レスポンスを中断することができます。

サーバは、アプリ本体やアプリの返したイテレーションで発生した例外をすべて補足し、ロギングする **べき** です。もしアプリがエラーを発生させたとき、すでにレスポンスの一部がブラウザーまで届いていた場合、サーバ（ゲートウェイ）はエラー情報を出力に付けくわえても **構いません** 。すでに送られたヘッダーが `text/*` のcontent typeを指定しており、サーバがただしく改変することができるならば可能です。

ミドルウェアによっては、追加の例外処理を提供したり、アプリ側のエラー情報をキャッチして置換したい場合もあると思います。そういった場合、ミドルウェアは `start_resopnse` に渡された `exc_info` を再送出する **のではなく** 、代わりにミドルウェアの規定した例外を投げたり、受け取った引数を保存したあとで例外を投げずリターンすることができます。こうすることで、ミドルウェアにエラー出力を改変させた上で、アプリはエラー内容のイテラブルを返す（あるいは `write()` を実行する）ことができます。こうした手法は、アプリが以下のような処理をしている限り有効です。

1. エラーのレスポンスを始める際、常に `exc_info` を渡している。

2. `exc_info` が渡される際、 `start_resnponse` で発生した例外を捕捉しない。

## HTTP 1.1 Expect/Continue

HTTP 1.1を実装するサーバ（ゲートウェイ）は、 **かならず** HTTP 1.1 の「expect/continue」機構を明確にサポートをしなければいけません。これは以下のうちのどれかの方法で達成できます。

1. `Expect: 100-continue` を含んだリクエスト群に対しては、即時に「100 Continue」レスポンスを返し、通常どおり処理を進める。

2. リクエストの処理を通常どおり進めるが、アプリが最初に `wsgi.inputh` ストリームから読み込もうとしたとき、そのストリームから「100 Continue」レスポンスを送るようにする。その読み込みリクエストは、クライアントが応答するまでブロックされていなくてはならない。

3. サーバが expect/continueに対応していないとクライアントがみなすまで待機し、自分のリクエストbodyをクライアントに送信する。（これは次善策であり、推奨されない。）

こうした挙動の制限はHTTP 1.0や、アプリオブジェクトに向けられていないリクエストには適用されないことに注意してください。HTTP 1.1 Expect/Continueの詳細については、RFC 2616, sections 8.2.3と10.1.1を参照ください。

## HTTPのその他の機能

一般的に、サーバ（ゲートウェイ）は「黙って」いるべきで、出力はすべてアプリの支配下で完成させるものです。変更を加えることができるとすれば、アプリの応答の意味を大きく改変しない場合に限ります。アプリ開発者にとっては、さらなる機能を提供したい場合はいつでもミドルウェアを追加できます。なので、サーバ（ゲートウェイ）の開発者はそうした実装に慎重であるべきです。ある意味では、サーバは、自分自身をHTTPの「ゲートウェイサーバ」とみなすべきで、その場合アプリはHTTPの「オリジンサーバ」にあたります。（こうした用語の定義についてはRFC 2616, section 1.3を参照ください）

しかし、WSGIサーバとアプリはHTTPで通信するわけではないので、RFC 2616でいうところの「ホップバイホップ」ヘッダーはWSGIの内部通信には適用されません。WSGIアプリは、このようなヘッダーを生成する必要のあるHTTP機能を使ったり、 `environ` 辞書に含まれた「ホップバイホップ」ヘッダーに依拠しようとしては **絶対に** いけません。
WSGIサーバは、送られてくる有効な「ホップバイホップ」ヘッダーを **かならず** 自分自身で処理する必要があります。たとえば、もし有効ならchunked encodingも含め、送られてきた `Transfer-Encoding` をすべてデコードするということです。

これらの原則をHTTPのさまざまな機能に適用することで、`If-None_match` と `If-Modified-Since` といったリクエストヘッダーと `Last-Modified` と `ETag` といったレスポンスヘッダーを使ってキャッシュ確認を担当するのが **おそらく** サーバである、ということが明確になります。しかし、これに関しては絶対にそうする必要はなく、もしアプリ側で対応したいのであれば、アプリがキャッシュの確認を行う **べき** です。かならずしもサーバ（ゲートウェイ）がそうした確認をする必要はないからです。

同様に、サーバはアプリの応答の再エンコードやトランスポートエンコードをおこなうことが **可能** です。コンテンツエンコーディングはアプリが自分で行う **べき** ですが、トランスポートエンコーディングは **絶対に** 適用してはいけません。クライアントからの要望があり、またアプリが自分自身でbyte rangesに対応していない場合、サーバはアプリのレスポンスのbyte rangesを送信する **ことができます** 。しかし繰り返しますが、望むのならばアプリ自身がこの機能を果たす **べき** です。

アプリに対するこれらの制限は、かならずしもすべてのアプリがすべてのHTTP機能を再実装しなければならないという意味ではありません。多くのHTTP機能は、その一部あるいは全部をミドルウェアで実装することができるので、サーバとアプリの両方の開発者は、同じ機能を何度も開発し直す必要はありません。

### スレッドのサポート

スレッドに対応するかしないかはサーバによります。
複数のリクエストを並列で実行できるサーバでも、アプリをシングルスレッドで走らせるオプションを提供するべきです。そうすることで、スレッドセーフでないアプリやフレームワークもそのサーバを使用できるからです。

## 実装とアプリケーションに関して

### サーバ拡張API

サーバによっては、アプリやフレームワークの開発者が特殊な用途で使えるような、さらに高度なAPIを提供したいかもしれません。
たとえば、 `mod_python` にもとづいたゲートウェイは、Apache APIの一部をWSGI拡張として提供したいかもしれません。

もっとも単純なケースでは、 `mod_python.some_api` のような `environ` 変数を定義する以上は必要ないかもしれません。しかし多くの場合、ミドルウェアの存在がものごとを複雑化します。
たとえば、`environ` 変数内の特定のHTTPヘッダーにアクセスできるAPIの場合、 `environ` はミドルウェアに改変されている可能性があります。

一般的に、WSGIの機能の一部分を重複させたり、置き換えたり、迂回するような拡張APIは、ミドルウェアとの互換性を損なうリスクがあります。サーバ（ゲートウェイ）の開発者は、誰もミドルウェアを使わないなどと推測してはいけません。なぜなら、いくつかのフレームワークは、そのほぼすべてを多様なミドルウェアの組み合わせとして構築・再構築して機能させているからです。

なので、最大限の互換性を提供するため、WSGIの機能の一部を置き換える拡張APIを提供しようとするサーバやゲートウェイは、その拡張APIを実行する際に、置き換えられた側のAPIの一部を使用するようにデザインしなければいけません [ **must** ] 。たとえば、HTTPリクエストヘッダーにアクセスする拡張APIは、アプリケーションに対し、現在の `environ` を渡すように強制する必要があります。こうすることで、サーバ/ゲートウェイは、API経由でアクセス可能なHTTPヘッダーがミドルウェアによって改変されていないことを検証できます。もし `environ` の中に入っているHTTPヘッダーを拡張APIが許容できない場合、アプリに対してサービスの提供を拒否する必要があります。たとえば例外を投げたり、ヘッダーのコレクションのかわりに `None` を返したり、APIに適した方法を取ります。

同様に、拡張APIが応答データやヘッダーを書き込むための代替手段を提供する場合、アプリ側に拡張サービスを使わせる前に、 `start_response` callbleを渡すように要求する必要があります。もし渡されたオブジェクトが、サーバ/ゲートウェイが最初にアプリに与えたものと異なった場合、正常な操作が保証されないため、拡張サービスの提供は拒否する必要があります。

こうしたガイドラインは、解析済みクッキー、フォーム変数、セッションのような `environ` を追加するミドルウェアにも適用されます。具体的には、このようなミドルウェアはこれらの機能を、 `environ` を操作する関数として提供するべきであり、単純に値を追加するべきではありません。これは、 `environ` からの情報の取得は、ミドルウェアによるURLの書き換えやその他の変更の *後に* 行われるということを保証するためです。

こうした「安全な拡張」のルールを、サーバ/ゲートウェイ側とミドルウェア側の両方の開発者が尊重するのは非常に大切です。ミドルウェアの機能が `environ` の拡張APIによってバイパスされることを避けるために、開発者がすべての拡張API削除せざるをえない、というような未来は避けなくてはなりません。

### アプリ設定

この規格書は、実行するアプリをサーバがどのように選んだり取得するか、ということは定義しません。こうした設定項目はそれぞれのサーバ固有の問題です。サーバ/ゲートウェイの開発者には、どのような方法で実行するアプリオブジェクトを設定するのか、またどのようなオプション（たとえばスレッドなど）があるのかをドキュメント化することが求められます。

逆にフレームワークの開発者は、フレームワークの機能を包み込むアプリオブジェクトをどのように生成するのかをドキュメント化する必要があります。サーバとアプリフレームワークを選択したユーザは、この２つを接続しなければいけません。しかし、いまフレームワークとサーバは共通のインターフェイスを持っているので、新たに触れるサーバ/フレームワークのペアであって、必要になるのは面倒な開発ではなく機械的な作業に過ぎないはずです。

最後に、特定のアプリやフレームワーク、ミドルウェアは `environ` 辞書を使ってシンプルな文字列の設定オプションを受け取りたいはずです。サーバやゲートウェイは、アプリのデプロイ時に名前-値のペアを `environ` に挿入できるようにすることで、これをサポートする **べき** です。もっとも単純なやりかたは、OSの提供する環境変数をただ `os.environ` から `environ` 辞書にコピーするというものです。デプロイをする際はふつう外部からサーバを設定できますし、CGIの場合もサーバの設定ファイルからセットできるはずです。

アプリはこのような必須の変数を最小限に抑える **べき** です。なぜならすべてのサーバが簡単な設定手段を持っているとは限らないからです。最悪のケースでは、デプロイ担当者が必要な設定値をスクリプト内で書き加えるということになります。

```python
from the_app import application

def new_app(environ, start_response):
    environ['the_app.configval1'] = 'something'
    return application(environ, start_response)
```

ただ、ほとんどの既存アプリやフレームワークでは、固有の設定ファイルのパスを示す値のみが必要になるはずです。（もちろん、アプリ実行ごとに読み込みが行われないように、設定値をキャッシュしておく必要があります。）

### URLの再構築

リクエストされたURLをアプリが完全に再構築する場合、Ian Bickingの提案する以下のアルゴリズムを使用するといいでしょう。

```python
from urllib.parse import quote
url = environ['wsgi.url_scheme']+'://'

if environ.get('HTTP_HOST'):
    url += environ['HTTP_HOST']
else:
    url += environ['SERVER_NAME']

    if environ['wsgi.url_scheme'] == 'https':
        if environ['SERVER_PORT'] != '443':
            url += ':' + environ['SERVER_PORT']
    else:
        if environ['SERVER_PORT'] != '80':
            url += ':' + environ['SERVER_PORT']

url += quote(environ.get('SCRIPT_NAME', ''))
url += quote(environ.get('PATH_INFO', ''))
if environ.get('QUERY_STRING'):
    url += '?' + environ['QUERY_STRING']
```

このように再構築されたURLが、クライアントからのリクエストとかならずしも完全に一致するとは限らない、ということには注意してください。たとえばサーバが書き換えを行っており、クライアントのもともとのURLを正規化しているかもしれません。

### プラットフォーム依存の任意のファイル操作

特定のOS環境は特殊な高性能ファイル送信機能を備えています。たとえばUnixにおける `sendfile()` システムコールなどがそうです。
サーバやゲートウェイはこの機能を `environ` 内の `wsgi.file_wrapper` として提供してもいい [ **may** ] でしょう。アプリはこの「file wrapper」を使用して、fileやfile-likeオブジェクトをイテラブルに変換して返してもいい [ **may** ] でしょう。

```python
if 'wsgi.file_wrapper' in environ:
    return environ['wsgi.file_wrapper'](filelike, block_size)
else:
    return iter(lambda: filelike.read(block_size), '')
```

サーバやゲートウェイが `wsgi.file_wrapper` を提供する場合、それは１つの必須位置引数と１つの任意位置引数を取るcallableでなければいけません。ひとつめの引数が送信されるfile-likeオブジェクトで、２つ目がブロックサイズの「提案」です（つまりサーバ/ゲートウェイはかならずしも使う必要がありません）。このcallableは **かならず** イテラブルオブジェクトを返さなければいけませんし、サーバ/ゲートウェイがアプリから実際に戻り値を受け取るまでは、 **絶対に** データの送信を行ってはいけません。
（そうしてしまった場合、ミドルウェアが応答データを解析したり上書きすることを妨げる可能性があります。）

「file-like」であるためには、アプリから返されるそのオブジェクトは、１つの任意のsize引数を取る `read()`メソッドを持っている必要があります。
`close()` を持っていても **かまわない** です。その場合、 `wsgi.file_wrapper` から返されるイテラブルは、file-likeオブジェクトが持っていたもともとの `close()` を呼ぶ `close()` メソッドを **かならず** 実装していなくてはいけません。もし「file-like」オブジェクトが、Pythonの組み込みのfileオブジェクトのメソッドやアトリビュートと同じもの（たとえば `fileno()`）を持っていた場合、 `wsgi.file_wrapper` はこれらが組み込みのfileオブジェクトと同じ意味を持っているとみなして **かまいません** 。

プラットフォーム依存のファイル操作は、かならずアプリが実行を終えて、サーバやゲートウェイがwrapperオブジェクトが返却されたことを確認した **あとで** 行われなければいけません。（繰り返しになりますが、ミドルウェアやエラー処理なども存在するため、wrapperが使用されることが保証されるわけではありません。）

`close()` に限らず、アプリから返ってくるfile wrapperは `iter(filelike.read,)` が返却された場合と同じ意味を持つと考えるべきです。言いかえれば、ファイル送信は、送信が始まった時点での「file」の現在位置から始まり、終端に達するまで、あるいは `Content-Length` のデータが書き込まれるまで続きます。（もしアプリが `Content-Length` を提供しない場合、サーバはfileの実装の情報をもとに、自分で生成しても **かまいません** 。）

もちろん、プラットフォーム依存のファイル送信APIは、一般的に任意の「file-like」オブジェクトを受け付けません。なので `wsgi.file_wrapper` は、渡されたオブジェクトの `fileno()` (Unix系OS)や `java.nio.FileChannel` （Jythonの場合）などを分析し、そのfile-likeオブジェクトがプラットフォーム依存APIの使用に適しているかを判断する必要があります。

仮にそのオブジェクトがプラットフォーム向けAPIに適して *いない* 場合でも、 `wsgi.file_wrapper` は **かならず** `read()` と `close()` を包み込むイテラブルを返却し、file wrapperを使用するアプリがプラットフォームを越えて移植可能であるようにしなければいけません。以下は、Python2.2未満と新しいバージョンで同じように動作する、非プラットフォーム依存のfile wrapperクラスです。

```python
class FileWrapper:

    def __init__(self, filelike, blksize=8192):
        self.filelike = filelike
        self.blksize = blksize
        if hasattr(filelike, 'close'):
            self.close = filelike.close

    def __getitem__(self, key):
        data = self.filelike.read(self.blksize)
        if data:
            return data
        raise IndexError
```

そして、サーバ/ゲートウェイは以下のコードで上記のクラスを使用し、プラットフォーム依存APIにアクセスできるようにします。

```python
environ['wsgi.file_wrapper'] = FileWrapper
result = application(environ, start_response)

try:
    if isinstance(result, FileWrapper):
        # check if result.filelike is usable w/platform-specific
        # API, and if so, use that API to transmit the result.
        # If not, fall through to normal iterable handling
        # loop below.

    for data in result:
        # etc.

finally:
    if hasattr(result, 'close'):
        result.close()
```