herohoroブログ

HTTPメソッドを理解したいならNotionAPIを使ってコマンドラインで通信せよ



🔄   2022-08-02

JSONを丸っと記載した関係でいつも以上に長いです。

⌘Nで複数ウィンドウにして、JSONと説明とを見比べながら読み進めると分かりやすいかもです…m(_ _)m

easy-notion-blogを楽しむための文献シリーズ第二弾\(^o^)/

Webを支える技術」の第7章周辺にどっぷり浸かりたいと思います。

アウトプットしていきましょ〜〜〜〜〜〜〜〜🚀🚀🚀🚀🚀

HTTPについて

HTTPはIP(Internet Protocol)をベースにしたTCP(transmission Control Protocol)の上に構成されたプロトコル…。

よくわからないので簡単に整理すると….

IP:PCでいつものようにインターネット通信をする

TCP:通信中の対応しきれないデータをしれっとフォローしてくれる

HTTP:通信されたデータを具体的に引き出せるようにしてくれる

そんなイメージかな🎶(*´∀`*)(*´∀`*)

引き出せるようにするためにHTTPでは必要最低限なメソッドを駆使しているようです。

まさに、

「お・は・し・も」理論。

小学生の頃避難訓練でやりましたよね。

  • 【お】さない
  • 【は】しらない
  • 【し】ゃべらない
  • 【も】どらない

これは先生が指示する声が通らないと子どもたちが危険な目に合ってしまわないようにするための決まりごと。

  • 【お】さない👉 急がず付いて来てね
  • 【は】しらない👉 歩けば大丈夫
  • 【し】ゃべらない👉 本当に必要な声を聞き取ってね
  • 【も】どらない👉 忘れ物より君の命が大切だよ

こんなメッセージが込められています。多分 😂

HTTPを置き換えるとこんな感じ。

  • 【お】さない👉データを冷静に取得する
  • 【は】しらない👉 データをざっくり管理
  • 【し】ゃべらない 👉 データをしっかり管理
  • 【も】どらない👉 無駄なデータは削除

若干の無理矢理感は否めませんが、

イメージとしてはこんな感じです😂

HTTPメッセージ構成

メールのような雛形なので分かりやすいです。

スタートラインリクエスト:【リクエストライン】
ヘッダ形式【名前:値】
ボディ本質的な情報

この雛形にどのように入れていくのかは実際にNotionAPIに触れてみると急に納得できるので後半また復習します。

HTTPメソッド

参考書には8つ紹介されていますが

主に使う4つを紹介します。

  • GET

データを取得する

  • POST

子要素に対してデータの取得・追加

※ リンク指定はできないよ。サーバー側で割り当てるよー

  • PUT

指定した要素に対してデータを修正・削除

※ リンクを指定しないと処理できないよ

  • DELETE

指定した要素を削除する

レスポンスにはボディが無いのが特徴。

NotionAPIを見てみよう

ページ内ブロックまで範囲を広げると壮大になるので今回は省略。

実際動かしてみる場合は

Notionに練習用データベースを用意して

Notion Integrationを設定しておいてくださいね(´・ω・`)

私はこんな感じのデータベースを用意してこの記事で解説していきます〜

画像が読み込まれない場合はページを更新してみてください。
サンプル02はdelete操作で消しちゃった

※ サンプルページ01・02をベースにJSONコードと見比べてみてください(;´Д`)

コードの途中の【DATABASE_ID】や【NOTION_API_SECRET】は

easy-notion-blogのセットアップ記事にある「クイックスタート6」以降に

触れているので参考にしてみてくださいm(_ _)m

GET :データベースを取得

画像が読み込まれない場合はページを更新してみてください。

https://developers.notion.com/reference/retrieve-a-database

データベースを1つ取得するだけならRetrieve a databaseで良さそうです⭐

2つ以上取得する場合はList databases (deprecated)を使うといいよ🐰

curl 'https://api.notion.com/v1/databases/~~~~~DATABASE_ID~~~~' \
  -H 'Authorization: Bearer '~~~~~~~~~~NOTION_API_SECRET~~~~~~~~~~~'' \
  -H 'Notion-Version: 2022-02-22'
Retrieve a database【GET】

雛形と照らし合わせて確認すると…..

スタートラインリクエストの場合:【リクエストライン】URL ?
ヘッダ形式【名前:値】-H
ボディ本質的な情報
🤔
リクエストラインに【GET】っていう文字ないな….

ま、細かいことは気にせずターミナルに貼り付けて実行してみると….

{
  "object": "database",
  "id": "~~~~~~~~~~~DATABASE_ID~~~~~~~~~~",
  "cover": null,
  "icon": null,
  "created_time": "2022-06-27T23:59:00.000Z",
  "created_by": {
    "object": "user",
    "id": "148bfa26-a10a-4673-86c7-539868890a5c"
  },
  "last_edited_by": {
    "object": "user",
    "id": "148bfa26-a10a-4673-86c7-539868890a5c"
  },
  "last_edited_time": "2022-06-28T00:06:00.000Z",
  "title": [
    {
      "type": "text",
      "text": { "content": "demo_database", "link": null },
      "annotations": {
        "bold": false,
        "italic": false,
        "strikethrough": false,
        "underline": false,
        "code": false,
        "color": "default"
      },
      "plain_text": "demo_database",
      "href": null
    }
  ],
  "description": [],
  "is_inline": true,
  "properties": {
    "Tags": {
      "id": "KvHU",
      "name": "Tags",
      "type": "multi_select",
      "multi_select": {
        "options": [
          {
            "id": "2fe79b4b-84dc-4ac8-91f8-9d02666c8cdb",
            "name": "天気",
            "color": "red"
          },
          {
            "id": "cc221846-f738-43c8-ba82-e27eb5329ec3",
            "name": "食事",
            "color": "pink"
          }
        ]
      }
    },
    "last_edited_time": {
      "id": "%5D_sX",
      "name": "last_edited_time",
      "type": "last_edited_time",
      "last_edited_time": {}
    },
    "Name": { "id": "title", "name": "Name", "type": "title", "title": {} }
  },
  "parent": {
    "type": "page_id",
    "page_id": "39446be1-b105-4275-a09f-5e15a2fbfa72"
  },
  "url": "https://www.notion.so/44a17fba7a554ab9ad603cab551cfd6c",
  "archived": false
}
Retrieve a database【GET】の結果

練習用データベースと見比べてみると納得!!!

画像が読み込まれない場合はページを更新してみてください。
サンプル02は気にしないでね

🤔
JSONにはタイトル名は出ないんだね~~~

POST:データベース内のページ一覧を取得

画像が読み込まれない場合はページを更新してみてください。

https://developers.notion.com/reference/post-database-query

公式リファレンスのサンプルコードにはフィルターやソートも記述されていましたが、

なにせ私の用意したデータベースは2ページしか無いので割愛し、

普通にページ一覧を取得してみようと思います。

curl -X POST 'https://api.notion.com/v1/databases/~~~~~~~~DATABASE_ID~~~~~/query' \
  -H 'Authorization: Bearer '~~~~~~~~~~NOTION_API_SECRET~~~~~~~~~~~'' \
  -H 'Notion-Version: 2022-02-22' \
  -H "Content-Type: application/json" \
	--data '{

	}'
Query a database【POST】

雛形と照らし合わせて確認すると…..

スタートラインリクエストの場合:【リクエストライン】-X
ヘッダ形式【名前:値】-H
ボディ本質的な情報—data

今回は雛形通りですね〜〜〜〜(*^^*)

ターミナルに貼り付けて実行してみると…..

{
  "object": "list",
  "results": [
    {
      "object": "page",
      "id": "4f1dc74a-eae2-4f92-bb2b-fc7f6b98d9cf",
      "created_time": "2022-06-27T23:59:00.000Z",
      "last_edited_time": "2022-06-28T04:40:00.000Z",
      "created_by": {
        "object": "user",
        "id": "148bfa26-a10a-4673-86c7-539868890a5c"
      },
      "last_edited_by": {
        "object": "user",
        "id": "148bfa26-a10a-4673-86c7-539868890a5c"
      },
      "cover": null,
      "icon": null,
      "parent": {
        "type": "database_id",
        "database_id": "44a17fba-7a55-4ab9-ad60-3cab551cfd6c"
      },
      "archived": false,
      "properties": {
        "Tags": {
          "id": "KvHU",
          "type": "multi_select",
          "multi_select": [
            {
              "id": "2fe79b4b-84dc-4ac8-91f8-9d02666c8cdb",
              "name": "天気",
              "color": "red"
            }
          ]
        },
        "last_edited_time": {
          "id": "%5D_sX",
          "type": "last_edited_time",
          "last_edited_time": "2022-06-28T04:40:00.000Z"
        },
        "Name": {
          "id": "title",
          "type": "title",
          "title": [
            {
              "type": "text",
              "text": { "content": "サンプルページ01", "link": null },
              "annotations": {
                "bold": false,
                "italic": false,
                "strikethrough": false,
                "underline": false,
                "code": false,
                "color": "default"
              },
              "plain_text": "サンプルページ01",
              "href": null
            }
          ]
        }
      },
      "url": "https://www.notion.so/01-4f1dc74aeae24f92bb2bfc7f6b98d9cf"
    },
    {
      "object": "page",
      "id": "d0ed9061-de23-44dd-8ce7-766162837846",
      "created_time": "2022-06-27T23:59:00.000Z",
      "last_edited_time": "2022-06-28T04:40:00.000Z",
      "created_by": {
        "object": "user",
        "id": "148bfa26-a10a-4673-86c7-539868890a5c"
      },
      "last_edited_by": {
        "object": "user",
        "id": "148bfa26-a10a-4673-86c7-539868890a5c"
      },
      "cover": null,
      "icon": null,
      "parent": {
        "type": "database_id",
        "database_id": "44a17fba-7a55-4ab9-ad60-3cab551cfd6c"
      },
      "archived": false,
      "properties": {
        "Tags": {
          "id": "KvHU",
          "type": "multi_select",
          "multi_select": [
            {
              "id": "cc221846-f738-43c8-ba82-e27eb5329ec3",
              "name": "食事",
              "color": "pink"
            }
          ]
        },
        "last_edited_time": {
          "id": "%5D_sX",
          "type": "last_edited_time",
          "last_edited_time": "2022-06-28T04:40:00.000Z"
        },
        "Name": {
          "id": "title",
          "type": "title",
          "title": [
            {
              "type": "text",
              "text": { "content": "サンプルページ03", "link": null },
              "annotations": {
                "bold": false,
                "italic": false,
                "strikethrough": false,
                "underline": false,
                "code": false,
                "color": "default"
              },
              "plain_text": "サンプルページ03",
              "href": null
            }
          ]
        }
      },
      "url": "https://www.notion.so/03-d0ed9061de2344dd8ce7766162837846"
    }
  ],
  "next_cursor": null,
  "has_more": false,
  "type": "page",
  "page": {}
}
Query a database【POST】お結果

Retrieve a databaseでは表示されなかったtitle名も取得されて長くなってきました…..

もう一度練習用データベースを振り返ってみます。

画像が読み込まれない場合はページを更新してみてください。
サンプル02は気にしないでね

ページを開いた時に表示される本文はまだ取得できていない状態ですね〜〜〜。

🖐️
ページ内ブロックまで範囲を広げると壮大になるので今回は省略。

Notion上に用意してある情報を取得できることが分かったので

今度は編集できるようにしてみます。

POST:データベース内にページを作成

画像が読み込まれない場合はページを更新してみてください。

https://developers.notion.com/reference/post-page

「新しく追加したサンプルページ01」というタイトルのページを

本文無しの状態で追加作成してみようと思います。

curl 'https://api.notion.com/v1/pages' \
  -H 'Authorization: Bearer '~~~~~~~~~~NOTION_API_SECRET~~~~~~~~~~~'' \
  -H "Content-Type: application/json" \
  -H "Notion-Version: 2022-02-22" \
  --data '{
	"parent": { "database_id": "~~~~~~~~DATABASE_ID~~~~~" },

	"properties": {
		"Name": {
			"title": [
				{
					"text": {
						"content": "新しく追加したサンプルページ01"
					}
				}
			]
		}
		
	}
}'
Create a page【POST】

雛形と照らし合わせて確認すると…..

スタートラインリクエストの場合:【リクエストライン】URL?
ヘッダ形式【名前:値】-H
ボディ本質的な情報—data

🤔
リクエストラインがURLのみのメソッドとそうでないのとは何が違うんだ???

ターミナルに貼り付けて実行してみると…..

{
  "object": "page",
  "id": "8c04d30b-7a46-4765-a112-74675c2a5079",
  "created_time": "2022-06-28T07:51:00.000Z",
  "last_edited_time": "2022-06-28T07:51:00.000Z",
  "created_by": {
    "object": "user",
    "id": "be3c2f0f-6429-4ca9-8156-4844563afe67"
  },
  "last_edited_by": {
    "object": "user",
    "id": "be3c2f0f-6429-4ca9-8156-4844563afe67"
  },
  "cover": null,
  "icon": null,
  "parent": {
    "type": "database_id",
    "database_id": "44a17fba-7a55-4ab9-ad60-3cab551cfd6c"
  },
  "archived": false,
  "properties": {
    "Tags": { "id": "KvHU", "type": "multi_select", "multi_select": [] },
    "last_edited_time": {
      "id": "%5D_sX",
      "type": "last_edited_time",
      "last_edited_time": "2022-06-28T07:51:00.000Z"
    },
    "Name": {
      "id": "title",
      "type": "title",
      "title": [
        {
          "type": "text",
          "text": { "content": "新しく追加したサンプルページ01", "link": null },
          "annotations": {
            "bold": false,
            "italic": false,
            "strikethrough": false,
            "underline": false,
            "code": false,
            "color": "default"
          },
          "plain_text": "新しく追加したサンプルページ01",
          "href": null
        }
      ]
    }
  },
  "url": "https://www.notion.so/01-8c04d30b7a464765a11274675c2a5079"
}
Create a page【POST】の結果

Notionの方にも作成されてた\(^o^)/

画像が読み込まれない場合はページを更新してみてください。
😲
FastNotionってこのメソッドを使ってるのかも!?

POST:データベース内のページ名を検索

画像が読み込まれない場合はページを更新してみてください。

https://developers.notion.com/reference/post-search

queryの値に検索したい単語を入れると探せるみたい。

curl -X POST 'https://api.notion.com/v1/search' \
  -H 'Authorization: Bearer '~~~~~~~~~~NOTION_API_SECRET~~~~~~~~~~~'' \
  -H 'Content-Type: application/json' \
  -H "Notion-Version: 2021-08-16" \
  --data '{
    "query":"追加",
		"sort":{
		      "direction":"ascending",
		      "timestamp":"last_edited_time"
		    }
		
  }'
Search 【POST】

「追加」という単語を含むタイトルのページを探してみることにしました(*´ω`*)(*´ω`*)

雛形と照らし合わせて確認すると…..

スタートラインリクエストの場合:【リクエストライン】-X
ヘッダ形式【名前:値】-H
ボディ本質的な情報—data

いいね 🤟

ターミナルに貼り付けて実行してみると…..

{
  "object": "list",
  "results": [
    {
      "object": "page",
      "id": "8c04d30b-7a46-4765-a112-74675c2a5079",
      "created_time": "2022-06-28T07:51:00.000Z",
      "last_edited_time": "2022-06-28T07:51:00.000Z",
      "created_by": {
        "object": "user",
        "id": "be3c2f0f-6429-4ca9-8156-4844563afe67"
      },
      "last_edited_by": {
        "object": "user",
        "id": "be3c2f0f-6429-4ca9-8156-4844563afe67"
      },
      "cover": null,
      "icon": null,
      "parent": {
        "type": "database_id",
        "database_id": "44a17fba-7a55-4ab9-ad60-3cab551cfd6c"
      },
      "archived": false,
      "properties": {
        "Tags": { "id": "KvHU", "type": "multi_select", "multi_select": [] },
        "last_edited_time": {
          "id": "%5D_sX",
          "type": "last_edited_time",
          "last_edited_time": "2022-06-28T07:51:00.000Z"
        },
        "Name": {
          "id": "title",
          "type": "title",
          "title": [
            {
              "type": "text",
              "text": {
                "content": "新しく追加したサンプルページ01",
                "link": null
              },
              "annotations": {
                "bold": false,
                "italic": false,
                "strikethrough": false,
                "underline": false,
                "code": false,
                "color": "default"
              },
              "plain_text": "新しく追加したサンプルページ01",
              "href": null
            }
          ]
        }
      },
      "url": "https://www.notion.so/01-8c04d30b7a464765a11274675c2a5079"
    }
  ],
  "next_cursor": null,
  "has_more": false
}
Search 【POST】の結果

😲
Create a pageと同じように見えるけど【next_cursor】があるね。

リストとして検索してみたけど1件しか無かったからごめんなさいって感じのJSONでした⭐

PATCH:データベース内のページを削除・修正

画像が読み込まれない場合はページを更新してみてください。

https://developers.notion.com/reference/patch-page

削除する

archivedの値をtrueにするとページを消せるようです。

curl https://api.notion.com/v1/pages/~~~~~~~~~PAGE_ID~~~~~~~~~ \
  -H 'Authorization: Bearer '~~~~~~~~~~NOTION_API_SECRET~~~~~~~~~~~'' \
  -H "Content-Type: application/json" \
  -H "Notion-Version: 2022-02-22" \
  -X PATCH \
	--data '{
		"archived": true
		}'
Updata a page【PATCH】

PAGE_IDは…

https://www.notion.so/01-8c04d30b7a464765a11274675c2a5079

の【-より後】で、8c04d30b7a464765a11274675c2a5079になります。

🙈
….. 結構ハマりました

雛形と照らし合わせて確認すると…..

スタートラインリクエストの場合:【リクエストライン】URL?
ヘッダ形式【名前:値】-H
ボディ本質的な情報—data

…. 🤔

Create a pageで作成した

【新しく追加したサンプルページ01】というページを

削除してみます。

ターミナルに貼り付けて実行してみると…..

{
  "object": "page",
  "id": "8c04d30b-7a46-4765-a112-74675c2a5079",
  "created_time": "2022-06-28T07:51:00.000Z",
  "last_edited_time": "2022-06-28T08:22:00.000Z",
  "created_by": {
    "object": "user",
    "id": "be3c2f0f-6429-4ca9-8156-4844563afe67"
  },
  "last_edited_by": {
    "object": "user",
    "id": "be3c2f0f-6429-4ca9-8156-4844563afe67"
  },
  "cover": null,
  "icon": null,
  "parent": {
    "type": "database_id",
    "database_id": "44a17fba-7a55-4ab9-ad60-3cab551cfd6c"
  },
  "archived": true,
  "properties": {
    "Tags": { "id": "KvHU", "type": "multi_select", "multi_select": [] },
    "last_edited_time": {
      "id": "%5D_sX",
      "type": "last_edited_time",
      "last_edited_time": "2022-06-28T08:22:00.000Z"
    },
    "Name": {
      "id": "title",
      "type": "title",
      "title": [
        {
          "type": "text",
          "text": { "content": "新しく追加したサンプルページ01", "link": null },
          "annotations": {
            "bold": false,
            "italic": false,
            "strikethrough": false,
            "underline": false,
            "code": false,
            "color": "default"
          },
          "plain_text": "新しく追加したサンプルページ01",
          "href": null
        }
      ]
    }
  },
  "url": "https://www.notion.so/01-8c04d30b7a464765a11274675c2a5079"
}
Updata a page【PATCH】の結果

Notionの方にも作成されてる\(^o^)/

画像が読み込まれない場合はページを更新してみてください。

HTTPメソッドのところで…..

  • DELETE

指定した要素を削除する

レスポンスにはボディが無いのが特徴。

って書いてあったのは、

消した時にレスポンスが無いってことなのかなってことをイメージしていいのかな… 🤔 💭

修正する

画像が読み込まれない場合はページを更新してみてください。

タイトルを間違えてしまっても後から修正できます(*´ω`*)

削除するコードの"archived": true を書き換えて

【後から修正したタイトルだよ】に変えてみると……

curl https://api.notion.com/v1/pages/~~~~~~~~~~~PAGE_ID~~~~~~~~~~ \
  -H 'Authorization: Bearer '~~~~~~~~~~NOTION_API_SECRET~~~~~~~~~~~'' \
  -H "Content-Type: application/json" \
  -H "Notion-Version: 2022-02-22" \
  -X PATCH \
	--data '{
      "properties": {
        "Name": {
          "title": [
            {
              "text": {
                "content": "後から修正したタイトルだよ"
              }
            }
					]
				}
			}
		}'
Updata a page【PATCH】

画像が読み込まれない場合はページを更新してみてください。

修正されてる〜〜〜〜\(^o^)/

ターミナルはこのような内容…..

{
  "object": "page",
  "id": "b9181804-e7f2-4505-9c1c-4a2a74a98af9",
  "created_time": "2022-06-28T08:31:00.000Z",
  "last_edited_time": "2022-06-28T08:47:00.000Z",
  "created_by": {
    "object": "user",
    "id": "148bfa26-a10a-4673-86c7-539868890a5c"
  },
  "last_edited_by": {
    "object": "user",
    "id": "be3c2f0f-6429-4ca9-8156-4844563afe67"
  },
  "cover": null,
  "icon": null,
  "parent": {
    "type": "database_id",
    "database_id": "44a17fba-7a55-4ab9-ad60-3cab551cfd6c"
  },
  "archived": false,
  "properties": {
    "Tags": { "id": "KvHU", "type": "multi_select", "multi_select": [] },
    "last_edited_time": {
      "id": "%5D_sX",
      "type": "last_edited_time",
      "last_edited_time": "2022-06-28T08:47:00.000Z"
    },
    "Name": {
      "id": "title",
      "type": "title",
      "title": [
        {
          "type": "text",
          "text": { "content": "後から修正したタイトルだよ", "link": null },
          "annotations": {
            "bold": false,
            "italic": false,
            "strikethrough": false,
            "underline": false,
            "code": false,
            "color": "default"
          },
          "plain_text": "後から修正したタイトルだよ",
          "href": null
        }
      ]
    }
  },
  "url": "https://www.notion.so/b9181804e7f245059c1c4a2a74a98af9"
}
Updata a page【PATCH】の結果

🤩
HTTPメソッドのPUT(今回はPATCH)の説明にあった【リンクを指定して】処理するって部分にやっと納得!!!

まとめ

easy-notion-blogをもっと楽しむために読みだした参考書ではありましたが、

後半ちんぷんかんぷんになってしまいました…. 🙈

NotionAPIのリファレンスを参照しながら動かすことで理解が深まった気がします。

なにはともあれ

動かして納得したHTTPメソッドでした\(^o^)/

改造したい機能…

HTTPメソッドを少しばかり理解できたことで

「何か改造したいな〜」という欲求が高まってきました。

  • 検索フォーム?👉 検索するほど読みたい記事ある???
  • コメント機能?👉 嫌なこと書かれたら落ち込みそう…
  • 記事リクエスト機能?👉需要なさそう….

そんなことを思いながら

NotionAPIと仲良くなれた気がした6月でした🎶

Twitterでは更新のお知らせを随時行っています

興味ある方はLet'sフォロー★

▼ この記事に興味があったら同じタグから関連記事をのぞいてみてね

新着記事を通知したい??


RSSリーダーにatomのリンクを登録すると通知が行くよ🐌

https://herohoro.com/atom

やってみてね(*´ω`*)(*´ω`*)

Twitter Timeline


フォロー大歓迎\(^o^)/