Open9

PostgRESTおためし🦩

もももも

PostgRESTをとりあえず動かす

Windows (arm64) + WSL2 + Docker でやる

Dockerイメージ↓

postgres              16.4        75282fa229a1   3 months ago   453MB
postgrest/postgrest   latest      caefe98d7bc4   3 months ago   322MB
もももも

1. PostgreSQLコンテナ立ち上げる

  1. docker run
$ docker run --net=test_nw --name tutorial -p 5432:5432 -e POSTGRES_PASSWORD=notused -d postgres:16.4
  1. docker ps
CONTAINER ID   IMAGE           COMMAND                   CREATED         STATUS         PORTS                    NAMES
3a44deaef93e   postgres:16.4   "docker-entrypoint.s…"   5 seconds ago   Up 4 seconds   0.0.0.0:5432->5432/tcp   tutorial

※psqlのユーザはpostgres

$ docker exec -it tutorial /bin/sh
# psql
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL:  role "root" does not exist
# su - postgres
postgres@3a44deaef93e:~$ psql
psql (16.4 (Debian 16.4-1.pgdg120+1))
Type "help" for help.

postgres=# exit
postgres@3a44deaef93e:~$
もももも

2. スキーマとテーブルを作成する

スキーマを作る必要があるらしい。

The first thing we’ll do is create a named schema for the database objects which will be exposed in the API. We can choose any name we like, so how about “api.” Execute this and the other SQL statements inside the psql prompt you started.

https://docs.postgrest.org/en/v12/tutorials/tut0.html

  1. スキーマの作成
postgres=# create schema api;
CREATE SCHEMA
  1. テーブルの作成
postgres=# create schema api;
CREATE SCHEMA
postgres=# create table api.todos (
  id int primary key generated by default as identity,
  done boolean not null default false,
  task text not null,
  due timestamptz
);
CREATE TABLE
postgres=# insert into api.todos (task) values
  ('finish tutorial 0'), ('pat self on back');
INSERT 0 2
postgres=#
もももも

3. ロールの作成

PostgRESTからのWebリクエスト用にロールを作っておくらしい。

Next make a role to use for anonymous web requests. When a request comes in, PostgREST will switch into this role in the database to run queries.

https://docs.postgrest.org/en/v12/tutorials/tut0.html

  1. 匿名のWEbリクエスト用のロール
postgres=# create role web_anon nologin;

grant usage on schema api to web_anon;
grant select on api.todos to web_anon;
CREATE ROLE
GRANT
GRANT
postgres=#
  1. PostgRESTからのDB接続用ロール
create role authenticator noinherit login password 'mysecretpassword';
grant web_anon to authenticator;

PostgreSQL側の設定はおわり

もももも

4. PostgRESTコンテナを立ち上げる①

チュートリアル通りに設定したときのURLは↓

postgres://authenticator:mysecretpassword@localhost:5432/postgres

docker run↓

docker run --rm -p 3000:3000 \
  --net=test_nw \
  -e PGRST_DB_URI="postgres://authenticator:mysecretpassword@tutorial:5432/postgres" \
  postgrest/postgrest

この状態でlocalhost:3000にアクセスすると

動いてはいる。

もももも

5. PostgRESTコンテナを立ち上げる②

環境変数が足りなかった

postgREST.list
PGRST_DB_URI=postgres://authenticator:mysecretpassword@tutorial:5432/postgres
PGRST_DB_SCHEMAS=api
PGRST_DB_ANON_ROLE=web_anon

envファイル作って再実行

docker run --rm -p 3000:3000 \
  --net=test_nw \
  --env-file postgREST.list \
  postgrest/postgrest

無事に取れた!

もももも

6. テーブル更新編(シークレット作成まで)

①テーブル更新用のロールを作成する

※postgresコンテナで作業

チュートリアル通りにロールを作成&権限を付与↓

create role todo_user nologin;
grant todo_user to authenticator;
grant usage on schema api to todo_user;
grant all on api.todos to todo_user;
grant usage, select on sequence api.todos_id_seq to todo_user;

②シークレットを作る

WSLのUbuntu上で作った

$ export LC_CTYPE=C
echo "jwt-secret = \"$(< /dev/urandom tr -dc A-Za-z0-9 | head -c32)\"" >> tutorial.conf

出力された文字列は以下のように環境変数として設定しておく。

postgREST.list
PGRST_DB_URI=postgres://authenticator:mysecretpassword@tutorial:5432/postgres
PGRST_DB_SCHEMAS=api
PGRST_DB_ANON_ROLE=web_anon
PGRST_JWT_SECRET={出力された文字列}

③アクセストークンを作る

以下のページでアクセストークンを作る
https://jwt.io/#debugger-io

PAYLOAD
{
  "role": "todo_user"
}
VERIFY SIGNATURE
HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
  {作ったシークレット}
)
もももも

6. テーブル更新編(リクエスト投げる)

※VSCodeのREST Clientを使用しています。
※postgRESTコンテナの再起動をわすれない(1敗)

GETしてみる

GET用.http
GET http://localhost:3000/todos HTTP/1.1
レスポンス
[
  {
    "id": 1,
    "done": false,
    "task": "finish tutorial 0",
    "due": null
  },
  {
    "id": 2,
    "done": false,
    "task": "pat self on back",
    "due": null
  }
]

POST(Insert)してみる

POST用.http
POST http://localhost:3000/todos HTTP/1.1
Authorization: Bearer {アクセストークン}
Content-Type: application/json

{
    "task": "learn how to auth"
}
レスポンス
HTTP/1.1 201 Created
Transfer-Encoding: chunked
Date: Wed, 13 Nov 2024 14:57:58 GMT
Server: postgrest/12.2.3 (519615d)
Content-Range: */*

追加できたか確認

GET用.http
GET http://localhost:3000/todos HTTP/1.1
レスポンス
[
  {
    "id": 1,
    "done": false,
    "task": "finish tutorial 0",
    "due": null
  },
  {
    "id": 2,
    "done": false,
    "task": "pat self on back",
    "due": null
  },
  {
    "id": 3,
    "done": false,
    "task": "learn how to auth",
    "due": null
  }
]
もももも

宿題

  • GET/POSTはできたので、DELETE/PATCH/PUTを確認したい
  • 色々な型を試す
  • docker-composeにする