例外、 HTTP エラー、リダイレクト

リダイレクトの実行と HTTP エラー

これは、 Pylons と比較して Pyramid でどうやってリダイレクトと HTTP エラー を送るかを示したものです:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# Pylons -- in controller action
from pylons.controllers.util import abort, redirect
abort(404)   # Not Found
abort(403)   # Forbidden
abort(400)   # Bad request; e.g., invalid query parameter
abort(500)   # Internal server error
redirect(url("section1"))   # Redirect (default 302 Found)

# Pyramid -- in view code
import pyramid.httpexceptions as exc
raise exc.exception_response(400)   # Not Found
raise exc.HTTPNotFound()            # Same thing
return exc.HTTPNotFound()           # Same thing
raise exc.HTTPForbidden()
raise exc.HTTPBadRequest()
raise exc.HTTPInternalServerError()
raise exc.HTTPFound(request.route_url("section1"))   # Redirect

pyramid.httpexceptions モジュールにはすべての公式 HTTP ステータスに 対応したクラスがあります。これらのクラスは ResponseException の両方から継承します。したがって、戻り値として返すことも、例外として 送出することもできます。 HTTP 例外を投げることでコードは構造的により 読みやすくなるかもしれません。それはいくつかの呼び出しスタックフレーム を通過することがあるサブルーチンで特に役立ちます。そうでなければエラー 状態を受け渡すために各々の呼び出し毎に if を必要とするでしょう。

例外ルール:

  1. route がリクエストにマッチしない場合、あるいは route とリクエストに マッチするビューがない場合、 Pyramid は内部で HTTNotFound を上げます。 現在の認可ポリシーに基づいてリクエストが拒否される場合、 Pyramid は HTTPForbidden を上げます。
  1. リクエストの処理中に捕捉されない例外が生じた場合、 Pyramid はそれを 捕捉して、その例外とマッチする「例外ビュー」を探します。例外ビューとは、 それに対する context 引数がその例外クラスや祖先、あるいはその例外が 実装しているインターフェースであるようなものです。さらに他のすべての ビュー述語もマッチしなければなりません; 例えば ‘route_name’ 引数が 指定されている場合、それは実際の route 名とマッチしなければなりません (したがって、例外ビューは典型的に route 名 なしで 登録されます)。 このビューは、例外オブジェクトが context として呼ばれます。そして、 ビューが返した任意のレスポンスがブラウザに送られます。このように、 ユーザに見せるエラー画面をカスタマイズするために例外ビューを使用する ことができます。
  1. マッチする例外ビューが見つからない場合、 HTTP 例外はそれ自体がレスポンス になります。したがって、それらはブラウザに送られます。標準 HTTPException は単純なエラーメッセージとレイアウトを持っています; サブクラスはこれをカスタマイズすることができます。
  1. HTTPException 以外のレスポンスは WSGI サーバーに伝搬します。 debug ツールバー tween が有効であれば、それは例外を捕捉して対話型の トレースバックを表示します。そうでなければ、 WSGI サーバが例外を捕捉して それ自身の “500 Internal Server Error” 画面を送信します。

これらは、代表的な HTTP 例外です:

クラス コード Location 意味
HTTPMovedPermanently 301 Y 恒久的なリダイレクト; クライアントは ブックマークを変更するべき。
HTTPFound 302 Y 一時的なリダイレクト。 [1]
HTTPSeeOther 303 Y 一時的なリダイレクト; クライアントは GET を使うべき。 [1]
HTTPTemporaryRedirect 307 Y 一時的なリダイレクト。 [1]
HTTPClientError 400 N 一般的なユーザエラー; 例えば、不正な クエリパラメータ。
HTTPUnauthorized 401 N ユーザは認証が必要。
HTTPForbidden 403 N 認証の失敗、または一般的な拒否。
HTTPNotFound 404 N この URL は認識されない。
HTTPGone 410 N 以前この URL に存在したリソースは 恒久的に利用できなくなった; クライアントはブックマークを削除すべき。
HTTPInternalServerError 500 N 内部エラーによりサーバーはリクエストを 処理することができなかった。

location カラムが “Y” のクラスのコンストラクタ引数は (location="", detail=None, headers=None, comment=None, ...) です。それ以外は、 コンストラクタ引数は (detail=None, headers=None, comment=None, ...) です。

location 引数は Python レベルではオプションですが、 HTTP 仕様は 絶対 URL である位置を要求しています。したがって、それは事実上必須です。

detail 引数はエラー画面の一部として表示されるプレーンテキスト文字列です。 headers はレスポンスに加えたい HTTP ヘッダー (name-value タプル) の リストです。 comment はユーザには表示されないプレーンテキスト文字列です。 (XXX これはログに記録される?)

例外ビュー

例外ビューは HTTPNotFound または HTTPForbidden と一緒に使用される ことが最も普通ですが、任意の例外クラスに対して例外ビューを登録することが できます。これは、 Pyramid マニュアルから拝借した、カスタム例外を用いた 例外ビューの例です:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from pyramid.response import Response

class ValidationFailure(Exception):
    pass

@view_config(context=ValidationFailure)
def failed_validation(exc, request):
    # If the view has two formal arguments, the first is the context.
    # The context is always available as ``request.context`` too.
    msg = exc.args[0] if exc.args else ""
    response =  Response('Failed validation: %s' % msg)
response.status_int = 500
return response

利便性のため、 Pyramid は “Not Found” ビューや “Forbidden” ビューを登録 するための特別なデコレータおよび Configurator メソッドを持っています。 @notfound_view_config@forbidden_view_config (pyramid.view で定義) は、コンテキスト引数の面倒を見ます。

加えて、 @notfound_view_configappend_slash 引数を受け付けます。 それは末尾のスラッシュ規約を強制するために使用できます。あなたのサイトが すべての route はスラッシュで終るべきと定義していて、 append_slash=True をセットした場合、スラッシュのないリクエストが route とマッチしなかった場合、Pyramid はリクエスト URL にスラッシュを 追加して再びマッチを試みます。これが route とマッチすれば、 Pyramid は リダイレクトを実行します。これは、末尾のスラッシュ (“/dir/” や “/dir/a/”) を好むサイトでのみ役立ちます。他のサイトでは末尾のスラッシュ を好まれず (“/dir” and “/dir/a”) 、またこのための特別な機能はありません。

参考

[1](1, 2, 3) 3つの一時的なリダイレクトステータスは、大部分は交換可能ですが、 わずかに異なる目的があります。詳細は HTTP ステータスのリファレンスに あります。

Table Of Contents

Previous topic

テンプレート

Next topic

静的ファイル