@rescript-tauri/plugin-http

Tauri 2.x HTTP fetch プラグイン の ReScript バインディングです。Web Fetch API のラッパーとして Rust 側を経由することで webview の CORS を回避し、型付きの proxy / TLS 設定も提供します。@tauri-apps/plugin-http v2.5.9 の stable な公開 API を 100% カバーします。

注釈

本パッケージは main で機能完備済みです。初回 npm 公開は他のパッケージと合わせて予定されています。それまでは、ソースリポジトリ経由かワークスペースリンクで利用してください。

インストール

pnpm add @rescript-tauri/plugin-http @tauri-apps/plugin-http

@rescript-tauri/plugin-http@rescript-tauri/core@tauri-apps/plugin-http の両方を peerDependencies として宣言しているため、上流側の各バージョンを利用者側で制御できます。

rescript.jsondependencies にパッケージを追加します:

{
  "dependencies": [
    "@rescript-tauri/core",
    "@rescript-tauri/plugin-http"
  ]
}

Rust 側では、プラグイン crate を追加して builder に登録します:

# src-tauri/Cargo.toml
[dependencies]
tauri-plugin-http = "2"
// src-tauri/src/main.rs
fn main() {
    tauri::Builder::default()
        .plugin(tauri_plugin_http::init())
        .run(tauri::generate_context!())
        .expect("error while running app");
}

許可されるオリジンは tauri.conf.json では設定しません。Tauri 2.x では次節で説明する capability 層でルーティングされます。

Capabilities

Tauri 2.x では、すべてのプラグイン権限を明示的に付与する必要があります。http:default (fetch API を許可) と、アプリがアクセスできる URL を限定する scoped な allow リストを組み合わせます:

{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "default",
  "windows": ["main"],
  "permissions": [
    "core:default",
    {
      "identifier": "http:default",
      "allow": [{ "url": "https://api.example.com/*" }]
    }
  ]
}

scoped な allow 配列はホワイトリストです。マッチしない URL は CORS とは独立に Rust 境界で拒否されます。** は開発時にのみ使用し、本番の capability ではアプリが通信するすべてのホストを列挙してください。

最小例

open RescriptTauriPluginHttp

let getUsers = async () => {
  let response: 'response =
    await PluginHttp.fetch("https://api.example.com/users")
  // The return value is the DOM Response. Use Obj.magic (or an
  // inline object type) to access .json() / .status / etc.
  let r = (Obj.magic(response): {"json": unit => promise<'json>, "status": int})
  if r["status"] === 200 {
    let body = await r["json"]()
    Console.log(body)
  }
}

Tauri 固有のオプション (proxy、独自のタイムアウト) を伴う POST もほぼ同じ書き方です。~init を JS オブジェクトリテラルとして渡します:

let postWithProxy = async () => {
  let _: 'response = await PluginHttp.fetch(
    "https://api.example.com/events",
    ~init={
      "method": "POST",
      "headers": {"content-type": "application/json"},
      "body": Js.Json.stringify(Js.Json.object_(Js.Dict.empty())),
      "proxy": {"all": "http://corp-proxy:8080"},
      "connectTimeout": 5000,
    },
  )
}

公開 API

PluginHttp は単一の fetch 関数と、Tauri 固有のオプションをカバーする 5 つの record 型を公開します:

シンボル

用途

fetch(input, ~init=?)

Rust に裏付けされた polymorphic な Web Fetch ラッパー (webview の CORS を回避)。inputstring / URL.t / Request を、initRequestInit & ClientOptions を受け取ります

proxy<'proxyValue>

{all?, http?, https?}'proxyValue はスロットごとに string (URL) または proxyConfig のいずれか

proxyConfig

{url, basicAuth?, noProxy?}

basicAuth

{username, password}Proxy-Authorization ヘッダーとして転送されます

clientOptions<'proxyValue>

{maxRedirections?, connectTimeout?, proxy?, danger?}

dangerousSettings

{acceptInvalidCerts?, acceptInvalidHostnames?} (デフォルトで無効)

fetch のシグネチャ

let fetch: ('input, ~init: 'init=?) => promise<'response>

'input'init'response の 3 つはすべて意図的に polymorphic にしています:

  • 'input — 通常は stringURL.t、または Request インスタンスを使います。ReScript は呼び出し側から型を推論するため、string リテラルを渡す場合は明示的な型注釈は不要です。

  • 'initRequestInit & ClientOptions の形状を持ちます。実際には、標準の RequestInit フィールド (methodheadersbodysignal など) と、後述する Tauri 固有の clientOptions フィールドの両方を含む JS オブジェクトリテラル ({"method": "POST", ...}) を渡します。

  • 'response — DOM の Response です。DOM 型はここではバインドしていません。実用的な 3 つのイディオムは Pitfalls 節を参照してください。

clientOptions のフィールド

フィールド

用途

maxRedirections

int (省略可)

追従する最大リダイレクト数。0 でリダイレクト追従を完全に無効化します。

connectTimeout

int (省略可)

接続タイムアウト (ミリ秒単位)。

proxy

proxy<'proxyValue> (省略可)

URL スキームごとの proxy 指定。

danger

dangerousSettings (省略可)

危険な TLS 設定 (デフォルトで無効)。

proxy / proxyConfig / basicAuth

proxy<'proxyValue> は各スロットがどのトラフィックをカバーするかを選択し、スロット間で共通の 'proxyValue 型 (プレーンな URL string または完全な proxyConfig record) でパラメータ化されます:

// URL-only form: pass strings for every slot
let init = {"proxy": {"all": "http://corp-proxy:8080"}}

// Full ProxyConfig with auth and bypass list
let init = {
  "proxy": {
    "https": {
      "url": "http://corp-proxy:8443",
      "basicAuth": {"username": "alice", "password": "s3cret"},
      "noProxy": "localhost,*.internal",
    },
  },
}

proxyConfig.noProxy は上流のカンマ区切りホストパターン構文 (localhost*.internal192.168.0.0/16 など) を受け付けます。

dangerousSettings

let init = {
  "danger": {
    "acceptInvalidCerts": true,
    "acceptInvalidHostnames": true,
  },
}

acceptInvalidCerts は SSL/TLS 証明書の検証をスキップし、acceptInvalidHostnames は証明書のホスト名チェックをスキップします。両方ともデフォルトは false です。開発ビルド時の自己署名証明書、内部ステージング、mTLS の実験用途以外では有効化しないでください。本番リリースコードではいずれも有効化してはいけません。

落とし穴

DOM の Web Fetch 型は意図的にバインドしていません

DOM の Request / Response / RequestInit 型は @rescript/core の限定的な Web Fetch 表面にあり、プラグインが公開する streaming / progress / clone API をカバーしていません。中途半端に型付けされたバインディングを提供するのではなく、fetch を polymorphic のまま残し、呼び出し側で戦略を選択します:

  1. 型注釈 — 操作するフィールドを捉える具体的な record / object 型を既に持っている場合:

    type apiResponse = {"ok": bool, "status": int}
    let r: apiResponse =
      Obj.magic(await PluginHttp.fetch("https://api.example.com"))
    
  2. Obj.magic + インラインの構造的型 — 必要なフィールドが少数の場合に有用な最小コストの方法:

    let r =
      (Obj.magic(
        await PluginHttp.fetch("https://api.example.com"),
      ): {"json": unit => promise<'a>})
    
  3. External バインディング — 繰り返しアクセスする場合は、実際に利用する表面を独自モジュールの @send / @get external ブロックで包んでください。

型付きの Web Fetch 表面は後続のサブステアリングに先送りされています (パッケージの CHANGELOG を参照)。

proxy<'proxyValue> は単一の型パラメータを取ります

proxy<'proxyValue>all / http / https スロット間で共通の型変数を1 つ持つため、~init の ReScript record 構文で record を組み立てる際に、あるスロットで string URL を、別のスロットで完全な proxyConfig record を混在させると型エラーになります。回避策は 2 つあります:

  • 型を統一する: URL しか必要ない場合でも、すべてのスロットを proxyConfig で包みます。

  • JS オブジェクトリテラルを使う: オブジェクトリテラルは型パラメータを強制しないため、{"http": "http://...", "https": {"url": "https://...", "basicAuth": …}} のような混在形状も 'init として受け付けられます。

dangerousSettings はデフォルトで無効

init から danger を省略すると、両方のチェックがデフォルトで有効のままです。プラグインの Tauri レベル capability 層からは再有効化できず、明示的な init.danger record でのみ無効化できます。これにより secure-by-default な動作が呼び出し側から見えるようになります。

互換性

コンポーネント

サポート範囲

上流 @tauri-apps/plugin-http

^2.0.0 (peer)

Rust tauri-plugin-http

2.x

@rescript-tauri/core

^0.1.0 (peer)

ReScript

>=12.0.0

@rescript/core

>=1.6.0

OS

Linux / macOS / Windows

関連項目