演習 - Azure Functions アプリの関数を作成する

完了

このユニットでは、Node.js Express アプリの GETPOSTPUTDELETE エンドポイント向けに Azure Functions アプリで関数を作成して構成します。

GET 関数にデータ アクセスを追加する

前のユニットで Azure Functions アプリを作成したときに、最初の API エンドポイントを作成しました。 この関数は、/vacations で HTTP GET が要求されたときに実行されます。 データ サービスを呼び出して休暇を取得するには、定型コードを更新する必要があります。

  1. functions/src/functions/getVacations.ts ファイルを開きます。

  2. 両方のファイルを並べて表示できるように、別ウィンドウで server/routes/vacation.routes.ts ファイルを開きます。

  3. getVacations.ts に、vacationService のインポート ステートメントを追加します。

    import { vacationService } from '../services';
    
  4. getVacations.ts で、getVacations 関数を編集して vacationService を呼び出します。

     export async function getVacations(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> {
         context.log(`Http function processed request for url "${request.url}"`);
         return { jsonBody: vacationService.getVacations() }; // Data access logic within the return object
     };
    
  5. これで終わりにすることもできます。 休暇を取得するために関数に追加する "必要がある" コードはこれだけです。 しかし、エラーを処理し、状態コードを返すコードも提供するべきです。 次のコードを使用するように関数を更新します。

     export async function getVacations(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> {
       context.log(`Http function processed request for url "${request.url}"`);
    
       try {
         const vacations = vacationService.getVacations();  // Data access logic
    
         if (vacations) {
           return {
             status: 200,
             jsonBody: vacations
           };
         } else {
           return {
             status: 404,
             jsonBody: {
               error: 'No vacations found'
             }
           };
         }      
       } catch (error: unknown) {
         const err = error as Error;
         context.error(`Error listing vacations: ${err.message}`);
    
         return {
           status: 500,
           jsonBody: {
             error: 'Failed to list vacations'
           }
         };
       }
     };
    

Azure Functions ルートを整理する

v4 プログラミング モデルでは、複数の方法でルートを整理できます。 ルート定義をルート ハンドラーと合わせて 1 つのファイルに残すことができます。 これは、エンドポイントが 1 つのアプリケーションでは問題ありません。 Tailwind Traders の開発者であるあなたは、このアプリケーションが多数の API に成長し、整理が必要になることを知っています。

  1. その整理を開始するには、ルート定義をキャプチャする新しい ./functions/src/index.ts ファイルを作成します。

  2. @azure/functions パッケージから提供されるアプリの依存関係を追加します。

    import { app } from '@azure/functions';
    
  3. ./functions/getVacations ファイルから getVacations 関数の依存関係を追加します。

    import { getVacations } from `./functions/getVacations`;
    
  4. ルート定義を ./functions/getVacations から index.ts ファイルに移動します。 メソッド プロパティ配列を GET に更新します。

    app.http('getVacations', {
        methods: ['GET'],
        route: 'vacations',
        authLevel: 'anonymous',
        handler: getVacations
    });
    

関数とハンドラーの名前付け

getVacations という名前は、app.http への最初のパラメーターと、2 番目のパラメーターのプロパティの両方で使用されています。 これは混乱を招く可能性があり、名前の使用方法に応じて、組織またはチームで異なる名前付けルールが必要になる場合があります。

Screenshot of the http definition with the first parameter numbered as one, and the second parameter's handler property numbered as two.

  • 最初のパラメーター - 文字列としての名前:最初のパラメーターの値は、Azure portal に表示される関数の名前です。 これらの名前はポータルに英数字で一覧表示されるため、同様の関数を目的別にグループ化する名前付け規則を使用したい場合があります (vacationGet またはメソッドによっては getVacation など)。 snake_case、kebab-case、camelCase などの別の区切り方法を選択することもできます。
  • 2 番目のパラメーター - ハンドラー関数:2 番目のパラメーターの値は、コード内でインポートされて使用される関数ハンドラーの名前です。 この名前はわかりやすく、関数の目的に合うものである必要があります。 これは、既に存在しているコード ベース内の関数に対する名前付け規則に準拠させ、一般的なコード適合ツールで適用することができます。

残りの関数を作成する

Node.js Express アプリケーションには 4 つのエンドポイントがあり、GET エンドポイントの関数を作成したところです。 次に、残りのルート エンドポイントの関数を作成します。

Method HTTP トリガー名 ルート
POST postVacation vacations
PUT updateVacation vacations/{id}
DELETE deleteVacation vacations/{id}

GET および POST のルートは同一です。 PUT および DELETE ルートでは、パラメーターを使用してどの休暇を使用するかを特定します。

HTTP POST 関数を作成する

休暇の追加を処理する POST 関数を作成します。

  1. Visual Studio Code で、Ctrl + Shift +P キーを使用してコマンド パレットを開き、Azure Functions: Create Function と入力して Enter キーを押します。

  2. 種類として [HTTP トリガー] を、名前として postVacation を選択します。

  3. ファイルに vacationService のインポート ステートメントを追加します。

    import { vacationService } from '../services';
    
  4. 定型 postVacation 関数を、データ アクセスとエラー処理用の次のコードに置き換えます。

    export async function postVacation(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> {
        context.log(`HTTP function processed request for URL: "${request.url}"`);
    
        try {
            const vacation = await request.json() as Vacation;
    
            // Validate the vacation object
            if (!vacation || typeof vacation !== 'object' || !vacation.name || !vacation.description) {
                return {
                    status: 400,
                    jsonBody: { 
                        error: 'Invalid or missing vacation data.' 
                    }
                };
            }
    
            // Data access logic
            const newVacation = vacationService.addVacation(vacation); 
    
            // Successfully added the vacation
            return {
                status: 201,
                jsonBody: newVacation
            };
        } catch (error: unknown) {
            const err = error as Error;
            context.error(`Error create vacation: ${err.message}`);
    
            return {
                status: 500,
                jsonBody: {
                    error: 'Failed to create vacation'
                }
            };
        }
    }
    

    受信した休暇データを読み取るために、request.json() メソッドを使用します。 このメソッドは、要求本文の JSON データに解決される Promise を返します。 その後、await キーワードを使用して、Promise が解決されるのを待ちます。 as Vacation 構文は、結果を Vacation オブジェクトとして扱うように TypeScript に指示する型アサーションです。

    const vacation = await request.json() as Vacation;
    
  5. ルート定義を postVacation ファイルから index.ts ファイルに移動します。 メソッド プロパティ配列を POST に更新します。

    app.http('post-vacation', {
        methods: ['POST'],
        route: 'vacations',
        authLevel: 'anonymous',
        handler: postVacation
    });
    

HTTP PUT 関数を作成する

休暇の追加を処理する PUT 関数を作成します。

  1. Visual Studio Code で、Ctrl + Shift + P キーを使用してコマンド パレットを開き、Azure Functions: Create Function と入力して Enter キーを押します。

  2. 種類として [HTTP トリガー] を、名前として updateVacation を選択します。

  3. ファイルに vacationService のインポート ステートメントを追加します。

    import { vacationService } from '../services';
    
  4. 定型 updateVacation 関数を、データ アクセスとエラー処理用の次のコードに置き換えます。

    export async function updateVacation(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> {
      try {
        const id = request.params.id;
        const { name, description } = await request.json() as Vacation;
    
        // Data access logic
        const updatedVacation = vacationService.updateVacation({ id, name, description });
    
        if (updatedVacation !== undefined) {
          return {
            status: 200,
            jsonBody: {
              updatedVacation
            }
          };
        } else {
          return {
            status: 404,
            jsonBody: {
              error: `Vacation with ID ${id} not found`
            }
          };
        }
      } catch (error: unknown) {
        const err = error as Error;
        context.error(`Error updating vacation: ${err.message}`);
    
        return {
          status: 500,
          jsonBody: {
            error: 'Failed to update vacation'
          }
        };
      }
    };
    

    request.params.id プロパティは、URL から休暇 ID を取得するために使用されます。 request.json() メソッドは、要求本文から休暇データを取得するために使用されます。 as Vacation 構文は、結果を Vacation オブジェクトとして扱うように TypeScript に指示する型アサーションです。

  5. ルート定義を putVacation ファイルから index.ts ファイルに移動します。 メソッド プロパティ配列を PUT に更新します。

    app.http('updateVacation', {
        methods: ['PUT'],
        route: 'vacations/{id}',
        authLevel: 'anonymous',
        handler: updateVacation
    });
    

HTTP DELETE 関数を作成する

休暇の追加を処理する DELETE 関数を作成します。

  1. Visual Studio Code で、Ctrl + Shift + P キーを使用してコマンド パレットを開き、Azure Functions: Create Function と入力して Enter キーを押します。

  2. 種類として [HTTP トリガー] を、名前として deleteVacation を選択します。

  3. ファイルに vacationService のインポートを追加します。

    import { vacationService } from '../services';
    
  4. 定型 deleteVacation 関数を、データ アクセスとエラー処理用の次のコードに置き換えます。

    export async function deleteVacation(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> {
      context.log(`Http function processed request for url "${request.url}"`);
    
      try {
    
        const id = request.params.id;
    
        if (!id) {
          return {
            status: 400,
            jsonBody: {
              error: 'ID parameter is required'
            }
          };
        }
    
        const deletedVacation = vacationService.deleteVacation(id);
    
        if (deletedVacation) {
          return {
            status: 204,
            jsonBody: {
              deleteVacation
            }
          };
        } else {
          return {
            status: 404,
            jsonBody: {
              error: `Vacation with ID ${id} not found`
            }
          };
        }
      } catch (error: unknown) {
        const err = error as Error;
        context.error(`Error deleting vacation: ${err.message}`);
    
        return {
          status: 500,
          jsonBody: {
            error: 'Failed to delete vacation'
          }
        };
      }
    };
    

    request.params.id プロパティは、URL から休暇 ID を取得するために使用されます。

  5. ルート定義を deleteVacation ファイルから index.ts ファイルに移動します。 メソッド プロパティ配列を DELETE に更新します。

    app.http('deleteVacation', {
        methods: ['DELETE'],
        route: 'vacations/{id}',
        authLevel: 'anonymous',
        handler: deleteVacation
    });
    

次のユニットに移動して、作成した Azure Functions アプリケーションをご確認ください。