かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

Azure Functions を始めてみました(node.js + VSCode)

node.js のインストール

とりあえず node.js がないと始まらないので入れました。

node.js

入れたバージョンはv8.3.0です。

VSCode の拡張機能のインストール

特に公式のものはないみたいですね。 ということで Azure Functions の定義ファイルのインテリセンス出してくれそうなプラグインを入れました。

Azure Functions Tools - Extensions for VS Code

ローカル実行

ドキュメントに従いやっていきます。

Azure Functions をローカルでコーディングしてテストする

Azure Functions Core Tools のインストール

npm パッケージとして公開されてるらしいのでサクッと入れます。

VSCode のターミナルあたりで以下のコマンドを打ち込みましょう。

npm i -g azure-functions-core-tools

プロジェクトの作成

以下のコマンドでカレントのディレクトリに作成してくれます。

func init

このあと、なんかストレージアカウントの設定とか追加しないといけないのですが、手動で local.settings.json に追記するかコマンドでサーバーの情報取ってくる方法があるみたいです。

ということで、どうせあとで Azure 上で実行するつもりなので Azure Portal から Function App を新規作成しましょう。

特に何も考えずに項目を埋めていくと自動的に Function App に紐づいた Storage Account が作成されます。ここでは OkazukiNodeJSEdu という名前で Function App を作成してみました。

そして、以下のコマンドをたたきます。(初回はログインが走るので認証画面がポップアップしてきます)

func azure functionapp fetch-app-settings OkazukiNodeJSEdu

暫く待つとポータルから情報とってくるみたいなログが出てきて local.settings.json が以下のように更新されます。

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "ストレージの接続文字列",
    "AzureWebJobsDashboard": "ストレージの接続文字列",
    "FUNCTIONS_EXTENSION_VERSION": "~1",
    "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING": "ストレージの接続文字列",
    "WEBSITE_CONTENTSHARE": "なんか入ってるはず",
    "WEBSITE_NODE_DEFAULT_VERSION": "6.5.0"
  },
  "ConnectionStrings": {}
}

関数の作成

とりあえず受け取った文字列をそのまま返す echo 的な関数を作ってみようと思います。関数の作成もコマンドが提供されています。

func new

とうつみたいです。

そうするとウィザードが走るので言語(JavaScript選んだ)、トリガー(起動のきっかけ。今回はHttpTriggerを選びました)、そして名前(今回は Echo と入れました)を入力して完了すると以下のファイルが作られます。

Echo
      function.json
      index.js
      sample.dat

生成された index.js を見ると以下のようになっています。

module.exports = function (context, req) {
    context.log('JavaScript HTTP trigger function processed a request.');

    if (req.query.name || (req.body && req.body.name)) {
        context.res = {
            // status: 200, /* Defaults to 200 */
            body: "Hello " + (req.query.name || req.body.name)
        };
    }
    else {
        context.res = {
            status: 400,
            body: "Please pass a name on the query string or in the request body"
        };
    }
    context.done();
};

クエリパラメータかボディに name というパラメータがあれば Hello xxxx って返してくれるみたいですね。とりあえずこのままやってみようと思います。

ローカル実行

では実行します。実行もコマンドでさくっと出来ます。以下のコマンドをたたきましょう。

func host start

出力に以下のように、どんな URL で待機してるよっていうのが出るので叩いてみます。

[2017/08/12 4:25:38] }
Http Function Echo: http://localhost:7071/api/Echo
Debugger listening on [::]:5858

ブラウザでたたいてもいいですが、なんとなく Postman で叩いてみました。まずは、http://localhost:7071/api/Echoをそのまま叩いてみました。こんな感じのレスポンスが返ってきました。

"Please pass a name on the query string or in the request body"

いいね。じゃぁ次にURLをこういう風に変えてみました。http://localhost:7071/api/Echo?name=okazuki

結果は以下のようなものが返ってきました。

"Hello okazuki"

いいね。

最後にメソッドを POST にして Body を以下のような JSON にしてみました。

{ "name": "post okazuki" }

実行すると以下のような結果が返ってきました。

"Hello post okazuki"

想定通りですね。

デバッグしてみよう

実行のときに以下のようにして実行するとデバッガーをアタッチすることが出来るようになるみたいですね。

func host start --debug vscode

VSCode の左側の虫のマークを押してデバッグビューにすると Attach to Azure Functions というのが出てるので再生ボタンを押してアタッチしてみましょう。

適当にブレークポンとはって Postman でリクエスト投げ込んでやると止まりました。ばっちりですね。

コマンドからの関数の実行

Postman を使って HTTP のリクエストを投げ込んでましたが、そういうことをしなくても関数を実行する方法があるみたいです。

func run  <FunctionName>

で実行できるみたいです。今回は Echo 関数なので

func run Echo

になりますね。やってみると以下のような結果になりました。サーバーがDOS窓で起動してきたのにびっくりしましたが動いてます。

PS C:\Users\kaota\Documents\Visual Studio Code\Projects\funcedu> func run Ech
o

We need to launch a server that will host and run your functions.
The server will auto load any changes you make to the function.
Do you want to always display this warning before launching a new server [yes
/no]? [yes]
NOTE: the 'func run' command only supports POST for HTTP triggers. For other
verbs, consider a REST client like cURL or Postman.
Response Status Code: BadRequest
"Please pass a name on the query string or in the request body"

この関数には、パラメータ渡したいですよね。パラメータは -c コマンドラインオプションで指定するみたいです。こんな感じで

func run Echo -c '{ \"name\": \"okazuki\" }'

実行するとこうなりました。

PS C:\Users\kaota\Documents\Visual Studio Code\Projects\funcedu> func run Ech
o -c '{ \"name\": \"okazuki\" }'
NOTE: the 'func run' command only supports POST for HTTP triggers. For other
verbs, consider a REST client like cURL or Postman.
Response Status Code: OK
"Hello okazuki"

-c コマンドラインオプションで毎回指定するのがだるい場合は -f オプションでコンテンツとして渡すものをファイルで指定できます。例えば testdata フォルダっていう名前のフォルダでも作って、その中に person.json みたいなファイルを以下のような内容で用意しておきます。

{
    "name": "okazuki"
}

そして、以下のようなコマンドを打ちます。

func run Echo -f testdata/person.json

実行するといい感じに動いてることが確認できます。こっちのほうがよく使いそうですね。

PS C:\Users\kaota\Documents\Visual Studio Code\Projects\funcedu> func run Ech
o -f testdata/person.json
NOTE: the 'func run' command only supports POST for HTTP triggers. For other
verbs, consider a REST client like cURL or Postman.
Response Status Code: OK
"Hello okazuki"

-d オプションでデバッガにアタッチするようにもできるみたいですが、VSCode からのうまいやり方がわかりません。とりあえず立ち上がってきたサーバーに、前にやった手順と同じ手順でデバッガアタッチすることは出来たのですが説明にある「関数を実行する前に、デバッガーを、ホスト プロセスにアタッチします。」という文言にあるみたいに、起動前に VSCode のデバッガがアタッチしにいくみたいなことはないです?まぁ普通ターミナルでコマンド叩いただけで VSCode のデバッガが勝手にアタッチしにいくとは思えないんだけど。まぁいっか。

Azure に発行!

以下のコマンドで発行できます。

func azure functionapp publish <FunctionAppName>

ということなので、今回の場合は OkazukiNodeJSEdu という名前で Azure 上に作ってるので、こうなりますね。

func azure functionapp publish OkazukiNodeJSEdu

叩いてみるとこんな感じのログが出ます。

PS C:\Users\kaota\Documents\Visual Studio Code\Projects\funcedu> func azure f
unctionapp publish OkazukiNodeJSEdu
Publish C:\Users\kaota\Documents\Visual Studio Code\Projects\funcedu contents
 to an Azure Function App. Locally deleted files are not removed from destina
tion.
Getting site publishing info...
Creating archive for current directory...
Uploading archive...
Upload completed successfully.

実際にポータルを開いてみると Echo 関数が生えてます。関数のURLを取得して Postman でリクエスト投げてみると動いてることが確認できます。