Azure Functions に custom handlers がやってきたので、(決まりに従えば) お好みのランタイムで Azure Functions が使えるようになりました。
例によって Deno で試してみたところ、ぽつぽつハマったので、まとめたいと思います。
Deno on Azure Functions
今回、Deno を使った Azure Functions で、HTTP トリガーの関数を一つ作ってみました。
ファイル構成
こんな感じです。
D:\home\site\wwwroot (or /home/site/wwwroot) ├── deno.exe (or deno) ├── host.json ├── HttpTrigger1 │ └── function.json ├── proxies.json └── server.ts
Deno は実行ファイルひとつで動くので、構築が楽チンです。
Windows の場合は、deno.exe
、Linux の場合は deno
を一緒にデプロイします。
前のエントリーに書いた通り、基本的には HTTP サーバーが構築できれば、どの言語でも動作するはずで、今回は server.ts
がその Web サーバーです。
関数の実装も全てを任せましたので、関数 HttpTrigger1
の下にあるのは、function.json
だけです。
server.ts
server.ts
の中身はこれだけです。
import { serve } from "https://deno.land/std@v0.36.0/http/server.ts"; const port = parseInt(Deno.env().FUNCTIONS_HTTPWORKER_PORT); const s = serve({ port }); console.log(`listening at port ${port} ...`); for await (const req of s) { console.log(req.url); if (/^\/HttpTrigger1\??/.test(req.url)) { req.respond({ body: "This is HttpTrigger1\n" }); continue; } req.respond({ body: "Hello Deno\n" }); }
Deno の Web サーバーのサンプル、そのものですが、待ち受けポートは、公式ドキュメントに従って、環境変数 FUNCTIONS_HTTPWORKER_PORT
を使って設定しています。
/HttpTrigger1
にリクエストが来たら 「This is HttpTrigger1」を返すだけです。
Azure Functions の HTTP トリガーの場合、?code=xxxxx
といった URL クエリーが付くことが多いので、その辺をすこーしだけ考慮して正規表現にしています。
その他のパスへのリクエストは、「Hello Deno」を返します。
Function Host から Web サーバーの /
に、時折 ping が来ているようなので、即 200 OK を返せるようにした方がいいと思います。
ハマりポイントその 1 ~ host.json
最初にハマったのは、host.json
の書き方でした。
まずは NG な host.json
から。
{ : "httpWorker": { "description": { "defaultExecutablePath": "deno.exe", "defaultWorkerPath": "server.ts", "arguments": [ "run", "--allow-env", "--allow-net"] } } }
一件、公式ドキュメントの例と同じに見えますが、これがうまく動かない。
deno.exe というファイルがない
と言われます。
いろいろ試した結果、server.ts
を入れている defaultWorkerPath
に文字列を入れると (空文字列は OK ) 、deno.exe
が見つからないようでした。
ドキュメントの例は、環境変数 PATH に node
のフルパスが含まれているので問題ないのでしょう。多分。
結果、OK な host.json
がこちらです。
{ : "httpWorker": { "description": { "defaultExecutablePath": "deno.exe", "arguments": [ "run", "--allow-env", "--allow-net", "server.ts"] } } }
server.ts
を defaultWorkerPath ではなく、引数に入れてみました。
この書き方だと、D:\home\site\wwwroot
の deno.exe
(Linux の場合、/home/site/wwwroot
の deno
) を見つけてくれます*1。
ハマりポイントその 2 ~ ホスティング プラン
公式ドキュメントの Restrictions の項目には、Linux の従量課金プランでは動作しない旨が記載されています。
Custom handlers are not supported in Linux consumption plans
上の制限は、Azure Functions 単独のものですが、Azure Functions (というか、App Service で)で Deno を使うと、もう少し制限があるのを忘れていました。
Windows 版 Deno は、起動時に OS のユーザー プロファイルをロードしようとしますが、通常 App Service 上ではこれができません。 github.com # まだ治っていませんね。。。
こちらに記載されている アプリケーション設定に WEBSITE_LOAD_USER_PROFILE
を追加することで回避できますが、これを有効にするには Basic プラン以上の App Service プランが必要です。
まとめるとこんな感じでしょうか。
Comsumption | ElasticPremium | Free/Shared | Basic/Standard/Premium | |
---|---|---|---|---|
Windows | ×*2 | ○ | ×*2 | ○ |
Linux | ×*3 | ○ | ○ | ○ |
まとめ
なんだかんだで、Deno を使って Azure Functions の関数を書くことができました。
ただ、すべての処理を server.ts に入れると、コードの可読性が悪くなりそうなので、できれば従来のように、関数単位でファイルを分離したいところです。
次はその辺りを試してみようかと。
express
的なフレームワークがあれば、できそうです。
# 逆に、関数と Web サーバー コードを統合できるので、ステートフルな関数も書き放題説。。。