Open4

Rust , Headless CMS作成メモ Workers-rs

knaka Tech-Blogknaka Tech-Blog

概要

  • Rust , Headless CMS試作メモになります。
  • cloudflare Workers-rs で、実装
  • データは、 D1 database 保存
  • 管理画面は、 React フルスタック
  • APIは、ほぼ 100% Rust言語
  • 小規模アプリ等などの、バックエンドにしたい。
  • フロントは 生成AI, バックは Headless CMS使用で、時短できれば

[ 公開 2025/09/04 ]


環境

  • cloudflare Workers-rs
  • D1 database
  • rustc 1.88.0 , cargo 1.88.0
  • node 22

書いたコード

https://github.com/kuc-arc-f/headless-2025/tree/main/headless-2025

  • dev-start
npm run build
npm run dev

設定方法

  • headless-2025/wrangler.toml
  • db 接続設定
  • API_KEY認証の、KEYを決める
  • 管理画面ログイン: USER_NAME , PASSWORD
[vars]
USER_NAME = "user1@example.com"
PASSWORD = "1234"
API_KEY = "123"

https://github.com/kuc-arc-f/headless-2025/blob/main/headless-2025/wrangler.toml


API使い方


  • 例: List
  • node.js
  • your-key: API_KEY , wrangler.toml に設定した API_KEY
  • content: データ種類
const start = async function() {
  try{
    const response = await fetch("http://localhost:8787/api/data/list?content=todo", {
      method: 'GET',
      headers: {
        'Authorization': 'your-key',
      }
    });
    if (!response.ok) {
      const text = await response.text();
      console.log(text)
      throw new Error('Failed to item');
    }
    const json = await response.json();
    console.log(json)
  }catch(e){console.log(e)}
}
start();

  • Create

  • your-key: API_KEY , wrangler.toml に設定した API_KEY

  • content: データ種類

  • data: json データ


const start = async function() {
  try{
      const item = {
        content: "test1",
        data: JSON.stringify({
          "title": "tit-1",
          "body": "body-1",
        })
      }
      const response = await fetch("http://localhost:8787/api/data/create", {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'your-key',
      },
      body: JSON.stringify(item),
    });
    if (!response.ok) {
      const text = await response.text();
      console.log(text);
      throw new Error('Failed to create item');
    }
    return response.json();
  }catch(e){console.log(e)}
}
start();

knaka Tech-Blogknaka Tech-Blog

Rust Axum , Headless CMSの例

  • Axum使用、Headless CMS作成メモになります。
  • 今回は、サバーレスではなく。セルフホスト等でデプロイ想定です。

環境

  • Axum
  • SQLite database
  • rustc 1.88.0 , cargo 1.88.0
  • node 20
  • react

書いたコード

https://github.com/kuc-arc-f/headless-2025/tree/main/headless-2025-rs


  • dev-start
npm run build
npm run dev

設定方法

  • .env
  • API_KEY認証の、KEYを決める
  • 管理画面ログイン: USER_NAME , PASSWORD
API_KEY=123
USER_NAME = "user1@example.com"
PASSWORD = "1234"

  • table
CREATE TABLE IF NOT EXISTS hcm_data (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    content  TEXT NOT NULL,
    data  TEXT NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)

  • sqlite3で、 db作成
  • Dbname: cms.db
sqlite3 cms.db

API使い方


  • 例: List
  • node.js
  • your-key: API_KEY , .env に設定した API_KEY
  • content: データ種類
const start = async function() {
  try{
    const response = await fetch("http://localhost:3000/api/data/list?content=test1", {
      method: 'GET',
      headers: {
        'Authorization': 'your-key',
      }
    });
    if (!response.ok) {
      const text = await response.text();
      console.log(text)
      throw new Error('Failed to create item');
    }
    const json = await response.json();
    console.log(json)
  }catch(e){console.log(e)}
}
start();

  • Create

  • your-key: API_KEY , .env に設定した API_KEY

  • content: データ種類

  • data: json データ


const start = async function() {
  try{
      const item = {
        content: "test2",
        data: JSON.stringify({
          "title": "tit-22",
          "body": "body-22",
        })
      }
      const response = await fetch("http://localhost:3000/api/data/create", {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'your-key',
      },
      body: JSON.stringify(item),
    });
    if (!response.ok) {
      const text = await response.text();
      console.log(text);
      throw new Error('Failed to create item');
    }
    return response.json();
  }catch(e){console.log(e)}
}
start();


knaka Tech-Blogknaka Tech-Blog

PGLite WASM + Bun , Headless CMSの例

  • PGLite WASM、Headless CMS作成メモになります。
  • 今回は、サバーレスではなく。セルフホスト等でデプロイ想定です。

関連

  • 前のPGLite 記事 インストールなど

https://zenn.dev/knaka0209/scraps/b077514499e644


環境

  • PGLite WASM , popstgres 17.x
  • bun 1.2.20
  • react

書いたコード

https://github.com/kuc-arc-f/bun_41ex/tree/main/headless-2025-pg


  • db create
bun run db_init.ts

  • dev-start
npm run build
npm run dev

設定方法

  • .env
  • DATA_DIR: PGLite data folder
  • API_KEY認証の、KEYを決める
  • 管理画面ログイン: USER_NAME , PASSWORD
DATA_DIR="/path/cmsdata"
API_KEY=1234
USER_NAME = "user1@example.com"
PASSWORD = "123"

API使い方


  • 例: List
  • node.js
  • your-key: API_KEY , .env に設定した API_KEY
  • content: データ種類
const start = async function() {
  try{
    const response = await fetch("http://localhost:3000/api/data/list?content=test1", {
      method: 'GET',
      headers: {
        'Authorization': 'your-key',
      }
    });
    if (!response.ok) {
      const text = await response.text();
      console.log(text)
      throw new Error('Failed to item');
    }
    const json = await response.json();
    console.log(json)
  }catch(e){console.log(e)}
}
start();

  • Create

  • your-key: API_KEY , .env に設定した API_KEY

  • content: データ種類

  • data: json データ


const start = async function() {
  try{
      const item = {
        content: "test2",
        data: JSON.stringify({
          "title": "tit-22",
          "body": "body-22",
        })
      }
      const response = await fetch("http://localhost:3000/api/data/create", {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'your-key',
      },
      body: JSON.stringify(item),
    });
    if (!response.ok) {
      const text = await response.text();
      console.log(text);
      throw new Error('Failed to create item');
    }
    return response.json();
  }catch(e){console.log(e)}
}
start();


knaka Tech-Blogknaka Tech-Blog

Headless CMS , 接続アプリの例

  • Headless CMS API使用して、連携アプリ作成
  • bun + Reactで作成。

環境

  • bun 1.2.20
  • React

書いたコード

https://github.com/kuc-arc-f/bun_41ex/tree/main/headless-app-1


  • .env
  • EXTERNAL_API_URL: 接続API URRL
  • API_KEY: Headless CMS に設定した API_KEY
EXTERNAL_API_URL="http://localhost:8787"
API_KEY=123

  • dev-start
npm run build
npm run dev

  • 一覧
  • headless-app-1/src/client/Home.tsx

https://github.com/kuc-arc-f/bun_41ex/blob/main/headless-app-1/src/client/Home.tsx

  • 起動処理、リストデータ取得
  const fetchItems = async () => {
    try {
      setLoading(true);
      const data = await itemsApi.getAll(CONTENT);
      console.log(data);
      setItems(data);
    } catch (err) {
      setError('アイテムの取得に失敗しました');
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    fetchItems();
  }, []);

  • API連携
  • headless-app-1/src/routes/todos.ts

https://github.com/kuc-arc-f/bun_41ex/blob/main/headless-app-1/src/routes/todos.ts

  • 外部API連携、レスポンスをフロント側に返す。
router.post('/list', async function(req: any, res: any) {
  try {
    const body = req.body;
    console.log(body)
    const url = process.env.EXTERNAL_API_URL;	
    const apikey = process.env.API_KEY;	
    const path = "/api/data/list?content=" + CONTENT 
    console.log("url=", url + path)
    const response = await fetch(url + path, {
      method: 'GET',
      headers: {
        'Authorization': apikey,
      }
    });    
    if(response.ok === false){
      console.error("Error, res.ok = NG");
      throw new Error("Error, res.ok = NG");
    }
    const json = await response.json();
    res.send({ret: 200, data: json.data});
  } catch (error) {
    console.error(error);
    res.sendStatus(500);
  }
});