ASP.NET Core に追加された Minimal API を使って webhook エンドポイントを構築

2.7K Views

January 29, 22

スライド概要

2022/01/29に開催されたBurikaigi 2022で発表した際の資料です。
Minimal APIを使ってTwilioのwebhookエンドポイントを構築してみました。

profile-image

Daizen Ikehara

@Neri78

スライド一覧

Developer Evangelist @ Twilio

シェア

埋め込む »CMSなどでJSが使えない場合

各ページのテキスト
1.

ASP.NET Core に 追加されたMinimal APIを 使ってwebhook エンドポイントを構築 @Neri78

2.

自己紹介 池原大然(いけはらだいぜん) Twitter: @Neri78 富山県の入善町出身 Developer Evangelist @ Twilio

3.

今日お話しすること ● 3分で理解するTwilio ● Minimal APIをはじめる ● webhookエンドポイントの構築

4.

3分 で理解する Twilio

5.

Twilio = 様々なコミュニケーションチャネルをクラウドを介し、 プログラム可能な状態で利用できるサービス © 2021 TWILIO INC. ALL RIGHTS RESERVED.

6.

ゲームも出してるよ! 題材: Twilio、GitHub、PHP、 Python、JavaScript(もうすぐ) TwilioQuestで検索 https://www.twilio.com/quest/ja

7.

“もしもし” Http Request “こんにちは!” Http Response Twilio Markup Language (TwiML) <Response> <Say language=”ja-JP”>こんにちは</Say> </Response>

8.

Http Request Http Response 今日は この部分を Minimal APIで構築 webhook endpoint

9.

このお題でお話しすることにした理由 ● .NET / C#はここ2年ほとんど触ってない 最近は専らJavaScript ● Minimal APIの情報を見て興味を持つ (APIの会社なんで...) ● Node.js + Expressと似てない?

10.

Minimal API を はじめる

11.

とても詳しい情報はこちら https://bit.ly/aspnet-minimal-api-ja

12.

Microsoft Learnにもコースあり https://bit.ly/mslearn-minimal-api-ja

13.
[beta]
Minimal(最小限)のコードでAPIを構築
dotnet new web -o 出力フォルダ名

トップレベルステートメント
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.Run();

14.
[beta]
似てるよね?
// Minimal API
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () => "Hello World!");

app.Run("http://localhost:3000");

// Node.js + Express
const express = require('express');
const app = express();

app.get('/', (req, res) => res.send('Hello World'));

app.listen(3000);

15.

ルーティング // Minimal API // Node.js + Express // GET // GET app.MapGet("/", () => "Hello GET"); // POST app.get("/", () => "Hello "); // POST app.MapPost("/", () => "Hello POST"); // PUT app.post("/", () => "Hello POST"); app.MapPut("/", () => "Hello PUT"); // PUT // DELETE app.put("/", () => "Hello PUT"); app.MapDelete("/", () => "Hello DELETE"); // DELETE // ???? app.delete("/", () => "Hello DELETE"); app.Map("/map", () => "????"); // ALL app.all("/", () => "????");

16.
[beta]
リクエスト情報へのアクセス
// Minimal API

or

app.MapGet("/header", (HttpRequest request) => {
var name = request.Query["name"];
return $"こんにちは {name} さん";
});
// Node.js + Express

app.get("/header", (req, res) => {
var name = req.query.name;
res.send(`こんにちは ${name} さん`);
});

17.

Http Request webhook エンドポイントの構築 Http Response

18.

要件 1. リクエストを受信する 2. 動的にTwiMLを返す 3. Twilio以外からのリクエストを拒否する Twilioパッケージもあるよ! dotnet add package Twilio

19.

Let’s Build!

20.
[beta]
app.MapGet("/voice", (HttpRequest request, HttpResponse response) => {
// url - 今回は決め打ち
var url = $"https://daizen.ngrok.io/voice{request.QueryString.Value}";

Minimal API

// Twilioから送られてくるリクエストのヘッダに付属する署名
var signature = request.Headers["X-Twilio-Signature"];
// TwilioアカウントのAuthToken
var authToken = Environment.GetEnvironmentVariable("AUTH_TOKEN") ?? "";

// 署名を検証
var validator = new Twilio.Security.RequestValidator(authToken);
if (validator.Validate(url, new System.Collections.Specialized.NameValueCollection(), signature)) {
// Content-Typeを設定
response.Headers.ContentType = "application/xml";
// TwiMLを設定
var twiml = new Twilio.TwiML.VoiceResponse();
twiml.Say(
message: "こんにちは",
language: Twilio.TwiML.Voice.Say.LanguageEnum.JaJp,
voice: Twilio.TwiML.Voice.Say.VoiceEnum.PollyTakumi);
return twiml.ToString();
} else {
Console.WriteLine("nooo");
response.StatusCode = 401;
return "Twilioからのリクエストではありません!";
}

21.
[beta]
app.get("/voice", (req, res) => {
// url - 今回は決め打ち
const url = `https://daizen.ngrok.io${req.url}`;
// Twilioから送られてくるリクエストのヘッダに付属する署名
const signature = req.headers["x-twilio-signature"];
// Twilioアカウントの AuthToken
const authToken = process.env.AUTH_TOKEN;

// 署名を検証
if (twilio.validateRequest(authToken, signature, url, {})) {
// Content-Typeを設定
res.contentType("application/xml");
// TwiMLを設定
const twiml = new twilio.twiml.VoiceResponse();
twiml.say({ language: "ja-JP",
voice: "Polly.Takumi" }, "こんにちは ")
res.send(twiml.toString());
} else {
res.status(401).send("Twilioのリクエストではありません ");
}

Node.js + Express

22.

まとめ

23.

Minimal APIを使った感想 ● ぱっと見Node.js + Expressにそっくりさんだが、 細かい部分はやはり違う(当たり前) ● シンプルな構成のAPI / Webhookエンドポイントを 素早く作成できそう(デモに最適) ● どこまで複雑なものを構築できるんだろうか?

24.

告知: ナイトセミナーを実施します! Twilio Night Vol.1 - コミュニケーション API「Twilio」をつかってみよう 2/8(火) 20:00 - 21:15 https://twilio.connpass.com/event/237567/

25.

ありがとうございました! @neri78