DockerとHasuraで爆速GraphQL API構築!Rustでアクセスしてみよう
はじめに#
Graphql 使っていますか?
iamfax.comではgraphqlを積極的に使っています。Graphqlは最初中々使う理由を見いだせないかもしれませんが、
- エンドポイントが一つでまとまり、バージョン管理の簡略化( v1/v2/.. などのRESTあるあるがなくなる)
- 強力な型システム
- リレーションシップを持つデータを一度のリクエストで取得可能
- リアルタイムデータのためのサブスクリプション
等、使ってみると強力な機能があり、なにはともあれまずは一度は使ってみることをおすすめします。RESTでよくね?と感じると思うかもしれませんが、使えば良さがわかって来ると思います。
さて、実際にGraphql使ってみましょう!というのは簡単ですが、使うための環境構築が面倒です。そこで、今回はGraphqlを手軽に使うために、オープンソースのHASURAを使ってGRAPHQLサーバーを作り、使う環境を整えます。
Hasura とは?#
Graphqlの問題?のひとつが構築がめんどくさいというところです。Lalavel, RailsやDjangoなどで構築しないと…なんて考えるとDockerがあるとはいえ面倒です。そこでHASURAです。
HASURAはテーブルさえ作ればGraphQLサーバーを構築することが可能なオープンソースのGraphQLサーバーです!PostgreSQLのテーブルを作るだけでいいんです!随分お手軽でしょう?
HasuraはGUIのポチポチとするだけでサーバーが作れますので、今回はStep by stepで画像形式でインストール方法を説明していきます。
最後にRUSTでアクセスして通信する事例もご紹介します。
Docker compose を使って Hasura を構築する#
次のDocker compose を用意します。
services:
postgres:
image: postgres:16.1 # 最新のPostgreSQLイメージを指定
restart: always
volumes:
- db_data:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: postgrespassword # 強力なパスワードに変更してください
graphql-engine:
image: hasura/graphql-engine:v2.47.0 # 最新のHasuraイメージを確認してください
ports:
- "8080:8080"
depends_on:
- "postgres"
restart: always
environment:
## postgres database to store Hasura metadata
HASURA_GRAPHQL_METADATA_DATABASE_URL: postgres://postgres:postgrespassword@postgres:5432/postgres
## this env var can be used to add the above postgres database to Hasura as a data source. this can be removed/updated based on your needs
PG_DATABASE_URL: postgres://postgres:postgrespassword@postgres:5432/postgres
## enable the console server
HASURA_GRAPHQL_ENABLE_CONSOLE: "true" # set to "false" to disable console
## enable debugging mode. It is recommended to disable this in production
HASURA_GRAPHQL_DEV_MODE: "true"
HASURA_GRAPHQL_ENABLED_LOG_TYPES: startup, http-log, webhook-log, websocket-log, query-log
## uncomment next line to set an admin secret
# HASURA_GRAPHQL_ADMIN_SECRET: myadminsecretkey
volumes:
db_data:
Docker compose 環境は構築済みと仮定しています。まだの人は公式サイトを参考に構築しましょう。
Hasura: GUIでテーブルを作る方法#
Hasuraコンソールの上部メニューから「DATA」を選択します。
このような画面になるので、「Connect Database」を押してPostgres dbを選択します。
ここで、DBのセットアップができます。Environment variableにしておき、先程のDocker compose に記載されている
HASURA_GRAPHQL_METADATA_DATABASE_URL
と書きます。Database nameは適当で構いません。Connect databaseを押します。
テーブルを作る#
DBと接続できたら試しに、Userテーブルを作ります。dataより、「Create Table」ボタンをクリックします。
テーブル情報を入力します:
```Table Name: users
Columns:
id (Type: Integer (auto-increment), Primary Key: チェック)
name (Type: Text, Nullable: false)
email (Type: Text, Nullable: true, Unique: チェック)
Primary Key: id
上記のような形になったら、「Add Table」をクリックします。
サンプルデータを追加する#
「Insert Row」タブで、いくつかサンプルデータを追加します(例: id=1, name=“Alice”, email=“[email protected]”)。
上部メニューから「API」を選択します。
GraphiQLエクスプローラーが表示されるので、以下のクエリを試してみてください。
query MyQuery {
users {
id
name
email
}
}
RUSTでアクセスする#
外部からアクセスできるかどうか、今回はRUSTで試してみます。別にPythonだろうがRuby, Goだろうがいいのですが、今回は型厳格なGraphqlを使っていますので、せっかくならRUSTで試してみましょう。
次のmain.rsを用意します。
use reqwest::Client;
use serde::{Deserialize};
use serde_json::json; // serde_json::json! マクロを使うために必要
// GraphQLのレスポンス構造体 (usersクエリに対応)
#[derive(Debug, Deserialize)]
struct User {
id: i32,
name: String,
email: Option<String>, // emailはNullableなのでOption
}
#[derive(Debug, Deserialize)]
struct UsersData {
users: Vec<User>,
}
#[derive(Debug, Deserialize)]
struct GraphQLResponse {
data: Option<UsersData>, // "data"フィールドはクエリ成功時に存在する
errors: Option<serde_json::Value>, // エラーがあればここに入る
}
// Hasuraのエンドポイント
const HASURA_ENDPOINT: &str = "http://localhost:8080/v1/graphql";
// 必要であればAdmin Secretを設定 (docker-compose.ymlで設定した場合)
// const HASURA_ADMIN_SECRET: &str = "myadminsecretkey";
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = Client::new();
// 実行したいGraphQLクエリ
let query = r#"
query GetAllUsers {
users {
id
name
email
}
}
"#;
// GraphQLリクエストのペイロード
let request_payload = json!({
"query": query,
// "variables": {} // 必要であれば変数を追加
});
println!("Sending GraphQL query to Hasura...");
let request_builder = client.post(HASURA_ENDPOINT)
.header("Content-Type", "application/json");
// Admin Secretが設定されている場合はヘッダーに追加
// if !HASURA_ADMIN_SECRET.is_empty() {
// request_builder = request_builder.header("X-Hasura-Admin-Secret", HASURA_ADMIN_SECRET);
// }
let response = request_builder
.json(&request_payload)
.send()
.await?;
if response.status().is_success() {
let gql_response: GraphQLResponse = response.json().await?;
if let Some(data) = gql_response.data {
println!("Successfully fetched users:");
for user in data.users {
println!(
" ID: {}, Name: {}, Email: {}",
user.id,
user.name,
user.email.as_deref().unwrap_or("N/A") // Option<String>の表示
);
}
} else if let Some(errors) = gql_response.errors {
eprintln!("GraphQL errors: {:?}", errors);
} else {
eprintln!("Received successful response but no data or errors.");
}
} else {
eprintln!(
"Failed to query Hasura. Status: {}. Body: {}",
response.status(),
response.text().await?
);
}
Ok(())
}
cargo.tomlは次のとおりです。
[package]
name = "hasura_rust_hello"
version = "0.1.0"
edition = "2024"
[dependencies]
tokio = { version = "1", features = ["full"] }
reqwest = { version = "0.11", features = ["json"] } # HTTPクライアント
serde = { version = "1.0", features = ["derive"] } # JSONのシリアライズ/デシリアライズ
serde_json = "1.0" # JSON操作
さて、実行してみましょう
$ cargo run
Sending GraphQL query to Hasura...
Successfully fetched users:
ID: 1, Name: fax_all_you_need_is, Email: [email protected]
きちんと表示されれば成功です
おわりに#
今回は、Docker ComposeとHasuraを使って、非常に手軽にGraphQL APIサーバーをローカル環境に構築し、Rustからアクセスする方法をご紹介しました。Hasuraの「テーブルを作るだけでGraphQL APIが完成する」という手軽さは、GraphQLを試してみたい、あるいは迅速にAPIをプロトタイピングしたい場合に大きなメリットとなります。
GUIで直感的に操作できるため、学習コストも比較的低く、すぐにGraphQLの強力な機能を体験できるでしょう。
Hasuraの限界と考慮点
これほど便利なHasuraですが、「これだけで全てOK!」というわけではありません。いくつかの限界や、より複雑なシステムを構築する際に考慮すべき点があります。
複雑なビジネスロジックの分離: 例えば、「ユーザー登録時にウェルカムメールを送信する」や「注文確定時に複数の外部サービスと連携して処理を行う」といった、データベース操作以外の複雑な副作用やワークフローを含むビジネスロジックは、Hasura自体に直接書き込むことはできません。これらはHasuraの Actions や Event Triggers といった機能を使って、外部のカスタムロジック(例えばRustやPythonで書いた別のマイクロサービスやサーバーレス関数)に処理を委譲する形で実装する必要があります。
リクエスト/レスポンスの高度な処理: クライアントからのリクエストデータや、データベースからのレスポンスデータを、Hasuraが自動的に行う以上の複雑な形式に変換したり、高度なバリデーションを行ったりする処理は、Hasura単体では難しいです。これも同様にActionsなどを活用して、連携する外部サービス側で対応することになります。
つまり、Hasuraはデータベースを中心としたGraphQL APIの強力な基盤として機能しますが、アプリケーション全体のロジックを全て担うわけではありません。Hasuraの得意な部分(DBからのAPI自動生成、認証・認可、リアルタイム性など)を活かしつつ、より複雑な部分は他のサービスと連携させるアーキテクチャを考えることが重要です。
とはいえ、多くの一般的なウェブアプリケーションやモバイルバックエンドにおいて、Hasuraは開発速度を大幅に向上させ、GraphQLの恩恵をすぐに享受できる素晴らしいツールです。ぜひ、ご自身のプロジェクトで試してみてください!