0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

0
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"
      }
    ]
  }
}

参考

0
1
0

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
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?