logologo
スタート
マニュアル
開発
プラグイン
API
English
简体中文
日本語
한국어
Deutsch
Français
Español
Português
Русский
Italiano
Türkçe
Українська
Tiếng Việt
Bahasa Indonesia
ไทย
Polski
Nederlands
Čeština
العربية
עברית
हिन्दी
Svenska
スタート
マニュアル
開発
プラグイン
API
logologo

クイックスタート

プラグイン開発概要
最初のプラグインを作成
プロジェクトディレクトリ構造

サーバーサイド開発

概要
プラグイン
コレクション
データベース操作
データソース管理
リソース管理
ACL権限制御
ミドルウェア
キャッシュ
イベント
リクエストコンテキスト
マイグレーション
ロガー
I18n 国際化
コマンド
定時タスク管理
テスト

クライアントサイド開発

概要
プラグイン
コンテキスト
ルーター
ACL権限制御
データソース管理
リソース
リクエスト
スタイルとテーマ
ロガー
I18n 国際化
テスト

その他

プラグインアップグレードガイド
言語一覧
依存関係の管理
ビルド
Previous PageACL権限制御
Next Pageキャッシュ
TIP

このドキュメントはAIによって翻訳されました。不正確な情報については、英語版をご参照ください

#ミドルウェア

NocoBase Serverのミドルウェアは、本質的にKoaのミドルウェアです。Koaと同様にctxオブジェクトを操作して、リクエストとレスポンスを処理できます。しかし、NocoBaseは異なるビジネス層のロジックを管理する必要があるため、すべてのミドルウェアをまとめてしまうと、保守や管理が非常に困難になります。

このため、NocoBaseではミドルウェアを4つの階層に分けています。

  1. データソースレベルのミドルウェア:app.dataSourceManager.use()
    特定のデータソースへのリクエストにのみ作用します。そのデータソースのデータベース接続、フィールド検証、トランザクション処理などのロジックによく使われます。

  2. リソースレベルのミドルウェア:app.resourceManager.use()
    定義済みのリソース(Resource)にのみ適用され、データ権限やフォーマットなどのリソースレベルのロジック処理に適しています。

  3. 権限レベルのミドルウェア:app.acl.use()
    権限チェックの前に実行され、ユーザーの権限やロールの検証に使われます。

  4. アプリケーションレベルのミドルウェア:app.use()
    すべてのリクエストで実行され、ログ記録、一般的なエラー処理、レスポンス処理などに適しています。

#ミドルウェアの登録

ミドルウェアは通常、プラグインのloadメソッド内で登録されます。例えば次のようになります。

export class MyPlugin extends Plugin {
  load() {
    // アプリケーションレベルのミドルウェア
    this.app.use(async (ctx, next) => {
      console.log('App middleware');
      await next();
    });

    // データソースレベルのミドルウェア
    this.app.dataSourceManager.use(async (ctx, next) => {
      console.log('DataSource middleware');
      await next();
    });

    // 権限レベルのミドルウェア
    this.app.acl.use(async (ctx, next) => {
      console.log('ACL middleware');
      await next();
    });

    // リソースレベルのミドルウェア
    this.app.resourceManager.use(async (ctx, next) => {
      console.log('Resource middleware');
      await next();
    });

  }
}

#実行順序

ミドルウェアの実行順序は次のとおりです。

  1. まず、acl.use()で追加された権限ミドルウェアが実行されます。
  2. 次に、resourceManager.use()で追加されたリソースミドルウェアが実行されます。
  3. その後、dataSourceManager.use()で追加されたデータソースミドルウェアが実行されます。
  4. 最後に、app.use()で追加されたアプリケーションミドルウェアが実行されます。

#before / after / tag 挿入の仕組み

ミドルウェアの実行順序をより柔軟に制御するために、NocoBaseではbefore、after、tagの各パラメーターを提供しています。

  • tag:ミドルウェアにタグを付け、後続のミドルウェアから参照できるようにします。
  • before:指定されたタグを持つミドルウェアの前に挿入します。
  • after:指定されたタグを持つミドルウェアの後に挿入します。

例:

// 通常のミドルウェア
app.use(m1, { tag: 'restApi' });
app.resourcer.use(m2, { tag: 'parseToken' });
app.resourcer.use(m3, { tag: 'checkRole' });

// m4はm1の前に配置されます
app.use(m4, { before: 'restApi' });

// m5はm2とm3の間に挿入されます
app.resourcer.use(m5, { after: 'parseToken', before: 'checkRole' });
TIP

位置が指定されていない場合、新しく追加されたミドルウェアのデフォルトの実行順序は次のとおりです。
acl.use() -> resourceManager.use() -> dataSourceManager.use() -> app.use()

#オニオンモデルの例

ミドルウェアの実行順序は、Koaのオニオンモデルに従います。これは、ミドルウェアスタックに最初に入り、最後に終了するというものです。

app.use(async (ctx, next) => {
  ctx.body = ctx.body || [];
  ctx.body.push(1);
  await next();
  ctx.body.push(2);
});

app.resourcer.use(async (ctx, next) => {
  ctx.body = ctx.body || [];
  ctx.body.push(3);
  await next();
  ctx.body.push(4);
});

app.acl.use(async (ctx, next) => {
  ctx.body = ctx.body || [];
  ctx.body.push(5);
  await next();
  ctx.body.push(6);
});

app.resourcer.define({
  name: 'test',
  actions: {
    async list(ctx, next) {
      ctx.body = ctx.body || [];
      ctx.body.push(7);
      await next();
      ctx.body.push(8);
    },
  },
});

異なるインターフェースへのアクセスにおける出力順序の例:

  • 通常のHTTPリクエスト:/api/hello
    出力:[1,2] (リソースが定義されていないため、resourceManagerとaclミドルウェアは実行されません)

  • リソースリクエスト:/api/test:list
    出力:[5,3,7,1,2,8,4,6]
    ミドルウェアは階層順序とオニオンモデルに従って実行されます。

#まとめ

  • NocoBaseのミドルウェアはKoaミドルウェアの拡張です。
  • 4つの階層:アプリケーション -> データソース -> リソース -> 権限
  • before / after / tag を使用して、実行順序を柔軟に制御できます。
  • Koaのオニオンモデルに従い、ミドルウェアの組み合わせとネストを保証します。
  • データソースレベルのミドルウェアは指定されたデータソースリクエストにのみ作用し、リソースレベルのミドルウェアは定義済みのリソースリクエストにのみ作用します。