JSON データを POST 送信する

Recipe ID: net-002

クライアントからサーバーへデータを送信する(POSTリクエスト)方法を解説します。
Tauri の plugin-http を使用することで、Web 標準の fetch と同様の書き心地で、Rust バックエンドを経由した安全で柔軟なリクエスト送信が可能です。

前提条件

この機能を使用するには、@tauri-apps/plugin-http プラグインが必要です。

1. プラグインのインストール

npm run tauri add http

src-tauri/capabilities/default.jsonhttp:default 権限を追加します。
Tauri v2 ではセキュリティの観点から allow: [{ "url": "*" }] のような無制限なワイルドカード指定は許可されていない場合があるため、使用する API のドメインを明示的に指定する必要があります。

以下の例では、コード例で使用する api.myapp.comapi.example.com を許可しています。

{
  "permissions": [
    {
      "identifier": "http:default",
      "allow": [
        { "url": "https://api.myapp.com/*" },
        { "url": "https://api.example.com/*" }
      ],
      "deny": []
    }
  ]
}
注意: 開発中は便利だからと広範囲な許可をしたくなりますが、本番ビルドでは実際に使用するドメインのみを許可することが強く推奨されます。

使用方法

fetch 関数の第2引数(オプションオブジェクト)で method: 'POST' を指定し、body に送信したい JSON 文字列を設定します。
また、サーバーが JSON を正しく認識できるように、Content-Type ヘッダーを明示的に設定することが重要です。

import { fetch } from '@tauri-apps/plugin-http';

const response = await fetch('https://api.example.com/endpoint', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
    },
    body: JSON.stringify({ key: 'value' }),
});

コード例

例1: ユーザー登録フォームの送信

ユーザー入力データを受け取り、API サーバーへ登録する例です。

import { fetch } from '@tauri-apps/plugin-http';

interface UserData {
    username: string;
    email: string;
    [key: string]: any; // その他のプロパティ
}

async function registerUser(userData: UserData): Promise<any> {
    try {
        const response = await fetch('https://api.myapp.com/v1/users', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                // 必要に応じて認証ヘッダーなどを追加
                // 'Authorization': 'Bearer ...' 
            },
            body: JSON.stringify(userData)
        });

        if (response.ok) {
            const result = await response.json();
            console.log('Registration success:', result);
            return result;
        } else {
            console.error('Registration failed:', response.status);
            // サーバーからのエラー詳細を取得
            const errorBody = await response.text();
            console.error(errorBody);
        }
    } catch (err) {
        console.error('Network error:', err);
    }
}

例2: タイムアウト設定

Tauri の http プラグインでは、リクエストのタイムアウトを設定することも可能です(Fetch API 標準にはないオプションですが、Rust 側の実装に依存します。標準的な AbortController を使うのが最も汎用的です)。

import { fetch } from '@tauri-apps/plugin-http';

async function postWithTimeout(url: string, data: any): Promise<any> {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), 5000); // 5秒でタイムアウト

    try {
        const response = await fetch(url, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(data),
            signal: controller.signal
        });
        
        clearTimeout(timeoutId);
        return await response.json();
    } catch (err: any) {
        if (err.name === 'AbortError') {
             console.error('Request timed out');
        } else {
             console.error('Fetch failed', err);
        }
    }
}

例3: PUT や PATCH メソッド

POST と同様に、メソッド名を変更するだけで PUT(更新)や PATCH(部分更新)リクエストも送信できます。

await fetch(`https://api.example.com/items/${id}`, {
    method: 'PUT', // または 'PATCH'
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ status: 'updated' })
});

注意点

* CORS: Rust 経由のリクエストなのでブラウザの CORS 制約は受けませんが、サーバー側が特定の User-Agent やヘッダーを要求する場合があります。必要に応じてヘッダーを調整してください。
* Body の型: fetchbody には文字列 (JSON.stringify したもの)、FormDataBlobArrayBuffer などが渡せますが、オブジェクトをそのまま渡すことはできません。必ず文字列化してください。