LoginSignup
15
5

More than 1 year has passed since last update.

Hasura v2.1.0で導入されたActions transformerを使って、好きなREST APIをGraphQLに繋げてみよう

Last updated at Posted at 2021-12-25

はじめに

Hasuraという、DBテーブルから自動的にGraphQL APIを作成してくれるGraphQLサーバーがあります。

「Hasuraって何?」という方は、「多機能なGraphQLサーバー: Hasura GraphQL Engineを知っておきたい人が読む記事」を読んでいただけると幸いです。

さて、先日このHasuraのコアとなる、hasura/Graphql-engineのマイナーアップデート版であるv2.1.0が公開されました。

v2.1.0のアップデート内容には、hasura metadata deployコマンドの登場やEvent Trigger transforms機能など、かなり多くの機能追加・修正が加えられています。
便利な機能が目白押しですが、中でも目玉はActions transformer機能でしょう。

この機能の登場により、HasuraからリクエストメソッドやURLを自由に組み立てて、様々なREST APIへ接続ができるようになりました。

本記事では、このActions transformerの概要紹介と、ちょっとしたサンプルを使って簡単な使い方の説明を行います。
公式ドキュメントにも使い方は書いてあるのですが、少し説明が足りない部分がある&機能が複雑でわかりにくい部分があるため、日本語の情報源として役に立てればいいかなと思い、本記事を公開しました。

本記事の要約

  • Hasura v2.1.0のアップデートで、Actions transformer機能が追加された

  • 今まではPOSTでしかREST APIに接続できなかったが、この機能によりGETPATCHなどのリクエストメソッドでHTTPリクエストができるようになった

環境

おさらい: Hasura Action

Hasuraは、DBスキーマから基本的なCRUDと集計(aggregate)スキーマを自動生成してくれます。ではユーザー独自のロジックを組み込むにはどうするかというと、外部APIを使用して拡張するという方法をとります。

Hasura Actionは、外部REST APIと接続し、そのレスポンス結果をGraphQLのスキーマに埋め込めるという機能です1

Screenshot 2021-12-21 22.10.47.png

図: https://hasura.io/docs/latest/graphql/core/actions/index.html

このHasura Actionはとても便利な機能なのですが、REST APIとの接続をwebhoookで行うため、以下のような制限がありました。

  • リクエストメソッドはPOSTのみ
  • エンドポイントを動的にできない
    • 例:/api/v2/users/:user_id/followers:user_idの部分を動的に変えることができない

このため、接続先APIをHasuraに合わせて改修する必要がある・外部サービスのAPIが使えないなどの制限があり、お世辞にも不自由なくREST APIと接続できるとは言いづらい状態でした。

ですが、この度のv2.1.0アップデートにより、接続先のREST APIにかかる制限がほとんどなくなりました。

v2.1.0で導入されたActions transformer

Actions transformerは、Hasura Acitonで接続するREST APIへのリクエストをカスタマイズできる機能です。
リリースノートやドキュメントを読むと、「Actionによって生成されるHTTPリクエストを変換する」2とあり、webhookリクエストをうまく変換しているようです。

カスタマイズできる接続先APIの設定は、下記に述べるようにかなり多岐にわたります。

  • エンドポイント
  • クエリパラメータ
  • リクエストメソッド
  • リクエストヘッダー
  • リクエストボディ
  • Content Type

設定が細かくできるようになったため、Hasura Actionの設定画面も以前と見比べるとリッチになりました。

v2.1.0以前 v2.1.0以後

次章で、Actions transformer機能でカスタマイズできる設定を1つづつ確認していきます。

【コラム】
Actions transformerには関係しませんが、Action設定画面に新しく増えた「Declared Global Types」という部分で、
他のActionで作成したスキーマの型が表示されるようになりました。
今まで、それぞれのActionでどんな型が定義されているかはActionの設定画面に行かないとわからなかったため、一眼でどのような型があるかを確認できるようになり非常に便利になりました。

Screenshot 2021-12-22 0.04.28.png

##設定できること

リクエストURL

Webhook(HTTP/S)Handler

リクエストURLは、「Webhook(HTTP/S)Handler」という設定項目で行います。

動的に変化するURLではない限り、対象APIのエンドポイントに含まれるパスの情報はここで設定します。
従来通り、ACTION_BASE_URLという環境変数を設定し、{{ACTION_BASE_URL}}とすることで環境変数を埋め込むことができます。

動的に変化する場合やクエリパラメータを含めたい場合は、後述する「Request Options Transformation」で行います。

リクエストメソッド・クエリパラメータ・(動的な)リクエストURL

「Request Options Transformation」という設定項目で、上記項目を設定できます。

Screenshot 2021-12-22 0.15.43.png

Request Method

ここでは、リクエストメソッドをGET / POST / PUT / PATCH / DELETEから選択できます。

Request URL Template

ここでは、動的なURLを設定できます。
{{$base_url}} + 「動的なパス」というフォーマットになっており、{{$base_url}}には、先述した「Webhook(HTTP/S) Handler」で設定したURLが展開されます。

「動的なパス」部分には、Hasura Actionの変数を展開して設定ができます。ここで使用できるHasura Actionの変数は以下になります。

名前 説明 書き方例   補足
$body Hasura Actionで作成したInputスキーマ Object {{$body.input.arg}} 書き方例は、以下のような引数を持つActionスキーマから取得する例SampleAction(arg: String!):
$session_variables クライアントから送られてくるHeaderに入っているsession_variables Array {{$session_variables['x-hasura-user-id']}} 書き方例は、session_variablesの中にあるx-hasura-user-idから取得する例

変数展開ができることにより、「Action引数の値をパスの一部にする」というような、自由なパス設計が可能になりました。

Query Params

ここでは、クエリパラメータを設定できます。設定はkey_value形式で行います。
Screenshot 2021-12-22 0.52.16.png

下記の図のように、クエリパラメータのKeyとvalueにも、Actionの変数を使用できます。

Screenshot 2021-12-22 0.54.33.png

Payload Transformation

今までは、以下のようなリクエストボディの形式でしかAPIにリクエストができませんでした。"input"という階層が挟まっています。

input {
  # Actionの引数が入る
  args: {
  ...
  }
}

v2.1.0からは、Hasuraから送るリクエストのボディを自由に設定ができます。
Actionの変数を利用でき、Configure Request Bodyエディタで記述します。どのように変換されるのかは、下のTransformed Request Bodyで確認ができます。
スクリーンショット 2021-12-25 17.40.14.png

実際に試してみる

ここからは、実際にHasuraから外部REST APIに接続してみます。

このチュートリアルでは、「**HasuraからQiita V2 APIに接続し、指定したユーザーの情報を取得する」**までを行います。

今回のチュートリアルで作るサンプルコードは以下のGitHubリポジトリにまとめています。READMEに沿っていただければ、Hasuraの動作環境が立ち上がります。

スキーマ作成

Actionのスキーマを設定します。まずは、Hasuraコンソール画面で[Actions] -> [create]で新しくActionを作成します。
続いて、Actionのスキーマを定義します。今回は以下のように作成しました。

type Query {
  find_qiita_user (user_id: String!): qiita_user
}

find_qiita_userというアクション(リゾルバ)名で、String型(必須)のuser_idを引数をとり、qiita_userという型の値を返します。

今回作成するqiita_user型は、Qiita APIのレスポンスの形にします。今回は[GET /api/v2/users/:user_id](https://qiita.com/api
/v2/docs#get-apiv2usersuser_id)を叩くため、ドキュメントを参考にしてスキーマを作成します。

type qiita_user {
  id: String!
  description: String!
  followers_count: Int!
  followees_count: Int!
  name: String!
}

このスキーマは、以下のフィールドを保持しています。

  • ユーザーID
  • 自己紹介コメント
  • フォロワー数
  • フォロー数

ここまでで、Actionは以下の図のようになります。
スクリーンショット 2021-12-25 17.49.48.png

接続設定

接続先APIを設定します。
ベースとなるURLの設定項目**「Webhook (HTTP/S) Handler」**には、今回叩くQiita APIの動的パス以外の部分を設定します。

  • https://qiita.com/api/v2

ヘッダーやタイムアウトの設定項目「headers」・「Action Custom Timeout」は今回設定しません(トークンが必要なAPIや、タイムアウトを制限したい場合には設定します)。また、「Sample Context」・「Payload Transformation」も今回は設定しません。

残るは、リクエストメソッドや動的パスの設定項目「Request Options Transformation」です。
Qiita APIのユーザー取得APIのエンドポイントGET /api/v2/users/:user_idに合わせ、以下のように設定します。

  • /users/{{$body.input.user_id}}
    Screenshot 2021-12-24 0.48.40.png

APIに合わせて、リクエストメソッドはGETとします。
また、{{$body.input.user_id}}とすることで、アクションの引数user_idをurlへ埋め込むようにしています。

小ネタとして、[Payload Transformation]->[Preview]には、実際にアクセスするURLが表示されます。
「Sample Input」のuser_idフィールドの値を変えてみて、発行されるURLをチェックしましょう。

動作確認

実際はappllorelayなどのクライアントライブラリを用いることになりますが、今回の動作確認はHasura Console上のGraphiQLエディタ上で行います。
Screenshot 2021-12-24 0.52.59.png

Qiita APIを叩いて取得したデータがちゃんとレスポンスに入っていますね!🎉

注意点

現在(2021/12/20)、APIのレスポンスのスキーマはネストできないという問題があります。
2022/02追記
Hasura v2.2.0のリリースにより、入れ子構造になった返り値を返せるようになりました!

詳細は以下を参考にしてください。

おわりに

いかかでしたでしょうか。Actions transformerの登場により、Hasura Actionで接続するAPIの幅がかなり広がりました。
本記事ではQIita APIを取り上げましたが、Hasura公式にData Hubという公式サンプル集があります。FirebaseやElasticSearchなどのサンプルがありますので、軽く読んでみるのも良いでしょう。

  1. 本題と逸れるため説明を省きましたが、RESTではなく外部GraphQL APIと接続するHasura Remote Schemasという機能もあります。

  2. 参考:https://hasura.io/docs/latest/graphql/core/actions/transforms.html#action-transforms

15
5
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
15
5