リクエスト処理
標準のリクエスト
作成したスキルサービスとAlexaとの通信は、SSL/TLSを利用してHTTPを使用するリクエスト-応答メカニズムで行います。ユーザーがAlexaスキルと対話するとき、作成したサービスは、JSON本文を含むPOSTリクエストを受け取ります。このリクエスト本文には、サービスがロジックを実行してJSON形式の応答を生成するために必要なパラメーターが含まれています。Node.jsはネイティブにJSONを処理できるため、ASK SDK v2 for Node.jsではJSONのシリアル化と逆シリアル化が必要ありません。リクエスト本文のJSON構造についてのドキュメントは、こちらを参照してください。
ハンドラー入力
リクエストハンドラー、リクエストと応答のインターセプター、エラーハンドラーにはすべて、呼び出し時にHandlerInput
オブジェクトが渡されます。このオブジェクトには、リクエスト処理に有効な各種エンティティが含まれます。以下はその例です。
- RequestEnvelope: スキルに送信されるリクエスト本文全体を含みます。
- ResponseBuilder: 応答を作成するヘルパーメソッドを含みます。詳細については、応答のビルドを参照してください。
- AttributesManager: リクエスト、セッション、永続アトリビュートへのアクセスを提供します。詳細については、アトリビュートの管理を参照してください。
- ServiceClientFactory: Alexa APIの呼び出しが可能なサービスクライアントを構築します。詳細については、AlexaサービスAPIの呼び出しを参照してください。
- Context: ホストコンテナが渡す任意のcontextオブジェクトを提供します。たとえばAWS Lambdaで実行されるスキルの場合、AWS Lambdaメソッドのcontextオブジェクトになります。
リクエストハンドラー
リクエストハンドラーは、受け取った1つ以上のタイプのリクエストを処理します。リクエストハンドラーの作成には、RequestHandler
インターフェースを使用できます。このインターフェースは以下の2つのメソッドで構成されています。
canHandle
は、SDKによって呼び出され、指定されたハンドラーが受け取ったリクエストを処理できるかどうかを判断します。このメソッドは、HandlerInput
オブジェクトを受け取り、ハンドラーがリクエストを処理できる場合はtrue、処理できない場合はfalseを返します。受信するリクエストのタイプやパラメーター、スキルのアトリビュートなど、この判断を行うための条件を選択できます。handle
は、リクエストハンドラーを呼び出すときにSDKによって呼び出されます。このメソッドには、ハンドラーのリクエスト処理ロジックが含まれます。また、HandlerInput
を受け取り、Response
またはPromise<Response>
を返します。
インターフェース
interface RequestHandler {
canHandle(handlerInput: HandlerInput): Promise<boolean> | boolean;
handle(handlerInput: HandlerInput): Promise<Response> | Response;
}
サンプルコード
以下は、HelloWorldIntent
を呼び出すことができるリクエストハンドラーの例です。
const HelloWorldIntentHandler = {
canHandle(handlerInput) {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& Alexa.getIntentName(handlerInput.requestEnvelope) === 'HelloWorldIntent';
},
handle(handlerInput) {
const speechText = 'こんにちは';
return handlerInput.responseBuilder
.speak(speechText)
.withSimpleCard('ハローワールド', speechText)
.getResponse();
}
};
import {
HandlerInput,
RequestHandler,
} from 'ask-sdk-core';
import { Response } from 'ask-sdk-model';
const HelloWorldIntentHandler : RequestHandler = {
canHandle(handlerInput : HandlerInput) : boolean {
return Alexa.getRequestType(handlerInput.requestEnvelope) === 'IntentRequest'
&& Alexa.getIntentName(handlerInput.requestEnvelope) === 'HelloWorldIntent';
},
handle(handlerInput : HandlerInput) : Response {
const speechText = 'こんにちは';
return handlerInput.responseBuilder
.speak(speechText)
.withSimpleCard('ハローワールド', speechText)
.getResponse();
},
};
canHandle
メソッドは、受け取るリクエストがIntentRequest
かどうかを検出し、インテント名がHelloWorldIntent
の場合にtrueを返します。handle
メソッドは、基本的な「こんにちは」という応答を生成して返します。
以下の例は、SDKを使ってリクエストハンドラーを登録する方法を示しています。
const Alexa = require('ask-sdk-core');
const skill = Alexa.SkillBuilders.custom()
.addRequestHandlers(
FooHandler,
BarHandler,
BazHandler)
.create();
import { SkillBuilders } from 'ask-sdk-core';
const skill = SkillBuilders.custom()
.addRequestHandlers(
FooHandler,
BarHandler,
BazHandler)
.create();
canHandle
メソッドを呼び出します。上記の例では、SDKが以下の順序でリクエストハンドラーを呼び出します。1. FooHandler
2. BarHandler
3. BazHandler
SDKは、指定されたリクエストを処理できる最初のハンドラーを常に選択します。この例では、
FooHandler
とBarHandler
の両方が特定のリクエストを処理できる場合、常にFooHandler
が呼び出されます。リクエストハンドラーのデザインや登録を行う際には、この点を考慮に入れてください。リクエストと応答のインターセプター
SDKは、RequestHandler
の実行前と実行後に実行するリクエストと応答のインターセプターをサポートします。インターセプターは、RequestInterceptor
インターフェースかResponseInterceptor
インターフェースを使用して実装できます。
どちらのインターセプターインターフェースも、戻り値の型がvoid
であるprocess
メソッドを1つ実行します。リクエストのインターセプターはHandlerInput
オブジェクトにアクセスでき、応答のインターセプターはHandlerInput
と、RequestHandler
によって生成されるオプションのResponse
にアクセスできます。
インターフェース
interface RequestInterceptor {
process(handlerInput: HandlerInput): Promise<void> | void;
}
interface ResponseInterceptor {
process(handlerInput: HandlerInput, response?: Response): Promise<void> | void;
}
リクエストのインターセプターは、受け取るリクエストのリクエストハンドラーが実行される直前に呼び出されます。リクエストアトリビュートは、リクエストのインターセプターがリクエストハンドラーにデータやエンティティを渡す方法を提供します。
応答のインターセプターは、リクエストハンドラーが実行された直後に呼び出されます。応答のインターセプターはリクエストハンドラーを実行して生成される出力結果にアクセスできるため、応答のサニタイズや検証といったタスクに適しています。
サンプルコード
以下は、応答がAlexaに送信される前に永続アトリビュートのデータベースへの保存を処理する応答のインターセプターの例です。
const PersistenceSavingResponseInterceptor = {
process(handlerInput) {
return new Promise((resolve, reject) => {
handlerInput.attributesManager.savePersistentAttributes()
.then(() => {
resolve();
})
.catch((error) => {
reject(error);
});
});
}
};
import {
HandlerInput,
ResponseInterceptor,
} from 'ask-sdk-core';
const PersistenceSavingResponseInterceptor : ResponseInterceptor = {
process(handlerInput : HandlerInput) : Promise<void> {
return handlerInput.attributesManager.savePersistentAttributes();
},
};
以下の例は、SDKを使ってインターセプターを登録する方法を示しています。
const Alexa = require('ask-sdk-core');
const skill = Alexa.SkillBuilders.custom()
.addRequestHandlers(
FooHandler,
BarHandler,
BazHandler)
.addRequestInterceptors(
FooRequestInterceptor,
BarRequestInterceptor)
.addResponseInterceptors(
FooResponseInterceptor,
BarResponseInterceptor)
.create();
import { SkillBuilders } from 'ask-sdk-core';
const skill = SkillBuilders.custom()
.addRequestHandlers(
FooHandler,
BarHandler,
BazHandler)
.addRequestInterceptors(
FooRequestInterceptor,
BarRequestInterceptor)
.addResponseInterceptors(
FooResponseInterceptor,
BarResponseInterceptor)
.create();
1. FooRequestInterceptor
2. BarRequestInterceptor
3. <リクエスト用に選択されたリクエストハンドラー>
4. FooResponseInterceptor
5. BarResponseInterceptor
エラーハンドラー
エラーハンドラーはリクエストハンドラーに似ていますが、リクエストではなく1つまたは複数のタイプのエラーを処理します。リクエストの処理中に未処理のエラーがスローされると、SDKがエラーハンドラーを呼び出します。
すべてのエラーハンドラーは、ErrorHandler
インターフェースを使用する必要があります。このインターフェースは以下の2つのメソッドで構成されています。
canHandle
は、SDKによって呼び出され、指定されたハンドラーがエラーを処理できるかどうかを判断します。ハンドラーがエラーを処理できる場合はtrue、処理できない場合はfalseを返します。catch-allハンドラーを作成する場合は常にtrueを返します。handle
は、エラーハンドラーを呼び出すときにSDKによって呼び出されます。このメソッドにはエラー処理ロジックがすべて含まれ、Response
またはPromise<Response>
を返します。
インターフェース
interface ErrorHandler {
canHandle(handlerInput: HandlerInput, error: Error): Promise<boolean> | boolean;
handle(handlerInput: HandlerInput, error: Error): Promise<Response> | Response;
}
サンプルコード
以下は、名前が「AskSdk」で始まるエラーをすべて処理できるエラーハンドラーの例です。
const myErrorHandler = {
canHandle(handlerInput, error) {
return error.name.startsWith('AskSdk');
},
handle(handlerInput, error) {
return handlerInput.responseBuilder
.speak('リクエストの処理中にエラーが発生しました。後でもう一度試してください。')
.getResponse();
}
};
import { HandlerInput } from 'ask-sdk-core';
import { Response } from 'ask-sdk-model';
const myErrorHandler = {
canHandle(handlerInput : HandlerInput, error : Error) : boolean {
return error.name.startsWith('AskSdk');
},
handle(handlerInput : HandlerInput, error : Error) : Response {
return handlerInput.responseBuilder
.speak('リクエストの処理中にエラーが発生しました。後でもう一度試してください。')
.getResponse();
},
};
ハンドラーのcanHandle
メソッドは、受け取るエラーの名前が「AskSdk」で始まる場合にtrueを返します。handle
メソッドは、ユーザーに正常なエラー応答を返します。
以下の例は、SDKを使ってエラーハンドラーを登録する方法を示しています。
const Alexa = require('ask-sdk-core');
const skill = Alexa.SkillBuilders.custom()
.addRequestHandlers(
FooHandler,
BarHandler,
BazHandler)
.addRequestInterceptors(
FooRequestInterceptor,
BarRequestInterceptor)
.addResponseInterceptors(
FooResponseInterceptor,
BarResponseInterceptor)
.addErrorHandlers(
FooErrorHandler,
BarErrorHandler)
.create();
import { SkillBuilders } from 'ask-sdk-core';
const skill = SkillBuilders.custom()
.addRequestHandlers(
FooHandler,
BarHandler,
BazHandler)
.addRequestInterceptors(
FooRequestInterceptor,
BarRequestInterceptor)
.addResponseInterceptors(
FooResponseInterceptor,
BarResponseInterceptor)
.addErrorHandlers(
FooErrorHandler,
BarErrorHandler)
.create();
1. FooErrorHandler
2. BarErrorHandler
最終更新日: 2022 年 11 月 08 日