Houdini 20.0 hwebserver

hwebserver.urlHandler function

Houdiniのウェブサーバーへのリクエストを制御する関数のデコレータ。

On this page

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

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

path

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

Note

ただし、/hwebserver/Request.html#pathには、リクエストされた時の変更されていないそのままのパスが格納されます。

is_prefix

Falseの場合、リクエストされたパスがpathに一致した場合にのみハンドラー関数が読み出されます。 しかし、Trueの場合、リクエストされたパスがpathで始まり、その後にスラッシュで、その後に何かになっていればハンドラー関数がコールされます。

ports

ハンドラー関数を呼び出し可能なポート。 ポートを指定しなかった場合、ハンドラー関数はウェブサーバーのメインポートにバインドされます。 ポート名は、空っぽでなく、且つ、main(メインポートに予約済みの名前)でなければ、どのような名前でも構いません。

Note

デコレートされた関数の名前は重要ではありません。

import hwebserver

@hwebserver.urlHandler("/hello")
def my_handler(request):
    return hwebserver.Response("Hello world")

クライアントにファイルをダウンロードするには、hwebserver.fileResponseの結果を返します:

import os.path
import hwebserver

@hwebserver.urlHandler("/hello")
def my_handler(request):
    file_path = os.path.expandvars("$HIP/hello.txt")
    return hwebserver.fileResponse(file_path)

RPC(Remote Procedural Call)APIを構築するには、hwebserver.apiFunctionデコレータを使用します。

NEW

URLハンドラーはasyncioに対応しています(Python3ビルド版のみ)。 asyncioを使用するとパフォーマンスが低下するので、ウェブサーバーはC++が良いです。 API関数がリクエスト処理中にIOを待つことが多い場合にのみ、コルーチンAPI関数を使用するのを推奨します。 デコレータは、自動的に関数の型を検出し、その型に基づいてその関数を処理します。

プリフィックスパス

デコレータにis_prefix=True引数を使用することで、関数が指定したパスから始まるすべてのリクエストを処理するように指定することができます。

例えば、@hwebserver.urlHandler("/node", is_prefix=True)は、/node/obj/node/stage/light1/node/obj/my_hda/sphere1などの/nodeから始まるすべてのリクエストを処理するようになります。

そのハンドラーでは、request.path()を使用してフルリクエストパスを取得することができ、ハンドラーの実装次第でそのプリフィックスパスを除去して“サフィックス”パスを取得することができます。

import hou
import hwebserver


@hwebserver.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 hwebserver.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 hwebserver.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
import hwebserver


@hwebserver.urlHandler("/")
def index(request):
    return hwebserver.Response(
        '''
        <form method="GET" action="/crag.bgeo">
            Download geometry at frame:
            <input name="frame" value="1">
            <input type="submit" value="Download">
        </form>
        ''')


@hwebserver.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 hwebserver.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 = hwebserver.Response(
        sop.geometryAtFrame(frame).data(),
        content_type="application/octet-stream"
    )
    response.setHeader(
        "Content-Disposition",
        'attachment; filename="crag_%s.bgeo' % frame
    )
    return response
See also

hwebserver

クラス

  • hwebserver.Request

    Houdiniのウェブサーバーに送信されるリクエスト。

  • hwebserver.Response

    Houdiniのウェブサーバーから送り返されるレスポンス。

  • hwebserver.UploadedFile

    Houdiniのウェブサーバーに送信されるリクエストにアップロードされたファイル。

  • URLHandler

    汎用のHTTPハンドラー。

  • AsyncURLHandler

    汎用の非同期HTTPハンドラー。

  • WebSocket

    組み込みサーバーをWebSocketに対応させるための基底クラス。

開始と停止

  • hwebserver.run

    Houdiniのウェブサーバーを開始します。

  • hwebserver.requestShutdown

    すべてのオープンリクエストが処理された後にシャットダウンするようにHoudiniのウェブサーバーに命令します。

  • hwebserver.isInDebugMode

    Houdiniのウェブサーバーがデバッグモード(でdebug=True)で起動されていればTrueを返します。

ウェブリクエストの処理とレスポンスの返し

ウェブソケット

  • WebSocket

    組み込みサーバーをWebSocketに対応させるための基底クラス。

  • hwebserver.webSocket

    HoudiniのウェブサーバーにWebSocketクラスを登録するデコレータ。

APIコール

  • hwebserver.apiFunction

    Houdiniウェブサーバー上のAPIエンドポイント経由で関数をコールを可能にするデコレータで、JSON形式またはバイナリ形式のレスポンスを返します。

  • hwebserver.APIError

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