カスタムエンドポイントで既存のAPIを拡張する


12

複数のお客様向けのAPIを作成しています。のようなコアエンドポイント/usersはすべてのお客様が使用しますが、一部のエンドポイントは個別のカスタマイズに依存しています。したがって、ユーザーAが特別なエンドポイントを必要/groupsとしており、他の顧客がその機能を持たない可能性があります。補足として、これらの追加機能のために、各顧客は自分のデータベーススキーマも使用します。

私は個人的にNestJ(内部ではExpress)を使用しています。したがって、app.module現在すべてのコアモジュールが登録されています(独自のエンドポイントなどで)

import { Module } from '@nestjs/common';

import { UsersModule } from './users/users.module'; // core module

@Module({
  imports: [UsersModule]
})
export class AppModule {}

この問題はNestJとは関係がないと思うので、理論的にはどのように対処しますか?

基本的に、基本的なシステムを提供できるインフラストラクチャが必要です。各拡張は一意であり、複数の/users実装が可能であるため、コアエンドポイントはもうありません。新しい機能を開発するときは、コアアプリケーションに触れないでください。拡張機能はそれ自体を統合するか、起動時に統合する必要があります。コアシステムはエンドポイントなしで出荷されますが、これらの外部ファイルから拡張されます。

いくつかのアイデアが思い浮かびます


最初のアプローチ:

各拡張機能は新しいリポジトリを表します。すべての拡張プロジェクトを保持するカスタム外部フォルダーへのパスを定義します。このカスタムディレクトリにはgroupsgroups.module

import { Module } from '@nestjs/common';

import { GroupsController } from './groups.controller';

@Module({
  controllers: [GroupsController],
})
export class GroupsModule {}

私のAPIはそのディレクトリをループして、各モジュールファイルをインポートしようとします。

  • 長所:

    1. カスタムコードはコアリポジトリから遠ざけられます
  • 短所:

    1. NestJsはTypescriptを使用するため、最初にコードをコンパイルする必要があります。APIビルドとカスタムアプリからのビルドをどのように管理しますか?(プラグアンドプレイシステム)

    2. カスタム拡張機能には、いくつかのtypescriptファイルが含まれているだけなので、非常に緩いです。APIのnode_modulesディレクトリにアクセスできないため、外部パッケージの依存関係を解決できないため、エディターにエラーが表示されます。

    3. 一部の拡張機能は、別の拡張機能からデータをフェッチする場合があります。おそらく、グループサービスがユーザーサービスにアクセスする必要があります。物事はここでトリッキーになるかもしれません。


2番目のアプローチ: 各拡張機能をAPIのsrcフォルダーのサブフォルダー内に保持します。ただし、このサブフォルダーを.gitignoreファイルに追加します。これで、拡張機能をAPI内に保持できます。

  • 長所:

    1. エディターは依存関係を解決できます

    2. コードをデプロイする前に、ビルドコマンドを実行すると、単一のディストリビューションが作成されます

    3. 他のサービスに簡単にアクセスできます(/groupsIDでユーザーを検索する必要があります)

  • 短所:

    1. 開発時には、そのサブフォルダ内にリポジトリファイルをコピーする必要があります。何かを変更した後、これらのファイルをコピーして、リポジトリファイルを更新したファイルで上書きする必要があります。

3番目のアプローチ:

外部カスタムフォルダー内では、すべての拡張機能が完全に独立したスタンドアロンAPIです。あなたのメインAPIは認証を提供するだけで、着信リクエストをターゲットAPIにリダイレクトするプロキシとして機能することができます。

  • 長所:

    1. 新しい拡張機能を簡単に開発およびテストできます
  • 短所:

    1. 展開は注意が必要です。メインAPIとn個の拡張APIが独自のプロセスを開始し、ポートをリッスンします。

    2. プロキシシステムは注意が必要です。クライアントが/usersプロキシにリクエストする場合、プロキシはそのエンドポイントをリッスンする拡張機能APIを認識する必要があります。そのAPIを呼び出し、その応答をクライアントに転送します。

    3. 拡張APIを保護するには(認証はメインAPIによって処理されます)、プロキシはこれらのAPIとシークレットを共有する必要があります。そのため、拡張APIは、一致するシークレットがプロキシから提供された場合にのみ、着信リクエストを渡します。


4番目のアプローチ:

マイクロサービスが役立つかもしれません。私はここからガイドを取りましたhttps://docs.nestjs.com/microservices/basics

ユーザー管理、グループ管理などのためのマイクロサービスを用意し、それらのマイクロサービスを呼び出す小さなapi /ゲートウェイ/プロキシを作成することで、これらのサービスを利用できます。

  • 長所:

    1. 新しい拡張機能を簡単に開発およびテストできます

    2. 分離された懸念

  • 短所:

    1. 展開は注意が必要です。メインAPIとn個のマイクロサービスが独自のプロセスを開始し、ポートをリッスンします。

    2. カスタマイズ可能にしたい場合は、顧客ごとに新しいゲートウェイAPIを作成する必要があるようです。したがって、アプリケーションを拡張する代わりに、毎回カスタマイズされたコンシューミングAPIを作成する必要があります。それは問題を解決しません。

    3. 拡張APIを保護するには(認証はメインAPIによって処理されます)、プロキシはこれらのAPIとシークレットを共有する必要があります。そのため、拡張APIは、一致するシークレットがプロキシから提供された場合にのみ、着信リクエストを渡します。



リンクをありがとう。しかし、コード内にカスタム拡張機能を含める必要はないと思います。マイクロサービスが問題を解決するかどうかを確認しますdocs.nestjs.com/microservices/basics
hrp8sfH4xQ4

あなたの問題は休息というより承認に関係していると思います。
adnanmuttaleb

@ adnanmuttalebはなぜ=を説明してもらえますか?
hrp8sfH4xQ4

回答:


6

これにはいくつかのアプローチがあります。あなたがする必要があるのは、どのワークフローがあなたのチーム、組織、そしてクライアントに最も適しているかを理解することです。

これが私次第である場合、モジュールごとに1つのリポジトリを使用することを検討し、NPMのようなパッケージマネージャーを使用して、プライベートスコープまたは組織スコープのパッケージで構成を処理します。次に、新しいビルドでパッケージリポジトリにプッシュするビルドリリースパイプラインを設定します。

この方法で必要なのは、メインファイルと、カスタムインストールごとのパッケージマニフェストファイルだけです。独自に新しいバージョンを開発してデプロイでき、クライアント側で必要なときに新しいバージョンをロードできます。

さらにスムーズにするために、構成ファイルを使用してモジュールをルートにマップし、ほとんどのブートストラップを実行する汎用ルートジェネレータースクリプトを記述できます。

パッケージは何でもかまいませんので、パッケージ内の相互依存関係はそれほど手間をかけずに機能します。変更とバージョン管理に関しては、規律が必要です。

プライベートパッケージの詳細については、こちらをご覧ください: プライベートパッケージNPM

現在、プライベートNPMレジストリはコストがかかりますが、それが問題である場合は、他にもいくつかのオプションがあります。無料と有料の両方の代替案について、この記事を確認してください。

プライベートnpmレジストリを作成する方法

ここで、独自のマネージャーをロールバックする場合は、シンプルなサービスロケーターを作成します。これは、リポジトリからコードをプルしてロードし、何らかの方法でメソッドを取得して、そのインスタンス。

私はそのようなシステムの簡単なリファレンス実装を書きました:

フレームワーク:移動サービスロケーター

パリンドロームをチェックするプラグインの例locomotionプラグインの例

フレームワークを使用してプラグインを検索するアプリケーション:Locomotionアプリの例

これをnpmから取得することで、次のスキーマでファイルnpm install -s locomotionを指定する必要があるため、これを試すことがplugins.jsonできます。

{
    "path": "relative path where plugins should be stored",
    "plugins": [
        { 
           "module":"name of service", 
           "dir":"location within plugin folder",
           "source":"link to git repository"
        }
    ]
}

例:

{
    "path": "./plugins",
    "plugins": [
        {
            "module": "palindrome",
            "dir": "locomotion-plugin-example",
            "source": "https://github.com/drcircuit/locomotion-plugin-example.git"
        }
    ]
}

次のようにロードします。const loco = require( "locomotion");

次に、サービスロケータオブジェクトを解決するプロミスを返します。これには、サービスを保持するためのロケータメソッドがあります。

loco.then((svc) => {
    let pal = svc.locate("palindrome"); //get the palindrome service
    if (pal) {
        console.log("Is: no X in Nixon! a palindrome? ", (pal.isPalindrome("no X in Nixon!")) ? "Yes" : "no"); // test if it works :)
    }
}).catch((err) => {
    console.error(err);
});

これは単なるリファレンス実装であり、深刻なアプリケーションに対して十分に堅牢ではないことに注意してください。ただし、パターンはまだ有効であり、この種のフレームワークを作成する要点を示しています。

これは、プラグイン構成、初期化、エラーチェックのサポートで拡張する必要があります。依存関係の注入のサポートなどを追加することもできます。


ありがとう。2つの問題が発生します。npmに依存しているようで、自己ホスト型レジストリをセットアップする必要があります。2つ目は、プライベートnpmが無料ではなくなったことです。基本的な技術的な解決策を見つけたいと思っていました。しかし、アイデアのために+1 :)
hrp8sfH4xQ4

1
この種のシステムの基本的なソリューションのリファレンス実装を追加しました。
Espen、

3

私は外部パッケージオプションに行きます。

packagesフォルダーを持つようにアプリを構成できます。私はそのフォルダーに外部パッケージのUMDコンパイル済みビルドを用意し、コンパイル済みのtypescriptがパッケージに問題を起こさないようにします。すべてのパッケージにはindex.js、各パッケージのルートフォルダにファイルが必要です。

また、アプリは、パッケージフォルダーを使用してループを実行しfsrequireすべてのパッケージindex.jsをアプリに含めることができます。

次に、依存関係のインストールは、注意する必要があるものです。各パッケージの設定ファイルもそれを解決できると思います。npmメインアプリにカスタムスクリプトを作成して、アプリケーションを起動する前にすべてのパッケージの依存関係をインストールできます。

このように、パッケージをパッケージフォルダーにコピーして貼り付け、アプリを再起動することで、アプリに新しいパッケージを追加できます。コンパイルされたtypescriptファイルは変更されず、独自のパッケージにプライベートnpmを使用する必要はありません。


お返事をありがとうございます。これは、@ Espenがすでに投稿したソリューションのように聞こえると思います、いいえ?
hrp8sfH4xQ4

@ hrp8sfH4xQ4はい。使いたくないというコメントを読んで追加しましたnpm。上記は、プライベートnpmアカウントを回避するために実行できるソリューションです。さらに、組織外の誰かが作成したパッケージを追加する必要はないと私は思います。正しい?
Kalesh Kaladharan

ところで。しかし、それをサポートすることも素晴らしいでしょう...どういうわけか...
hrp8sfH4xQ4

サードパーティのパッケージを追加するオプションが必要な場合npmは、それまたは他のパッケージマネージャーを使用する方法です。そのような場合、私の解決策では不十分です。
Kalesh Kaladharan

よろしければ、できるだけ多くのアプローチを収集するまでお待ちください
hrp8sfH4xQ4
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.