Houdini 19.0 Pythonスクリプト hou hou.webServer

hou.webServer.urlHandler HOM function

HoudiniのWebサーバーへ送信されるリクエストを制御する関数のデコレータ。

On this page

urlHandler(path, is_prefix=False, ports=[])

このデコレータを使って関数をデコレート(修飾)すると、指定されたサーバーパスでのリクエストのハンドラーとしてその関数が登録されます。

path

"/"で始まる文字列ですが、スラッシュで終わらせても、終わらせなくてもどちらでも構いません。 パスが登録される時、末尾のスラッシュはサーバーの挙動に何も影響を与えません。 pathにスラッシュが含まれていない場合は暗黙的にスラッシュが追加され、サーバーがパスをリクエストハンドラーにマッチさせる際には、サーバーリクエストで送信されるパスにスラッシュが欠落していればスラッシュが追加されます。

Note

ただし、hou.webServer.Request.path()には、リクエストされたそのままの修正されていないパスが格納されます。

is_prefix

Falseの場合、ハンドラー関数は、リクエストされたパスがpathにマッチした場合にのみ呼び出されます。 しかしTrueの場合、ハンドラー関数は、リクエストされたパスがpathで始まり、その後にスラッシュ、その後に他の何かが付いている時にコールされます。

ports

URLハンドラーを明示的にバインドさせたいポート。 何もポートを指定しなかった場合、URLハンドラーはWebサーバーのメインポートにバインドされます。 このポート番号には実際のポート番号を指定することはもちろん、0を指定するとメインポートへのバインドになり、-1を指定するとすべてのポートへのバインドになります。

Note

ポート番号を指定する際にハンドラーをメインポートにバインドさせたいのであれば、実際のポート番号ではなく0を指定することを推奨します。 ハンドラーがルックアップのパフォーマンスが向上し、メインポートを変更してもハンドラーが引き続きメインポートにバインドされるという利点があります。

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.Nodeオブジェクトを取得します。そこにノードが存在しなければ、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を接頭辞ハンドラーとして登録したと仮定します。

リクエストされたパス

ハンドラー

request.path()

/

/

/

/exact

/exact

/exact

/exact/

/exact

/exact/

/exact/geo

404

N/A

/pre/

/pre

/pre/

/pre

/pre

/pre

/pre/geo

/pre

/pre/geo

/pre/geo/

/pre

/pre/geo/

/pre/usd

/pre/usd

/pre/usd

/pre/usd/scene

/pre/usd

/pre/usd/scene

/pregeo

404

N/A

/missing

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

hou.webServer

クラス

開始と停止

Webリクエストの処理とレスポンス

APIコール

  • hou.webServer.apiFunction()

    HoudiniのWebサーバー上のAPIエンドポイントを介してコール可能な関数のデコレータで、JSONレスポンスまたはバイナリレスポンスを返します。

  • hou.webServer.APIError

    apiFunctionハンドラーでこの例外を引き起こしてエラーを示します。