10分以内でNode.jsのプロキシサーバを構築する方法
読む所要時間: 11 分
皆さんは「プロキシ」という言葉を一度は聞いたことがあるのではないでしょうか。実はプロキシは非常に身近で便利な技術です。
プロキシとは、複数のサービスの間に位置し、リクエストとレスポンスを双方向に処理・修正する中間的なアプリケーションのことです。
現実世界に例えると、スペインから来た人を目の前にして、あなたがスペイン語を話せないとします。困っていたところ、あなたは友人の田中さんがスペイン語と日本語を話せ、通訳ができることを思い出します。
通訳が以下のとおり行われます。
- あなたが田中さんに日本語で話しかけます。
- 田中さんは頭の中でそれをスペイン語に翻訳して、新しい友人にスペイン語で話します。
- 新しい友人は、スペイン語で田中さんに返事をします。
- 田中さんは頭の中でそれを日本語に翻訳して、あなたに日本語で返事をします。
このシナリオでは、田中さんはあなたと新しい友人との間の代理人(プロキシ)としての役割を持っています。お互いに直接話すことはできませんが、田中さんのおかげで会話のキャッチボール(リクエストとレスポンスの送受信)ができます。
プロキシとは何かを理解できたので、次にプロキシの使用例についてご紹介します。おすすめの使用例を列挙します。
- 認可: サービスへのアクセスを認可されたリクエストのみを転送する。
- ロードバランシング: 複数のインスタンスにリクエストを均等に分配する。
- ロギング: バックエンドAPIサービスへのリクエストをログ出力する。
プロキシとは何か、なぜプロキシが有用なのかを理解できたところで、Node.jsを使って簡単なプロキシを作ってみましょう。
必要なもの
このチュートリアルを進めるには、以下の項目が必要です。
シンプルなNode.jsプロキシを構築する
簡単な手順で、Node.jsで複数の異なるサーバーおよびエンドポイントにリクエストを転送できるシンプルなプロキシを作成しましょう。
プログラムの初期化
まず、新しいNode.jsプログラムを作成します。ターミナルを開き、以下のコマンドを実行してください。
これにより、プログラムの基本設定を含むpackage.jsonファイルが生成されます。コマンドを実行すると設定に関する質問(名前、バージョンなど)が表示されます。質問に対してエンターキーをクリックすると、デフォルトの値が設定されます。たとえば、アプリケーションのデフォルトエントリーポイントはindex.jsです。
依存パッケージをインストールする
プロキシを動作させるには以下のパッケージが必要です。
express
: Node.jsで使うウェブサーバーフレームワーク。http-proxy-middleware
: シンプルなプロキシフレームワーク。- (任意)
morgan
: HTTPリクエストログ出力用のミドルウェア。
これらのパッケージをインストールします。以下のコマンドを実行してください。
スタートコマンドを追加する
生成されたpackage.jsonにスタートコマンドを追加します。scripts
パラメータを追加し、その値に、{"start": "node index.js"}
を指定してください。
スタートコマンドを追加した後のpackage.jsonは以下のとおりです。
プログラムのルートディレクトリに、空のindex.jsファイルを作成してください。
これで、プログラムを実行する準備が整いました。以下のコマンドを実行してください。
プログラムが実行されます。現時点ではindex.jsは空なので、ターミナルには何も出力されません。
設定が完了したので、次にプロキシを作成しましょう。
プロキシを作成する
まず、依存パッケージをインポートします。index.jsファイルをテキストエディタで開き、以下のコードをペーストしてください。
次に、Expressサーバーを作成し、後ほど使用する変数を定義します。依存パッケージのブロックの下に、以下のコードをペーストしてください。
受信したリクエストをログに記録するmorganミドルウェアを追加します。変数のブロックの下に、以下のコードをペーストしてください。
テスト用の/infoエンドポイントを追加します。このエンドポイントはリクエストを転送せず、テキストレスポンスのみを返します。
morganミドルウェアのブロックの下に、以下のコードをペーストしてください。
Authorization Headerがない場合に、403(Forbidden)エラーを送信する認可用のミドルウェアも追加します。
/infoエンドポイントのブロックの下に、以下のコードをペーストしてください。
プロキシのエンドポイントを定義します。/json_placeholderで始まるリクエストを、ダミーデータを提供するAPI、JSON Placeholder APIにプロキシします。また、APIに転送される際に/json_placeholderが省略されるように、pathRewrite
を定義します。
app.use
のブロックの下に、以下のコードをペーストしてください。
これにより、/json_placeholderを含むパスにリクエストが送られると、リクエスト先のURLから/json_placeholder
が省略されます。例えば、localhost:3000/json_placeholder/posts/1にリクエストを送ると、リクエスト先のURLはhttps://jsonplaceholder.typicode.com/posts/1に上書きされます。
最後に、設定したサーバーを呼び出します。index.jsファイルの最終行に、以下のコードをペーストしてください。
プロキシを実行する
プロキシを実行します。ターミナルでプログラムのルートディレクトリから以下のコマンドを実行してください。
以下のような内容がターミナルで出力されます。
これでプロキシが実行されました。
/infoにGETリクエストを送信します。
2つ目のターミナルを開いて、以下のコマンドを実行してください。
問題なくサーバーが動作すると、プロキシからのレスポンスが出力されます。
これまでの手順で、エンドポイントに対するGETリクエストからのレスポンスを検証しました。次に、実際にプロキシの動作検証を行います。
2つ目のターミナルで、以下のコマンドを実行してください。
すると、以下のForbiddenエラーが出力されます。
これは、認可ミドルウェアがすべてのリクエストにAuthorization Headerが含まれていることを必要とするためです。
そこで、リクエストに変更を加えます。
2つ目のターミナルで、以下のコマンドを実行してください。
すると、以下のオブジェクトが出力されます。
プロキシを通したリクエストが成功しました。
さらに、POSTリクエストでも試してみましょう。
2つ目のターミナルで、以下のコマンドを実行してください。
すると、以下のオブジェクトが出力されます。
これでプロキシサーバーの開発、動作検証ができました!
このプログラムの全コードは、Githubリポジトリを参照してください。
次のステップ
本稿でご紹介したプロキシは、非常にシンプルです。ユースケースに応じて、以下のように拡張できます。
- より洗練された認可ミドルウェアを使用して、サービスへのアクセスを承認されたリクエストのみを転送する。
- APIサービスの多数のデプロイメントにリクエストを均等に分散させる。
- バックエンドAPIサービスへのすべてのリクエストを記録する。
- プロキシサーバー、Twilio、C#でアイデンティティを保護する(英語記事)。
- ReactアプリにNode.jsサーバープロキシを設定する。
まとめ
プロキシサーバーは複雑なイメージを持たれがちですが、実は非常に簡単に構築できます。このチュートリアルでプロキシの基礎が学べたので、次はさらに複雑なプロキシサーバーを作ってみてはいかがでしょうか。ぜひプロジェクトをシェアしてください!
Nikolay NikolovはTwilioのSuper SIMチームのソフトウェアエンジニアインターンをしています。ウェブや機械学習の概念を探求し、技術愛好家と共有することが好きです。Nikolayへのご連絡は、LinkedInまたはウェブサイトからお願いします。