question

kun432 avatar image
kun432 asked ·

Alexa-hostedスキルから、外部にhttpsリクエストをするサンプルコード(axiosを使った場合)

外部の公開されているAPIを利用すると、スキル開発の幅が広がります。


Alexaブログでも以下の記事で紹介されています。

https://developer.amazon.com/ja/blogs/alexa/post/28368692-a0b9-4579-b129-e6793bef7848/alexa-skill-recipe-update-making-http-requests-to-get-data-from-an-external-api-using-the-ask-software-development-kit-for-node-js-version-2


ただ、Promise、少し難しくて最初のうちはよくわからない方も多いかと思います(私も未だによくわかっていません)。もう少し非同期処理を簡単・シンプルにわかりやすく書きたい、ということで、シンプルに外部へのHTTP/HTTPSリクエストを書けるライブラリ 'axios' を使った場合のサンプルコードをご紹介します。

https://www.npmjs.com/package/axios


packages.jsonに追加します。一旦、保存・デプロイして、ライブラリを配置します。

  "dependencies": {
    "ask-sdk-core": "^2.0.7",
    "ask-sdk-model": "^1.4.1",
    "aws-sdk": "^2.326.0",      // 最後にカンマを追加
    "axios": "^0.19.0"          // 追加
  }


GETとPOSTの2つのサンプルをご紹介します。


■GET


例として、郵便番号-住所検索APIを使ってみます。APIキーなしで使えます。

https://zipaddress.net/


パラメータとして郵便番号を渡してやると住所を返してくれます。オプションで出力をローマ字にするパラメータもあります。コマンドで実行する場合はこんな感じになります。

$ curl https://api.zipaddress.net/?zipcode=6500042  | jq .
{
  "code": 200,
  "data": {
    "pref": "兵庫県",
    "address": "神戸市中央区波止場町",
    "city": "神戸市中央区",
    "town": "波止場町",
    "fullAddress": "兵庫県神戸市中央区波止場町"
  }
}


こんな感じで書けます。

const Axios = require('axios');

const API_URL = 'https://api.zipaddress.net/';
・・・
    async handle(handlerInput) {
        let speechText;
        const zipcode = handlerInput.requestEnvelope.request.intent.slots.zipcode;        
        if (zipcode && zipcode.value && zipcode.value.match(/^\d{7}$/g)) {
            try {
                const res = await Axios.get(API_URL, {
                    params: {
                        zipcode: zipcode.value,
                        lang: "ja"
                    }
                });
                if (res.data.code !== 200) {
                    speechText = "その郵便番号は存在しません。郵便番号を確かめてから、もう一度ご利用ください。";
                } else {
                    speechText = `郵便番号、<say-as interpret-as='digits'>${zipcode.value}</say-as>の住所は ${res.data.data.fullAddress} です。`;
                }
                return handlerInput.responseBuilder
                    .speak(speechText)
                    .getResponse();
            } catch (error) {
                return handlerInput.responseBuilder
                    .speak("APIのリクエストに失敗しました。スキルを中止します。")
                    .getResponse();
            }
        } else {
            throw new Error("unknown slot value.");
        }
    }


非同期処理もasync/awaitでシンプルにかけて、エラー処理もきちんとできるので良いですね!パラメータはzipcodeだけで良いのでもっとシンプルにかけますが、複数パラメータが必要な場合を想定して、上記のように書いています。


■POST


例として、gooラボ様のひらがな化APIを使ってみます。事前にサイトで登録の上、APIキーを取得してください。

https://labs.goo.ne.jp/api/jp/hiragana-translation/


パラメータとして、アプリケーションID、出力種別(ひらがな/カタカナ)、変換したいテキストを指定します。コマンドで実行する場合はこんな感じになります。

$ curl -X POST -H "Content-Type: application/json" -d '{"app_id":"XXXXXXXXXXXXXXXXXXXX", "output_type":"hiragana", "sentence":"祇園精舎の鐘の声、諸行無常の響きあり"}' https://labs.goo.ne.jp/api/hiragana | jq .
{
  "request_id": "labs.goo.ne.jp\t1560171174\t0",
  "output_type": "hiragana",
  "converted": "ぎおんしょうじゃの かねの こえ、 しょぎょうむじょうの ひびきあり"
}


こんな感じで書けます。

const Axios = require('axios')

const API_URL = 'https://labs.goo.ne.jp/api/hiragana';
const API_KEY = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
const OUTPUT_TYPE = 'hiragana';
・・・
    async handle(handlerInput) {
        const user_say = handlerInput.requestEnvelope.request.intent.slots.user_say;
        if (user_say && user_say.value) {
            try {
                const res = await Axios.post(API_URL,{
                    app_id: API_KEY,
                    output_type: OUTPUT_TYPE,
                    sentence: user_say.value
                });
                const hiraganaText = res.data.converted;  // ひらがな化されて返ってきた文字列

                〜ここで文字列処理をする、例えばしりとりの場合だと最後の文字をとって次の単語を拾ってくるなど〜
                
                return handlerInput.responseBuilder
                    .speak(speechText)
                    .getResponse();
            } catch (error) {
                return handlerInput.responseBuilder
                    .speak("APIのリクエストに失敗しました。スキルを中止します。")
                    .getResponse();
            }
        } else {
            throw new Error("unknown slot value.");
        }
    }


GETの場合とあんまり変わらないので、覚えることが少なくて良いですね!ご活用ください。


また、もっと良い書き方あるぞ、もっといいライブラリあるぞ、書き方間違ってるぞ等あれば、是非ご指摘くださいませ。


注意

  • APIを利用する場合は、API提供元の規約等を確認してから使用してください。
  • 上記の例はあくまでもサンプルなので、実際にはもう少し工夫する必要があります。
alexa skills kitapinodejshosted skillalexaskillawards2019
10 |2000 characters needed characters left characters exceeded

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

0 Answers