LoginSignup
1

More than 3 years have passed since last update.

AppSyncのデータソースにHTTPエンドポイントを設定する

Last updated at Posted at 2021-03-20

概要

  • AppSyncのデータソースにhttpエンドポイントが設定することで外部APIのレスポンス結果を利用することができるので、利用して見たのでメモ

前提

外部APIとして、OpenWeatherが提供する無料プランのAPIを利用する。APIの利用には Sing up してAPIキーを利用する必要があるので、発行しておく。

利用するAPI

$ curl api.openweathermap.org/data/2.5/weather?q=Tokyo&appid={API key}
  • レスポンス
    • 以下のような形式でレスポンスが帰ってくるので、こちらをAppSyncを介して取得できるようにする

{
  "coord": { "lon": 139.7531, "lat": 35.6854 },
  "weather": [
    {
      "id": 803,
      "main": "Clouds",
      "description": "broken clouds",
      "icon": "04d"
    }
  ],
  "base": "stations",
  "main": {
    "temp": 290.55,
    "feels_like": 289.43,
    "temp_min": 288.71,
    "temp_max": 291.48,
    "pressure": 1019,
    "humidity": 55
  },
  "visibility": 10000,
  "wind": { "speed": 1.03, "deg": 0 },
  "clouds": { "all": 75 },
  "dt": 1616214160,
  "sys": {
    "type": 1,
    "id": 8077,
    "country": "JP",
    "sunrise": 1616186707,
    "sunset": 1616230318
  },
  "timezone": 32400,
  "id": 1861060,
  "name": "Japan",
  "cod": 200
}

AppSync APIの作成

  • AWSコンソール上で、一から構築を選択し、APIの作成を行なってみた

スキーマ定義の作成

  • openweather APIのレスポンスを、そのままGraphqlの型として作成した。作成し終わったらスキーマ定義を保存する
type Clouds {
    all: String
}

type Coord {
    lon: String
    lat: String
}

type CurrentWeather {
    coord: Coord
    weather: [Weather]
    base: String
    main: Main
    visibility: String
    wind: Wind
    clouds: Clouds
    dt: String
    sys: Sys
    timezone: String
    id: String
    name: String
    cod: String
}

type Main {
    temp: String
    feels_like: String
    temp_min: String
    temp_max: String
    pressure: String
    humidity: String
}

## クエリの実行
type Query {
    currentWeather(q: String, appid: String): CurrentWeather
}

type Sys {
    type: String
    id: String
    countory: String
    sunrise: String
    sunset: String
}

type Weather {
    id: String
    main: String
    description: String
    icon: String
}

type Wind {
    speed: String
    deg: String
}

# ルートスキーマ
schema {
    query: Query
}

データソースの作成

以下のようにデータソースを作成する

  • データソース名:openweathermap_api
  • データソースのタイプ:HTTPエンドポイント
  • エンドポイント:https://api.openweathermap.org

リゾルバーの設定

  • 作成したスキーマ定義のQuery「currentWeather」のリゾルバー設定を行う。データソースは先ほど作成した、「openweathermap_api」を利用する

リクエストマッピングテンプレート

  • resourcePathをapiのパス(/data/2.5/weather)に変更する。他はデフォルトで問題なし
{
  "version": "2018-05-29",
  "method": "GET",
  "resourcePath": "/data/2.5/weather",
  "params":{
      "query":$util.toJson($ctx.args)
  }
}

レスポンスマッピングテンプレート

  • デフォルトのままで問題なし
## Raise a GraphQL field error in case of a datasource invocation error
#if($ctx.error)
  $util.error($ctx.error.message, $ctx.error.type)
#end
## If the response is not 200 then return an error. Else return the body **
#if($ctx.result.statusCode == 200)
    $ctx.result.body
#else
    $utils.appendError($ctx.result.body, "$ctx.result.statusCode")
#end

クエリを投げてみる

  • 上記でAPIのレスポンス取得のための設定ができたので、AWSコンソール上からクエリを投げてみる。レスポンスに必要なパラメータのみ指定することが可能
query MyQuery {
  currentWeather(appid: "{APIキー}", q: "Tokyo") {
    weather {
      description
    }
    name
    main {
      feels_like
      humidity
      pressure
      temp
      temp_max
      temp_min
    }
  }
}
  • レスポンス
    • 指定した形式でレスポンス情報の取得ができた
{
  "data": {
    "currentWeather": {
      "weather": [
        {
          "description": "broken clouds"
        }
      ],
      "name": "Tokyo",
      "main": {
        "feels_like": "288.95",
        "humidity": "63",
        "pressure": "1018",
        "temp": "290.61",
        "temp_max": "291.15",
        "temp_min": "289.82"
      }
    }
  }
}

クエリの追加

  • クエリを新たに追加し、一つのデータソースで複数リゾルバーで利用することで、異なるURLへのリクエストが可能なので設定して試してみる

追加するAPI

$ curl http://api.openweathermap.org/geo/1.0/direct?q=Tokyo&appid={APIキー}
  • レスポンス
[
  {
    "name": "Tokyo Prefecture",
    "local_names": {
      "ascii": "Tokyo Prefecture",
      "en": "Tokyo",
      "feature_name": "Tokyo Prefecture",
      "fr": "Préfecture de Tokyo",
      "ja": "東京都"
    },
    "lat": 35.6895,
    "lon": 139.6917,
    "country": "JP"
  }
]

スキーマ定義

  • 新たに下記のスキーマ定義を追加する
type Query {
    currentWeather(q: String, appid: String): CurrentWeather
    geoCoding(q: String, appid: String): [GeoCoding] # こちらを追加
}

# 追加
type GeoCoding {
    name: String
    local_names: localNames
    lat: String
    lon: String
    country: String
}

# 追加
type localNames {
    ascii: String
    en: String
    feature_name: String
    fr: String
    ja: String
}

リゾルバーの設定

  • 追加したスキーマ定義のQuery「geoCoding」のリゾルバー設定を行う。データソースは最初に作成したものと同じ、「openweathermap_api」を利用する

リクエストマッピングテンプレート

  • resourcePathをapiのパス(/geo/1.0/direct)に変更する。他はデフォルトで問題なし
{
  "version": "2018-05-29",
  "method": "GET",
  "resourcePath": "/geo/1.0/direct",
  "params":{
      "query":$util.toJson($ctx.args),
  }
}

レスポンスマッピングレンプレート

  • デフォルトで問題なし
## Raise a GraphQL field error in case of a datasource invocation error
#if($ctx.error)
  $util.error($ctx.error.message, $ctx.error.type)
#end
## If the response is not 200 then return an error. Else return the body **
#if($ctx.result.statusCode == 200)
    $ctx.result.body
#else
    $utils.appendError($ctx.result.body, "$ctx.result.statusCode")
#end

再度クエリを投げてみる

  • クエリにgeoCodingが追加されるので、パラメータを設定してクエリを投げてみる
query MyQuery {
  currentWeather(appid: "{APIキー}", q: "Tokyo") {
    weather {
      description
      icon
      id
      main
    }
    name
    main {
      feels_like
      humidity
      pressure
      temp
      temp_max
      temp_min
    }
  }
  geoCoding(appid: "{APIキー}", q: "Tokyo") {
    country
    lat
    local_names {
      ascii
      en
      feature_name
      fr
      ja
    }
    lon
    name
  }
}
  • レスポンス
    • geoCodingのAPIレスポンスについても取得ができた。Graphqlへの一回リクエストで複数APIのレスポンス情報が取得できた
{
  "data": {
    "currentWeather": {
      "weather": [
        {
          "description": "light rain",
          "icon": "10n",
          "id": "500",
          "main": "Rain"
        }
      ],
      "name": "Tokyo",
      "main": {
        "feels_like": "287.63",
        "humidity": "88",
        "pressure": "1017",
        "temp": "288.95",
        "temp_max": "289.82",
        "temp_min": "288.15"
      }
    },
    "geoCoding": [
      {
        "country": "JP",
        "lat": "35.6895",
        "local_names": {
          "ascii": "Tokyo Prefecture",
          "en": "Tokyo",
          "feature_name": "Tokyo Prefecture",
          "fr": "Préfecture de Tokyo",
          "ja": "東京都"
        },
        "lon": "139.6917",
        "name": "Tokyo Prefecture"
      }
    ]
  }
}

参考

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1