On this page |
urlHandler(path, is_prefix=False, ports=[])
このデコレータを使って関数をデコレート(修飾)すると、指定されたサーバーパスでのリクエストのハンドラーとしてその関数が登録されます。
path
"/"
で始まる文字列ですが、スラッシュで終わらせても、終わらせなくてもどちらでも構いません。
パスが登録される時、末尾のスラッシュはサーバーの挙動に何も影響を与えません。
path
にスラッシュが含まれていない場合は暗黙的にスラッシュが追加され、サーバーがパスをリクエストハンドラーにマッチさせる際には、サーバーリクエストで送信されるパスにスラッシュが欠落していればスラッシュが追加されます。
Note
ただし、/hom/hou/webServer/Request.html#pathには、リクエストされたそのままの修正されていないパスが格納されます。
is_prefix
False
の場合、ハンドラー関数は、リクエストされたパスがpath
にマッチした場合にのみ呼び出されます。
しかしTrue
の場合、ハンドラー関数は、リクエストされたパスがpath
で始まり、その後にスラッシュ、その後に他の何かが付いている時にコールされます。
ports
URLハンドラーを明示的にバインドさせたいポート。 何もポートを指定しなかった場合、URLハンドラーはWebサーバーのメインポートにバインドされます。 このポート番号には実際のポート番号を指定することはもちろん、0を指定するとメインポートへのバインドになり、-1を指定するとすべてのポートへのバインドになります。
Note
ポート番号を指定する際にハンドラーをメインポートにバインドさせたいのであれば、実際のポート番号ではなく0
を指定することを推奨します。
ハンドラーがルックアップのパフォーマンスが向上し、メインポートを変更してもハンドラーが引き続きメインポートにバインドされるという利点があります。
-
あなたの関数では、hou.webServer.Requestオブジェクトを引数として受け取るようにしてください。このオブジェクトには、リクエストパス、URL引数、フォームパラメータ、ヘッダ値などを取得するメソッドが用意されています。
-
あなたの関数では、hou.webServer.Responseオブジェクトを返すようにしてください。
Response
オブジェクトでは、レスポンスの内容、HTTPコード、ヘッダなどを設定することができます。 -
レスポンスをWebブラウザで閲覧できるようにしたいのであれば、Pythonだと素早く簡単にHTMLを生成する方法がたくさんあります。Houdiniには
jinja2
テンプレート化ライブラリが同梱されています。
Note
デコレートされる関数の名前は重要ではありません。
import hou @hou.webServer.urlHandler("/hello") def my_handler(request): return hou.webServer.Response("Hello world")
ファイルをクライアントにダウンロードするために、hou.webServer.fileResponse()の結果を返します:
import os.path import hou @hou.webServer.urlHandler("/hello") def my_handler(request): file_path = os.path.expandvars("$HIP/hello.txt") return hou.webServer.fileResponse(file_path)
RPC(Remote Procedure Call)のAPIを構築したいのであれば、hou.webServer.apiFunction()デコレータを使用してください。
接頭辞パス ¶
デコレータでis_prefix=True
引数を使用することで、指定されたパスで始まるすべてのリクエストをあなたの関数が処理するように指定することができます。
例えば、@hou.webServer.urlHandler("/node", is_prefix=True)
は、/node
, such as /node/obj
、/node/stage/light1
、/node/obj/my_hda/sphere1
などの/node
で始まるすべてのリクエストを処理します。
ハンドラー内でrequest.path()
を使用することでフルリクエストパスを取得することができ、ハンドラー次第でそのパスから接頭辞パスを取り除いて“接尾辞”パスを取得することができます。
import hou @hou.webServer.urlHandler("/node", is_prefix=True) def node_handler(request): path = request.path() assert path.startswith("/node") # 先頭の"/node"と末尾のスラッシュを取り除きます。 node_path = path[len("/node"):] if not node_path: node_path = "/" if node_path != "/" and node_path.endswith("/"): node_path = node_path[:-1] # 指定したパスのhou.OpNodeオブジェクトを取得します。そこにノードが存在しなければ、404 Not Foundでレスポンスを返します。 node = hou.node(node_path) if not node: return hou.webServer.notFoundResponse(request) html = "<h1>{}</h1>".format(node.name()) html += "<p>{}</p>".format(node.type().name()) html += "<ul>\n" if node != hou.root(): html += '<li><a href="/node{}">..</a></li>\n'.format( node.parent().path()) for child_node in node.children(): html += '<li><a href="/node{}">{}</a></li>\n'.format( child_node.path(), child_node.name()) html += "</ul>\n" return hou.webServer.Response(html)
パスのマッチング ¶
-
パスが末尾のスラッシュを除いて完全にマッチすれば、その末尾のスラッシュは除去されます。
-
“接頭辞付きの”マッチの接尾辞の末尾がスラッシュなら、その末尾のスラッシュは除去されます。
例えば、/
と/exact
を厳格パスハンドラーとして登録し、/pre
と/pre/usd
を接頭辞ハンドラーとして登録したと仮定します。
リクエストされたパス |
ハンドラー |
|
---|---|---|
|
|
|
|
|
|
|
|
|
|
404 |
N/A |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
404 |
N/A |
|
404 |
N/A |
サンプル ¶
import hou @hou.webServer.urlHandler("/") def index(request): return hou.webServer.Response( ''' <form method="GET" action="/crag.bgeo"> Download geometry at frame: <input name="frame" value="1"> <input type="submit" value="Download"> </form> ''') @hou.webServer.urlHandler("/crag.bgeo") def crag(request): '''リクエストされたフレームにおけるCragテストジオメトリのbgeoファイルを返します。''' url_args = request.GET() frame_str = url_args.get("frame", "1") try: frame = float(frame_str) except ValueError: return hou.webServer.errorResponse( request, "Frame is not a number", 422) sop = hou.node("/obj/geo1/testgeometry_crag1") if sop is None: sop = hou.node("/obj").createNode("geo").createNode("testgeometry_crag") response = hou.webServer.Response( sop.geometryAtFrame(frame).data(), content_type="application/octet-stream" ) response.setHeader( "Content-Disposition", 'attachment; filename="crag_%s.bgeo' % frame ) return response
See also |